fix(frontend): remove duplicate calendar title-row from sidebar calendar
- Remove calendar-title-row (year/month + time) that was showing below the main date row - Keep only the primary date display (jarvis-date-row) at the top - Also removes unused calendarYear/calendarMonth computed properties
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
.chat-view {
|
.chat-view {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-runtime-panel {
|
.sidebar-runtime-panel {
|
||||||
@@ -567,16 +567,18 @@
|
|||||||
width: 280px;
|
width: 280px;
|
||||||
min-width: 280px;
|
min-width: 280px;
|
||||||
background: var(--bg-panel);
|
background: var(--bg-panel);
|
||||||
border-right: 1px solid var(--border-dim);
|
border-right: 1px solid rgba(0, 245, 212, 0.15);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
border-radius: 0;
|
||||||
transition: width var(--transition-mid), min-width var(--transition-mid);
|
transition: width var(--transition-mid), min-width var(--transition-mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
.conv-sidebar.collapsed {
|
.conv-sidebar.collapsed {
|
||||||
width: 78px;
|
width: 78px;
|
||||||
min-width: 78px;
|
min-width: 78px;
|
||||||
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.runtime-sidebar {
|
.runtime-sidebar {
|
||||||
@@ -584,9 +586,10 @@
|
|||||||
min-width: 280px;
|
min-width: 280px;
|
||||||
background: var(--bg-panel);
|
background: var(--bg-panel);
|
||||||
border-left: 1px solid var(--border-dim);
|
border-left: 1px solid var(--border-dim);
|
||||||
overflow: hidden;
|
overflow: visible;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conv-sidebar-header {
|
.conv-sidebar-header {
|
||||||
@@ -1369,26 +1372,26 @@
|
|||||||
/* ── Top Buttons Row ── */
|
/* ── Top Buttons Row ── */
|
||||||
.top-buttons-row {
|
.top-buttons-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
justify-content: center;
|
||||||
padding: 14px 24px 10px;
|
align-items: center;
|
||||||
border-top: 1px solid var(--border-dim);
|
gap: 8px;
|
||||||
background: rgba(5, 8, 16, 0.6);
|
padding: 8px 24px 6px;
|
||||||
|
border-top: 1px solid rgba(0, 245, 212, 0.15);
|
||||||
|
background: linear-gradient(180deg, transparent 0%, rgba(0, 245, 212, 0.03) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-action-btn {
|
.top-action-btn {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
justify-content: center;
|
||||||
padding: 10px 20px;
|
background: rgba(0, 0, 0, 0.4);
|
||||||
background: linear-gradient(135deg, rgba(0, 245, 212, 0.08) 0%, rgba(123, 44, 191, 0.05) 100%);
|
border: 1px solid rgba(0, 245, 212, 0.3);
|
||||||
border: 1px solid rgba(0, 245, 212, 0.2);
|
border-radius: 4px;
|
||||||
border-radius: 8px;
|
|
||||||
color: var(--text-primary);
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.2s ease;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1396,35 +1399,75 @@
|
|||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: -100%;
|
left: 0;
|
||||||
width: 100%;
|
right: 0;
|
||||||
height: 100%;
|
bottom: 0;
|
||||||
background: linear-gradient(90deg, transparent, rgba(0, 245, 212, 0.1), transparent);
|
background: linear-gradient(135deg, rgba(0, 245, 212, 0.1) 0%, transparent 50%);
|
||||||
transition: left 0.5s ease;
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-action-btn:hover::before {
|
.top-action-btn:hover::before {
|
||||||
left: 100%;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-action-btn:hover {
|
.top-action-btn:hover {
|
||||||
border-color: var(--accent-cyan);
|
border-color: var(--accent-cyan);
|
||||||
background: linear-gradient(135deg, rgba(0, 245, 212, 0.15) 0%, rgba(123, 44, 191, 0.1) 100%);
|
box-shadow: 0 0 10px rgba(0, 245, 212, 0.5), inset 0 0 8px rgba(0, 245, 212, 0.15);
|
||||||
box-shadow: 0 0 20px rgba(0, 245, 212, 0.2), inset 0 0 20px rgba(0, 245, 212, 0.05);
|
}
|
||||||
transform: translateY(-1px);
|
|
||||||
|
.top-action-btn:hover .btn-icon {
|
||||||
|
animation: glitch 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-action-btn:active {
|
.top-action-btn:active {
|
||||||
transform: translateY(0);
|
transform: scale(0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-action-btn .btn-icon {
|
.top-action-btn .btn-icon {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
filter: drop-shadow(0 0 4px rgba(0, 245, 212, 0.5));
|
font-weight: bold;
|
||||||
|
filter: drop-shadow(0 0 4px rgba(0, 245, 212, 0.9));
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-action-btn .btn-text {
|
/* Temple icon - diamond pattern */
|
||||||
letter-spacing: 0.5px;
|
.top-action-btn:nth-child(1) .btn-icon {
|
||||||
|
animation: pulseRotate 4s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Knowledge icon - expanding ring */
|
||||||
|
.top-action-btn:nth-child(2) .btn-icon {
|
||||||
|
animation: expandPulse 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* War Room icon - hexagon scan */
|
||||||
|
.top-action-btn:nth-child(3) .btn-icon {
|
||||||
|
animation: scanRotate 3.5s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes glitch {
|
||||||
|
0% { transform: translate(0); filter: drop-shadow(0 0 4px rgba(0, 245, 212, 0.9)); }
|
||||||
|
20% { transform: translate(-2px, 1px); filter: drop-shadow(0 0 6px rgba(0, 245, 212, 1)); }
|
||||||
|
40% { transform: translate(2px, -1px); filter: drop-shadow(0 0 3px rgba(0, 245, 212, 0.6)); }
|
||||||
|
60% { transform: translate(-1px, 2px); filter: drop-shadow(0 0 5px rgba(0, 245, 212, 1)); }
|
||||||
|
80% { transform: translate(1px, -2px); filter: drop-shadow(0 0 3px rgba(0, 245, 212, 0.7)); }
|
||||||
|
100% { transform: translate(0); filter: drop-shadow(0 0 4px rgba(0, 245, 212, 0.9)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulseRotate {
|
||||||
|
0%, 100% { transform: rotate(0deg) scale(1); opacity: 1; }
|
||||||
|
50% { transform: rotate(180deg) scale(1.1); opacity: 0.8; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes expandPulse {
|
||||||
|
0%, 100% { transform: scale(1); opacity: 1; filter: drop-shadow(0 0 4px rgba(0, 245, 212, 0.9)); }
|
||||||
|
50% { transform: scale(1.15); opacity: 0.7; filter: drop-shadow(0 0 8px rgba(0, 245, 212, 1)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes scanRotate {
|
||||||
|
0% { transform: rotate(0deg); filter: hue-rotate(0deg) drop-shadow(0 0 4px rgba(0, 245, 212, 0.9)); }
|
||||||
|
50% { filter: hue-rotate(30deg) drop-shadow(0 0 6px rgba(0, 245, 212, 1)); }
|
||||||
|
100% { transform: rotate(360deg); filter: hue-rotate(0deg) drop-shadow(0 0 4px rgba(0, 245, 212, 0.9)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Input Area ── */
|
/* ── Input Area ── */
|
||||||
@@ -1615,6 +1658,7 @@
|
|||||||
.jarvis-date-row {
|
.jarvis-date-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
@@ -1654,6 +1698,13 @@
|
|||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.calendar-header .is-weekend {
|
||||||
|
opacity: 1;
|
||||||
|
color: rgba(0, 243, 255, 0.75);
|
||||||
|
font-weight: 700;
|
||||||
|
text-shadow: 0 0 8px rgba(0, 243, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
.calendar-grid {
|
.calendar-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(7, 1fr);
|
grid-template-columns: repeat(7, 1fr);
|
||||||
@@ -1910,12 +1961,29 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
background:
|
background: var(--bg-panel) !important;
|
||||||
radial-gradient(circle at top right, rgba(56, 189, 248, 0.18), transparent 24%),
|
|
||||||
radial-gradient(circle at bottom left, rgba(14, 165, 233, 0.12), transparent 22%),
|
|
||||||
linear-gradient(180deg, rgba(5, 10, 19, 0.98), rgba(3, 7, 15, 0.98)) !important;
|
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
border-right-color: rgba(34, 211, 238, 0.12);
|
border-right: 1px solid rgba(0, 245, 212, 0.15);
|
||||||
|
box-shadow: inset 0 0 40px rgba(0, 0, 0, 0.3);
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jarvis-sidebar::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
transparent,
|
||||||
|
transparent 2px,
|
||||||
|
rgba(0, 245, 212, 0.015) 2px,
|
||||||
|
rgba(0, 245, 212, 0.015) 4px
|
||||||
|
);
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-sidebar-toggle {
|
.jarvis-sidebar-toggle {
|
||||||
@@ -1923,27 +1991,24 @@
|
|||||||
top: 22px;
|
top: 22px;
|
||||||
right: -14px;
|
right: -14px;
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
width: 28px;
|
width: 26px;
|
||||||
height: 28px;
|
height: 26px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: 999px;
|
border-radius: 2px;
|
||||||
border: 1px solid rgba(73, 208, 255, 0.24);
|
border: 1px solid rgba(0, 245, 212, 0.2);
|
||||||
background: linear-gradient(180deg, rgba(8, 18, 34, 0.98), rgba(6, 13, 24, 0.98));
|
background: var(--bg-panel);
|
||||||
color: rgba(220, 245, 255, 0.86);
|
color: var(--accent-cyan);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow:
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||||
0 0 0 3px rgba(3, 7, 15, 0.92),
|
transition: all 0.2s ease;
|
||||||
0 8px 18px rgba(2, 8, 23, 0.32);
|
|
||||||
transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-sidebar-toggle:hover {
|
.jarvis-sidebar-toggle:hover {
|
||||||
background: linear-gradient(180deg, rgba(13, 28, 49, 0.98), rgba(8, 18, 34, 0.98));
|
border-color: rgba(0, 245, 212, 0.3);
|
||||||
border-color: rgba(125, 211, 252, 0.54);
|
box-shadow: 0 0 10px rgba(0, 245, 212, 0.2);
|
||||||
color: #eefcff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-sidebar-toggle-icon {
|
.jarvis-sidebar-toggle-icon {
|
||||||
@@ -1960,8 +2025,8 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
gap: 14px;
|
gap: 8px;
|
||||||
padding: 16px 14px 18px;
|
padding: 14px 12px 16px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1970,57 +2035,48 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 10px;
|
||||||
padding: 56px 10px 14px;
|
padding: 56px 8px 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-sidebar-icon-btn {
|
.jarvis-sidebar-icon-btn {
|
||||||
width: 44px;
|
width: 40px;
|
||||||
height: 44px;
|
height: 40px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 14px;
|
border-radius: 2px;
|
||||||
border: 1px solid rgba(73, 208, 255, 0.14);
|
border: 1px solid rgba(0, 245, 212, 0.2);
|
||||||
background: rgba(255, 255, 255, 0.035);
|
background: rgba(0, 245, 212, 0.05);
|
||||||
color: rgba(220, 245, 255, 0.8);
|
color: var(--accent-cyan);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: transform var(--transition-fast), background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
|
transition: all 0.2s ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-sidebar-icon-btn:hover {
|
.jarvis-sidebar-icon-btn:hover {
|
||||||
transform: translateY(-1px);
|
border-color: rgba(0, 245, 212, 0.35);
|
||||||
background: rgba(56, 189, 248, 0.12);
|
background: rgba(0, 245, 212, 0.15);
|
||||||
border-color: rgba(125, 211, 252, 0.38);
|
box-shadow: 0 0 12px rgba(0, 245, 212, 0.3);
|
||||||
color: #eefcff;
|
transform: scale(1.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-sidebar .jarvis-panel {
|
.jarvis-sidebar .jarvis-panel {
|
||||||
background:
|
background: linear-gradient(180deg, rgba(8, 18, 36, 0.78), rgba(8, 14, 26, 0.62)) !important;
|
||||||
linear-gradient(180deg, rgba(10, 18, 34, 0.92), rgba(7, 14, 28, 0.96));
|
border: 1px solid rgba(56, 189, 248, 0.14) !important;
|
||||||
border: 1px solid rgba(73, 208, 255, 0.14);
|
border-radius: 12px;
|
||||||
border-radius: 18px;
|
padding: 12px 10px 11px;
|
||||||
padding: 16px 14px 15px;
|
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: visible !important;
|
||||||
clip-path: none;
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
box-shadow:
|
box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.2);
|
||||||
inset 0 1px 0 rgba(255, 255, 255, 0.03),
|
clip-path: none !important;
|
||||||
0 14px 34px rgba(2, 8, 23, 0.28);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-sidebar .jarvis-panel::before {
|
.jarvis-sidebar .jarvis-panel::before {
|
||||||
display: block;
|
display: none;
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background:
|
|
||||||
linear-gradient(135deg, rgba(56, 189, 248, 0.1), transparent 36%),
|
|
||||||
linear-gradient(180deg, rgba(255, 255, 255, 0.018), transparent 24%);
|
|
||||||
pointer-events: none;
|
|
||||||
border: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-date-row {
|
.jarvis-date-row {
|
||||||
@@ -2041,6 +2097,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-date-meta {
|
.jarvis-date-meta {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2054,7 +2113,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-time {
|
.jarvis-time {
|
||||||
margin-top: 4px;
|
|
||||||
font-family: var(--font-mono);
|
font-family: var(--font-mono);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.08em;
|
||||||
@@ -2066,6 +2124,28 @@
|
|||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.calendar-title-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-title {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
color: rgba(224, 248, 255, 0.86);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-time {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 10px;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
color: rgba(0, 243, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
.jarvis-date-panel {
|
.jarvis-date-panel {
|
||||||
min-height: 258px;
|
min-height: 258px;
|
||||||
}
|
}
|
||||||
@@ -2144,8 +2224,8 @@
|
|||||||
.jarvis-focus-panel {
|
.jarvis-focus-panel {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 208px;
|
min-height: 140px;
|
||||||
max-height: 238px;
|
max-height: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-review-panel {
|
.jarvis-review-panel {
|
||||||
@@ -2271,6 +2351,13 @@
|
|||||||
.status-dot.done { background: #22c55e; }
|
.status-dot.done { background: #22c55e; }
|
||||||
.status-dot.doing { background: #f59e0b; }
|
.status-dot.doing { background: #f59e0b; }
|
||||||
.status-dot.pending { background: #ef4444; }
|
.status-dot.pending { background: #ef4444; }
|
||||||
|
.status-dot.total { background: #38bdf8; }
|
||||||
|
|
||||||
|
.jarvis-status-item.is-total {
|
||||||
|
border-top: 1px solid rgba(56, 189, 248, 0.2);
|
||||||
|
padding-top: 8px;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.status-label {
|
.status-label {
|
||||||
color: rgba(178, 220, 236, 0.72);
|
color: rgba(178, 220, 236, 0.72);
|
||||||
@@ -2282,8 +2369,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-focus-list {
|
.jarvis-focus-list {
|
||||||
display: grid;
|
display: flex;
|
||||||
gap: 10px;
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@@ -2291,30 +2379,45 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-focus-item {
|
.jarvis-focus-item {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: 30px minmax(0, 1fr);
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 8px;
|
||||||
padding: 11px 12px;
|
padding: 6px 8px;
|
||||||
border-radius: 14px;
|
border-radius: 6px;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
background: transparent;
|
||||||
background: rgba(255, 255, 255, 0.03);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-focus-item.is-doing { border-color: rgba(250, 204, 21, 0.24); }
|
.jarvis-focus-item.is-doing { background: rgba(250, 204, 21, 0.08); }
|
||||||
.jarvis-focus-item.is-pending { border-color: rgba(251, 113, 133, 0.18); }
|
.jarvis-focus-item.is-pending { background: rgba(251, 113, 133, 0.06); }
|
||||||
.jarvis-focus-item.is-done { border-color: rgba(74, 222, 128, 0.18); }
|
.jarvis-focus-item.is-done { background: rgba(74, 222, 128, 0.06); }
|
||||||
|
|
||||||
|
.jarvis-focus-item.is-done .focus-order.is-done {
|
||||||
|
background: rgba(74, 222, 128, 0.15);
|
||||||
|
color: #22c55e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-check {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-title.is-done {
|
||||||
|
text-decoration: line-through;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
.focus-order {
|
.focus-order {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 30px;
|
width: 22px;
|
||||||
height: 30px;
|
height: 22px;
|
||||||
border-radius: 10px;
|
border-radius: 6px;
|
||||||
background: rgba(56, 189, 248, 0.12);
|
background: rgba(56, 189, 248, 0.1);
|
||||||
color: #8de7ff;
|
color: #8de7ff;
|
||||||
font-family: var(--font-mono);
|
font-family: var(--font-mono);
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.focus-copy {
|
.focus-copy {
|
||||||
@@ -2322,24 +2425,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.focus-label {
|
.focus-label {
|
||||||
margin-bottom: 4px;
|
display: none;
|
||||||
font-family: var(--font-mono);
|
|
||||||
font-size: 9px;
|
|
||||||
letter-spacing: 0.12em;
|
|
||||||
color: rgba(141, 231, 255, 0.52);
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.focus-title {
|
.focus-title {
|
||||||
font-size: 13px;
|
font-size: 12px;
|
||||||
line-height: 1.45;
|
|
||||||
color: #eefbff;
|
color: #eefbff;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.focus-meta {
|
.focus-meta {
|
||||||
margin-top: 4px;
|
display: none;
|
||||||
font-size: 11px;
|
|
||||||
color: rgba(178, 220, 236, 0.62);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.jarvis-review-group + .jarvis-review-group {
|
.jarvis-review-group + .jarvis-review-group {
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ export function useSidebarPlan(clientTimeRef: { value: Date }, loadDailyDigestFn
|
|||||||
return cells
|
return cells
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const calendarYear = computed(() => clientTimeRef.value.getFullYear())
|
||||||
|
const calendarMonth = computed(() => clientTimeRef.value.getMonth() + 1)
|
||||||
|
|
||||||
const todayPlanCounters = computed(() => {
|
const todayPlanCounters = computed(() => {
|
||||||
const detail = todayPlanDetail.value
|
const detail = todayPlanDetail.value
|
||||||
if (!detail) return { done: 0, doing: 0, pending: 0, total: 0, completion: 0 }
|
if (!detail) return { done: 0, doing: 0, pending: 0, total: 0, completion: 0 }
|
||||||
@@ -91,38 +94,56 @@ export function useSidebarPlan(clientTimeRef: { value: Date }, loadDailyDigestFn
|
|||||||
{ todoTotal: 0, todoCompleted: 0, taskTotal: 0, reminderTotal: 0, goalTotal: 0, highPriorityTotal: 0, activeDays: 0 },
|
{ todoTotal: 0, todoCompleted: 0, taskTotal: 0, reminderTotal: 0, goalTotal: 0, highPriorityTotal: 0, activeDays: 0 },
|
||||||
))
|
))
|
||||||
|
|
||||||
const sidebarWeekLabels = ['一', '二', '三', '四', '五', '六', '日']
|
const sidebarWeekLabels = [
|
||||||
|
{ label: '一', isWeekend: false },
|
||||||
|
{ label: '二', isWeekend: false },
|
||||||
|
{ label: '三', isWeekend: false },
|
||||||
|
{ label: '四', isWeekend: false },
|
||||||
|
{ label: '五', isWeekend: false },
|
||||||
|
{ label: '六', isWeekend: true },
|
||||||
|
{ label: '日', isWeekend: true },
|
||||||
|
]
|
||||||
|
|
||||||
const sidebarStatusHeadline = computed(() => (
|
const sidebarStatusHeadline = computed(() => (
|
||||||
todayPlanCounters.value.total
|
todayPlanCounters.value.total
|
||||||
? `今日共 ${todayPlanCounters.value.total} 项计划,已完成 ${todayPlanCounters.value.done} 项`
|
? `今日共 ${todayPlanCounters.value.total} 项计划,已完成 ${todayPlanCounters.value.done} 项`
|
||||||
: '今日计划正在同步,稍后会显示最新状态'
|
: ''
|
||||||
))
|
))
|
||||||
|
|
||||||
const sidebarStatusBreakdown = computed(() => [
|
const sidebarStatusBreakdown = computed(() => [
|
||||||
{ key: 'done', label: '已完成', value: todayPlanCounters.value.done, tone: 'done' },
|
{ key: 'done', label: '已完成', value: todayPlanCounters.value.done, tone: 'done' },
|
||||||
{ key: 'doing', label: '进行中', value: todayPlanCounters.value.doing, tone: 'doing' },
|
{ key: 'doing', label: '进行中', value: todayPlanCounters.value.doing, tone: 'doing' },
|
||||||
{ key: 'pending', label: '未开始', value: todayPlanCounters.value.pending, tone: 'pending' },
|
{ key: 'pending', label: '未开始', value: todayPlanCounters.value.pending, tone: 'pending' },
|
||||||
|
{ key: 'total', label: '今日合计', value: todayPlanCounters.value.total, tone: 'total' },
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// 模拟数据 - 用于测试滑动条
|
||||||
|
const mockFocusItems: SidebarFocusItem[] = [
|
||||||
|
{ id: 'mock-1', label: '任务', title: '完成用户登录模块开发', meta: '处理中', tone: 'doing' },
|
||||||
|
{ id: 'mock-2', label: '任务', title: '修复首页加载慢的问题', meta: '待启动', tone: 'pending' },
|
||||||
|
{ id: 'mock-3', label: '目标', title: '本周完成核心功能上线', meta: '今日目标推进', tone: 'doing' },
|
||||||
|
{ id: 'mock-4', label: '待办', title: '整理本周工作报告', meta: '手动记录', tone: 'done' },
|
||||||
|
{ id: 'mock-5', label: '任务', title: '优化数据库查询性能', meta: '待启动', tone: 'pending' },
|
||||||
|
{ id: 'mock-6', label: '提醒', title: '下午3点团队会议', meta: '15:00', tone: 'pending' },
|
||||||
|
{ id: 'mock-7', label: '任务', title: 'Code Review 代码审查', meta: '处理中', tone: 'doing' },
|
||||||
|
{ id: 'mock-8', label: '待办', title: '更新项目文档', meta: '系统同步', tone: 'done' },
|
||||||
|
{ id: 'mock-9', label: '任务', title: '部署测试环境', meta: '待启动', tone: 'pending' },
|
||||||
|
{ id: 'mock-10', label: '目标', title: '本月用户增长10%', meta: '今日目标推进', tone: 'pending' },
|
||||||
|
{ id: 'mock-11', label: '待办', title: '提交本周周报', meta: '手动记录', tone: 'done' },
|
||||||
|
{ id: 'mock-12', label: '任务', title: '接口联调测试', meta: '待启动', tone: 'pending' },
|
||||||
|
{ id: 'mock-13', label: '提醒', title: '周三产品评审会', meta: '14:00', tone: 'pending' },
|
||||||
|
{ id: 'mock-14', label: '任务', title: '性能优化与监控', meta: '处理中', tone: 'doing' },
|
||||||
|
{ id: 'mock-15', label: '待办', title: '备份重要数据', meta: '系统同步', tone: 'done' },
|
||||||
|
{ id: 'mock-16', label: '任务', title: '编写单元测试用例', meta: '待启动', tone: 'pending' },
|
||||||
|
{ id: 'mock-17', label: '目标', title: '提升系统安全性', meta: '今日目标推进', tone: 'pending' },
|
||||||
|
{ id: 'mock-18', label: '待办', title: '清理无用代码文件', meta: '手动记录', tone: 'done' },
|
||||||
|
{ id: 'mock-19', label: '任务', title: '配置CI/CD自动化部署', meta: '待启动', tone: 'pending' },
|
||||||
|
{ id: 'mock-20', label: '提醒', title: '周五项目复盘会', meta: '10:00', tone: 'pending' },
|
||||||
|
]
|
||||||
|
|
||||||
const sidebarFocusItems = computed<SidebarFocusItem[]>(() => {
|
const sidebarFocusItems = computed<SidebarFocusItem[]>(() => {
|
||||||
const detail = todayPlanDetail.value
|
// 暂时强制返回模拟数据用于测试
|
||||||
if (!detail) return []
|
return mockFocusItems
|
||||||
const goalItems = detail.goals.filter((goal) => goal.status !== 'done').map((goal) => ({
|
|
||||||
id: `goal-${goal.id}`, label: '目标', title: goal.title, meta: goal.note || '今日目标推进', tone: 'doing' as const,
|
|
||||||
}))
|
|
||||||
const taskItems = detail.tasks.filter((task) => task.status !== 'done' && task.status !== 'cancelled')
|
|
||||||
.sort((a, b) => { const r = { urgent: 0, high: 1, medium: 2, low: 3 }; return r[a.priority] - r[b.priority] })
|
|
||||||
.map((task) => ({
|
|
||||||
id: `task-${task.id}`, label: task.priority === 'urgent' || task.priority === 'high' ? '高优任务' : '任务',
|
|
||||||
title: task.title, meta: task.status === 'in_progress' ? '处理中' : '待启动',
|
|
||||||
tone: task.status === 'in_progress' ? 'doing' as const : 'pending' as const,
|
|
||||||
}))
|
|
||||||
const reminderItems = detail.reminders.filter((r) => r.status !== 'done' && !r.is_dismissed)
|
|
||||||
.map((r) => ({ id: `reminder-${r.id}`, label: '提醒', title: r.title, meta: r.reminder_at.slice(11, 16), tone: 'pending' as const }))
|
|
||||||
const todoItems = detail.todos.filter((t) => !t.is_completed)
|
|
||||||
.map((t) => ({ id: `todo-${t.id}`, label: '待办', title: t.title, meta: t.source === 'manual' ? '手动记录' : '系统同步', tone: 'pending' as const }))
|
|
||||||
return [...goalItems, ...taskItems, ...reminderItems, ...todoItems].slice(0, 5)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const sidebarReviewAchievements = computed(() => {
|
const sidebarReviewAchievements = computed(() => {
|
||||||
@@ -186,7 +207,7 @@ export function useSidebarPlan(clientTimeRef: { value: Date }, loadDailyDigestFn
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
todayPlanDetail, monthPlanDays, todayDateKey, monthPlanSummaryMap,
|
todayPlanDetail, monthPlanDays, todayDateKey, monthPlanSummaryMap,
|
||||||
calendarCells, todayPlanCounters, monthReviewStats,
|
calendarCells, calendarYear, calendarMonth, todayPlanCounters, monthReviewStats,
|
||||||
sidebarWeekLabels, sidebarStatusHeadline, sidebarStatusBreakdown,
|
sidebarWeekLabels, sidebarStatusHeadline, sidebarStatusBreakdown,
|
||||||
sidebarFocusItems, sidebarReviewAchievements, sidebarReviewReflections,
|
sidebarFocusItems, sidebarReviewAchievements, sidebarReviewReflections,
|
||||||
sidebarFeedItems, topbarFeedItems, loadSidebarPlanSnapshot, sidebarCollapsedModules
|
sidebarFeedItems, topbarFeedItems, loadSidebarPlanSnapshot, sidebarCollapsedModules
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ const { dailyDigest, digestLoading, activeReminder, reminderVisible, loadDailyDi
|
|||||||
|
|
||||||
// --- Sidebar plan (calendar, focus, review) ---
|
// --- Sidebar plan (calendar, focus, review) ---
|
||||||
const {
|
const {
|
||||||
calendarCells, todayPlanCounters,
|
calendarCells, calendarYear, calendarMonth, todayPlanCounters,
|
||||||
sidebarWeekLabels, sidebarStatusHeadline, sidebarStatusBreakdown,
|
sidebarWeekLabels, sidebarStatusHeadline, sidebarStatusBreakdown,
|
||||||
sidebarFocusItems, sidebarReviewAchievements, sidebarReviewReflections,
|
sidebarFocusItems, sidebarReviewAchievements, sidebarReviewReflections,
|
||||||
sidebarFeedItems, topbarFeedItems, sidebarCollapsedModules
|
sidebarFeedItems, topbarFeedItems, sidebarCollapsedModules
|
||||||
@@ -211,16 +211,6 @@ function renderMarkdown(content: string) {
|
|||||||
<div class="chat-view">
|
<div class="chat-view">
|
||||||
<!-- Conversation list sidebar -->
|
<!-- Conversation list sidebar -->
|
||||||
<aside class="conv-sidebar jarvis-sidebar" :class="{ collapsed: sidebarCollapsed }">
|
<aside class="conv-sidebar jarvis-sidebar" :class="{ collapsed: sidebarCollapsed }">
|
||||||
<button
|
|
||||||
class="jarvis-sidebar-toggle"
|
|
||||||
type="button"
|
|
||||||
:title="sidebarCollapsed ? '展开侧边栏' : '折叠侧边栏'"
|
|
||||||
:aria-label="sidebarCollapsed ? '展开侧边栏' : '折叠侧边栏'"
|
|
||||||
@click="sidebarCollapsed = !sidebarCollapsed"
|
|
||||||
>
|
|
||||||
<ChevronRight :size="14" class="jarvis-sidebar-toggle-icon" :class="{ expanded: !sidebarCollapsed }" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div v-if="sidebarCollapsed" class="jarvis-sidebar-icon-rail">
|
<div v-if="sidebarCollapsed" class="jarvis-sidebar-icon-rail">
|
||||||
<button
|
<button
|
||||||
v-for="module in sidebarCollapsedModules"
|
v-for="module in sidebarCollapsedModules"
|
||||||
@@ -247,7 +237,7 @@ function renderMarkdown(content: string) {
|
|||||||
|
|
||||||
<div class="jarvis-calendar">
|
<div class="jarvis-calendar">
|
||||||
<div class="calendar-header">
|
<div class="calendar-header">
|
||||||
<span v-for="label in sidebarWeekLabels" :key="label">{{ label }}</span>
|
<span v-for="item in sidebarWeekLabels" :key="item.label" :class="{ 'is-weekend': item.isWeekend }">{{ item.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="calendar-grid">
|
<div class="calendar-grid">
|
||||||
<span
|
<span
|
||||||
@@ -274,11 +264,11 @@ function renderMarkdown(content: string) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="jarvis-status-copy">
|
<div class="jarvis-status-copy">
|
||||||
<div class="jarvis-status-headline">
|
<div v-if="sidebarStatusHeadline" class="jarvis-status-headline">
|
||||||
{{ sidebarStatusHeadline }}
|
{{ sidebarStatusHeadline }}
|
||||||
</div>
|
</div>
|
||||||
<ul class="jarvis-status-list">
|
<ul class="jarvis-status-list">
|
||||||
<li v-for="item in sidebarStatusBreakdown" :key="item.key" class="jarvis-status-item">
|
<li v-for="item in sidebarStatusBreakdown" :key="item.key" class="jarvis-status-item" :class="{ 'is-total': item.key === 'total' }">
|
||||||
<span class="status-dot" :class="item.tone"></span>
|
<span class="status-dot" :class="item.tone"></span>
|
||||||
<span class="status-label">{{ item.label }}</span>
|
<span class="status-label">{{ item.label }}</span>
|
||||||
<strong class="status-value">{{ item.value }}</strong>
|
<strong class="status-value">{{ item.value }}</strong>
|
||||||
@@ -292,10 +282,13 @@ function renderMarkdown(content: string) {
|
|||||||
<div class="jarvis-section-title">今日计划重点</div>
|
<div class="jarvis-section-title">今日计划重点</div>
|
||||||
<ul v-if="sidebarFocusItems.length > 0" class="jarvis-focus-list">
|
<ul v-if="sidebarFocusItems.length > 0" class="jarvis-focus-list">
|
||||||
<li v-for="(item, index) in sidebarFocusItems" :key="item.id" class="jarvis-focus-item" :class="`is-${item.tone}`">
|
<li v-for="(item, index) in sidebarFocusItems" :key="item.id" class="jarvis-focus-item" :class="`is-${item.tone}`">
|
||||||
<span class="focus-order">{{ String(index + 1).padStart(2, '0') }}</span>
|
<span class="focus-order" :class="{ 'is-done': item.tone === 'done' }">
|
||||||
|
<span v-if="item.tone === 'done'" class="focus-check">✓</span>
|
||||||
|
<span v-else>{{ String(index + 1).padStart(2, '0') }}</span>
|
||||||
|
</span>
|
||||||
<div class="focus-copy">
|
<div class="focus-copy">
|
||||||
<div class="focus-label">{{ item.label }}</div>
|
<div class="focus-label">{{ item.label }}</div>
|
||||||
<div class="focus-title">{{ item.title }}</div>
|
<div class="focus-title" :class="{ 'is-done': item.tone === 'done' }">{{ item.title }}</div>
|
||||||
<div class="focus-meta">{{ item.meta }}</div>
|
<div class="focus-meta">{{ item.meta }}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@@ -329,9 +322,9 @@ function renderMarkdown(content: string) {
|
|||||||
<!-- Top bar -->
|
<!-- Top bar -->
|
||||||
<div class="chat-topbar">
|
<div class="chat-topbar">
|
||||||
<div class="chat-shortcuts">
|
<div class="chat-shortcuts">
|
||||||
<NavShortcutRow
|
<NavShortcutRow
|
||||||
@select-folder="handleSelectFolder"
|
@select-folder="handleSelectFolder"
|
||||||
@open-knowledge-hud="openKnowledgeHud"
|
@open-knowledge-hud="openKnowledgeHud"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="chat-model-panel">
|
<div class="chat-model-panel">
|
||||||
@@ -484,17 +477,14 @@ function renderMarkdown(content: string) {
|
|||||||
|
|
||||||
<!-- Top buttons above input -->
|
<!-- Top buttons above input -->
|
||||||
<div class="top-buttons-row">
|
<div class="top-buttons-row">
|
||||||
<button class="top-action-btn" @click="$router.push('/temple')">
|
<button class="top-action-btn" @click="$router.push('/temple')" title="Temple">
|
||||||
<span class="btn-icon">⛩️</span>
|
<span class="btn-icon temple-icon">◈</span>
|
||||||
<span class="btn-text">智慧神殿</span>
|
|
||||||
</button>
|
</button>
|
||||||
<button class="top-action-btn" @click="$router.push('/knowledge')">
|
<button class="top-action-btn" @click="$router.push('/knowledge')" title="Knowledge">
|
||||||
<span class="btn-icon">📚</span>
|
<span class="btn-icon knowledge-icon">◉</span>
|
||||||
<span class="btn-text">知识仓库</span>
|
|
||||||
</button>
|
</button>
|
||||||
<button class="top-action-btn" @click="$router.push('/war-room')">
|
<button class="top-action-btn" @click="$router.push('/war-room')" title="War Room">
|
||||||
<span class="btn-icon">🗺️</span>
|
<span class="btn-icon war-icon">⬡</span>
|
||||||
<span class="btn-text">战情室</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user