feat(clerk): add dedicated nav pages, state restore, and fullscreen ESC fix

- Add ClerkUiStateService with full account state save/restore (no double network call on back navigation)
- Add Photo & Signature, Standing Instructions, Today's Activity as dedicated nav pages
- Remove photo/signature, standing instructions, linked accounts, today's activity panels from main dashboard
- Add ESC key to exit fullscreen; clicking Clerk nav immediately restores fullscreen without re-navigating
- Compact clerk dashboard UI with reduced font sizes and padding throughout
- Add CashierOnlyGuard for route protection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jaanu423
2026-06-09 12:49:06 +05:30
co-authored by Claude Sonnet 4.6
parent f7d9259eb7
commit 40a436dabe
20 changed files with 3708 additions and 1020 deletions
@@ -8,10 +8,9 @@
:host {
display: block;
min-height: 100vh;
background: #f0f2f5;
font-family: Inter, Roboto, sans-serif;
font-size: 13px;
font-size: 12px;
}
// ── Root wrapper ──────────────────────────────────────────────────────────────
@@ -19,8 +18,8 @@
.te-root {
display: flex;
flex-direction: column;
gap: 10px;
padding: 10px 14px;
gap: 6px;
padding: 6px 10px;
}
// ── Day-status blocking banners ───────────────────────────────────────────────
@@ -60,6 +59,223 @@
}
}
// ── Cashier compact account info strip ───────────────────────────────────────
.te-acs {
display: flex;
align-items: center;
background: #fff;
border: 1px solid #dce4ef;
border-radius: 8px;
overflow: hidden;
min-height: 44px;
}
.te-acs-id {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
flex-shrink: 0;
}
.te-acs-photo {
width: 30px;
height: 30px;
border-radius: 50%;
object-fit: cover;
flex-shrink: 0;
border: 2px solid #dce4ef;
&--ph {
background: #f0f4f9;
display: flex;
align-items: center;
justify-content: center;
}
&--clickable {
cursor: zoom-in;
transition:
border-color 0.15s,
box-shadow 0.15s;
&:hover {
border-color: #2563eb;
box-shadow: 0 0 0 3px rgb(37 99 235 / 18%);
}
}
}
.te-acs-nameblock {
display: flex;
flex-direction: column;
gap: 1px;
}
.te-acs-name {
font-size: 12px;
font-weight: 700;
color: #0d1b2e;
white-space: nowrap;
}
.te-acs-acno {
font-size: 10px;
font-family: 'Roboto Mono', monospace;
color: #5a7089;
letter-spacing: 0.4px;
}
.te-acs-sep {
width: 1px;
align-self: stretch;
background: #dce4ef;
flex-shrink: 0;
}
.te-acs-meta {
display: flex;
align-items: center;
gap: 6px;
padding: 0 10px;
flex-shrink: 0;
}
.te-acs-tag {
display: inline-flex;
align-items: center;
height: 20px;
padding: 0 7px;
border-radius: 10px;
font-size: 10px;
font-weight: 700;
background: #f0fdf4;
color: #16a34a;
border: 1px solid #bbf7d0;
&--blocked {
background: #fef2f2;
color: #dc2626;
border-color: #fecaca;
}
&--dormant {
background: #fffbeb;
color: #d97706;
border-color: #fde68a;
}
}
.te-acs-kv {
font-size: 11px;
color: #4a607a;
white-space: nowrap;
b {
font-size: 9px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.4px;
color: #8aa0b8;
margin-right: 2px;
}
}
.te-acs-bals {
display: flex;
align-items: stretch;
flex: 1;
}
.te-acs-b {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
padding: 5px 10px;
border-right: 1px solid #f0f4f9;
gap: 1px;
&:last-child {
border-right: none;
}
&--main {
background: #f8fbff;
}
&--after {
background: #f0fdf6;
}
}
.te-acs-b-l {
font-size: 9px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
color: #8aa0b8;
white-space: nowrap;
}
.te-acs-b-v {
font-size: 11.5px;
font-weight: 700;
color: #1a2a3e;
font-variant-numeric: tabular-nums;
white-space: nowrap;
&--cr {
color: #059669;
}
}
.te-acs-alerts {
display: flex;
align-items: center;
gap: 4px;
padding: 0 10px;
flex-shrink: 0;
}
.te-acs-alert {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 10px;
font-weight: 600;
border-radius: 4px;
padding: 3px 7px;
&--danger {
background: #fef2f2;
color: #991b1b;
svg {
stroke: #dc2626;
}
}
&--warning {
background: #fffbeb;
color: #92400e;
svg {
stroke: #d97706;
}
}
&--info {
background: #eff6ff;
color: #1e40af;
svg {
stroke: #3b82f6;
}
}
}
// ── CBS Blue Transaction Entry ────────────────────────────────────────────────
$ws-ink: #0d1b2e; // nav bar dark navy
@@ -80,11 +296,11 @@ $ws-fld-bd: #c8d8eb;
.ws-wrap {
background: $ws-canvas;
border-radius: 12px;
border-radius: 10px;
overflow: hidden;
box-shadow:
0 1px 3px rgb(13 27 46 / 8%),
0 8px 24px -10px rgb(13 27 46 / 18%);
0 1px 3px rgb(13 27 46 / 6%),
0 4px 14px -8px rgb(13 27 46 / 14%);
border: 1px solid $ws-border;
font-family: 'Hanken Grotesk', Inter, sans-serif;
}
@@ -94,27 +310,27 @@ $ws-fld-bd: #c8d8eb;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 18px;
height: 48px;
padding: 0 12px;
height: 32px;
background: linear-gradient(90deg, #0d1b2e 0%, #162542 100%);
border-bottom: 2px solid $ws-accent;
&__left {
display: flex;
align-items: center;
gap: 10px;
gap: 8px;
}
&__right {
display: flex;
align-items: center;
gap: 14px;
gap: 10px;
}
&__icon {
width: 28px;
height: 28px;
border-radius: 7px;
width: 22px;
height: 22px;
border-radius: 6px;
background: $ws-accent;
display: flex;
align-items: center;
@@ -122,12 +338,14 @@ $ws-fld-bd: #c8d8eb;
svg {
stroke: #fff;
width: 12px;
height: 12px;
}
}
&__title {
font-family: Newsreader, Georgia, serif;
font-size: 16px;
font-size: 14px;
font-weight: 500;
color: #e8f0fb;
letter-spacing: 0.01em;
@@ -136,8 +354,8 @@ $ws-fld-bd: #c8d8eb;
&__effdt {
display: flex;
align-items: center;
gap: 7px;
font-size: 11.5px;
gap: 6px;
font-size: 11px;
color: #7a95b0;
svg {
@@ -146,14 +364,14 @@ $ws-fld-bd: #c8d8eb;
}
&__date {
height: 28px;
padding: 0 10px;
height: 24px;
padding: 0 8px;
border: 1px solid #2a4060;
border-radius: 6px;
border-radius: 5px;
background: #0a1628;
color: #e8f0fb;
font-family: 'Hanken Grotesk', monospace;
font-size: 12px;
font-size: 11px;
font-weight: 600;
outline: none;
@@ -166,9 +384,9 @@ $ws-fld-bd: #c8d8eb;
.ws-btn {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 7px 15px;
border-radius: 8px;
gap: 4px;
padding: 5px 12px;
border-radius: 7px;
border: none;
font-family: 'Hanken Grotesk', sans-serif;
font-size: 12px;
@@ -243,7 +461,7 @@ $ws-fld-bd: #c8d8eb;
background: $ws-accent;
color: #fff;
font-weight: 700;
padding: 8px 20px;
padding: 6px 16px;
box-shadow: 0 2px 8px rgb(232 119 34 / 30%);
&:hover:not(:disabled) {
@@ -259,20 +477,20 @@ $ws-fld-bd: #c8d8eb;
// ── Row cards ────────────────────────────────────────────────────────────────
.ws-rows {
padding: 12px 14px;
padding: 8px 10px;
display: flex;
flex-direction: column;
gap: 10px;
gap: 6px;
}
.ws-card {
display: flex;
align-items: flex-start;
gap: 10px;
gap: 6px;
background: $ws-card;
border: 1px solid $ws-border;
border-radius: 12px;
padding: 12px 14px 12px 10px;
border-radius: 10px;
padding: 6px 8px;
cursor: pointer;
transition:
border-color 0.15s,
@@ -293,17 +511,17 @@ $ws-fld-bd: #c8d8eb;
&__badge {
flex-shrink: 0;
width: 26px;
height: 26px;
width: 22px;
height: 22px;
border-radius: 50%;
background: $ws-ink;
color: #c8daf0;
font-size: 11px;
font-size: 10px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
margin-top: 22px;
margin-top: 16px;
}
&__body {
@@ -354,7 +572,7 @@ $ws-fld-bd: #c8d8eb;
gap: 0;
&--mt {
margin-top: 10px;
margin-top: 6px;
}
}
@@ -372,7 +590,7 @@ $ws-fld-bd: #c8d8eb;
&__fields {
display: flex;
align-items: flex-end;
gap: 8px;
gap: 6px;
flex-wrap: nowrap;
height: 100%;
align-content: flex-end;
@@ -390,7 +608,7 @@ $ws-fld-bd: #c8d8eb;
.ws-vdivider {
width: 1px;
background: $ws-divider;
margin: 18px 10px 0;
margin: 12px 8px 0;
flex-shrink: 0;
}
@@ -471,14 +689,14 @@ $ws-fld-bd: #c8d8eb;
}
&__ctl {
height: 34px;
padding: 0 9px;
height: 26px;
padding: 0 7px;
border: 1px solid $ws-fld-bd;
border-radius: 8px;
border-radius: 6px;
background: $ws-fld-bg;
color: $ws-text;
font-family: 'Hanken Grotesk', sans-serif;
font-size: 13px;
font-size: 11.5px;
outline: none;
width: 100%;
transition:
@@ -523,9 +741,9 @@ select.ws-f__ctl {
display: flex;
align-items: center;
border: 1px solid $ws-fld-bd;
border-radius: 8px;
border-radius: 7px;
background: $ws-fld-bg;
height: 34px;
height: 30px;
transition:
border-color 0.15s,
box-shadow 0.15s;
@@ -553,8 +771,8 @@ select.ws-f__ctl {
}
.ws-amt-prefix {
padding: 0 6px 0 9px;
font-size: 13px;
padding: 0 5px 0 8px;
font-size: 12px;
color: $ws-muted;
font-weight: 600;
flex-shrink: 0;
@@ -566,10 +784,10 @@ select.ws-f__ctl {
border: none;
background: transparent;
font-family: 'Hanken Grotesk', monospace;
font-size: 13px;
font-size: 12px;
font-weight: 600;
text-align: right;
padding-right: 9px;
padding-right: 8px;
color: $ws-text;
outline: none;
font-variant-numeric: tabular-nums;
@@ -578,8 +796,8 @@ select.ws-f__ctl {
// ── Segmented DR/CR toggle ───────────────────────────────────────────────────
.ws-seg {
display: flex;
height: 34px;
border-radius: 8px;
height: 30px;
border-radius: 7px;
overflow: hidden;
border: 1px solid $ws-fld-bd;
@@ -624,7 +842,7 @@ select.ws-f__ctl {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 18px;
padding: 7px 14px;
background: linear-gradient(180deg, #f4f7fc, #edf2f9);
border-top: 1px solid $ws-divider;
@@ -903,24 +1121,50 @@ select.te-cell {
// ── Status messages ──────────────────────────────────────────────────────────
.te-loading {
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
padding: 14px 16px;
background: #fff;
border: 1px solid #e2e8f0;
border-radius: 10px;
color: #64748b;
font-size: 13px;
justify-content: center;
gap: 14px;
background: rgb(241 245 249 / 88%);
backdrop-filter: blur(6px);
z-index: 999;
&::before {
content: '';
width: 16px;
height: 16px;
border: 2px solid #e2e8f0;
border-top-color: #3b82f6;
&__spinner {
position: relative;
width: 56px;
height: 56px;
svg {
animation: te-spin 1s linear infinite;
}
}
&__arc {
transform-origin: 28px 28px;
}
&__pulse {
position: absolute;
inset: 6px;
border-radius: 50%;
animation: te-spin 0.7s linear infinite;
background: radial-gradient(circle, rgb(37 99 235 / 12%), transparent 70%);
animation: te-pulse 1.4s ease-in-out infinite;
}
&__title {
font-size: 15px;
font-weight: 700;
color: #1e293b;
letter-spacing: -0.01em;
}
&__sub {
font-size: 12.5px;
color: #94a3b8;
margin-top: -6px;
}
}
@@ -930,6 +1174,19 @@ select.te-cell {
}
}
@keyframes te-pulse {
0%,
100% {
opacity: 0.4;
transform: scale(0.9);
}
50% {
opacity: 1;
transform: scale(1.1);
}
}
.te-error {
padding: 10px 16px;
background: #fef2f2;
@@ -945,13 +1202,13 @@ select.te-cell {
.te-detail {
display: flex;
flex-direction: column;
gap: 10px;
gap: 5px;
}
.te-detail-top {
display: grid;
grid-template-columns: 1.1fr 0.9fr 1.1fr;
gap: 10px;
gap: 7px;
@media (width <= 1100px) {
grid-template-columns: 1fr 1fr;
@@ -974,11 +1231,11 @@ select.te-cell {
&__header {
display: flex;
align-items: center;
gap: 8px;
padding: 9px 14px;
gap: 5px;
padding: 4px 8px;
background: linear-gradient(135deg, #1e293b, #334155);
color: #e2e8f0;
font-size: 11px;
font-size: 9.5px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
@@ -991,13 +1248,13 @@ select.te-cell {
}
&__body {
padding: 10px 14px;
padding: 4px 8px;
&--center {
display: flex;
align-items: center;
justify-content: center;
min-height: 60px;
min-height: 32px;
}
}
}
@@ -1007,11 +1264,11 @@ select.te-cell {
.te-field {
display: flex;
align-items: flex-start;
gap: 6px;
margin-bottom: 5px;
font-size: 12px;
gap: 5px;
margin-bottom: 3px;
font-size: 11px;
border-bottom: 1px dotted #f1f5f9;
padding-bottom: 4px;
padding-bottom: 3px;
&:last-child {
border-bottom: none;
@@ -1021,7 +1278,7 @@ select.te-cell {
.te-field-row {
display: flex;
gap: 10px;
gap: 8px;
.te-field {
flex: 1;
@@ -1029,9 +1286,9 @@ select.te-cell {
}
.te-label {
min-width: 88px;
min-width: 76px;
color: #64748b;
font-size: 11px;
font-size: 10.5px;
font-weight: 600;
white-space: nowrap;
padding-top: 1px;
@@ -1039,14 +1296,14 @@ select.te-cell {
.te-value {
color: #1e293b;
font-size: 12px;
font-size: 11px;
font-weight: 500;
flex: 1;
&-name {
font-weight: 700;
color: #0f172a;
font-size: 13px;
font-size: 12px;
}
&-wrap {
@@ -1069,10 +1326,10 @@ select.te-cell {
.te-joint-row {
display: flex;
align-items: center;
gap: 8px;
padding: 7px 8px;
gap: 6px;
padding: 5px 6px;
border-bottom: 1px solid #f1f5f9;
font-size: 12px;
font-size: 11px;
border-radius: 6px;
margin-bottom: 2px;
@@ -1225,9 +1482,9 @@ select.te-cell {
display: flex;
align-items: center;
justify-content: space-between;
padding: 5px 0;
padding: 3px 0;
border-bottom: 1px dotted #f1f5f9;
font-size: 12px;
font-size: 11px;
&:last-child {
border-bottom: none;
@@ -1252,7 +1509,7 @@ select.te-cell {
.te-bal-label {
flex: 1;
color: #475569;
font-size: 12px;
font-size: 11px;
}
.te-bal-value {
@@ -1288,8 +1545,8 @@ select.te-cell {
.te-bal-item {
display: flex;
align-items: center;
gap: 6px;
padding: 10px 18px;
gap: 5px;
padding: 7px 14px;
border-right: 1px solid #e2e8f0;
&:last-child {
@@ -1312,7 +1569,7 @@ select.te-cell {
&__val {
font-weight: 800;
font-size: 13px;
font-size: 12px;
color: #1e293b;
font-variant-numeric: tabular-nums;
letter-spacing: 0.01em;
@@ -1322,7 +1579,7 @@ select.te-cell {
}
&--big {
font-size: 16px;
font-size: 14px;
}
}
}
@@ -2246,7 +2503,7 @@ select.te-cell {
.te-denom-wrap {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
gap: 6px;
@media (width <= 1100px) {
grid-template-columns: 1fr 1fr;
@@ -2260,16 +2517,16 @@ select.te-cell {
.te-denom-table {
width: 100%;
border-collapse: collapse;
font-size: 12px;
font-size: 11px;
th {
background: #f1f5f9;
color: #64748b;
font-size: 10px;
font-size: 9.5px;
font-weight: 700;
letter-spacing: 0.05em;
text-transform: uppercase;
padding: 5px 10px;
padding: 3px 8px;
border-bottom: 1px solid #e2e8f0;
text-align: left;
@@ -2279,10 +2536,10 @@ select.te-cell {
}
td {
padding: 5px 10px;
padding: 2px 8px;
border-bottom: 1px solid #f8fafc;
color: #1e293b;
font-size: 12px;
font-size: 11px;
&.num {
text-align: right;
@@ -2301,8 +2558,8 @@ select.te-cell {
tfoot td {
background: #f1f5f9;
border-top: 2px solid #e2e8f0;
font-size: 12px;
padding: 6px 10px;
font-size: 11px;
padding: 4px 8px;
}
}
@@ -2349,11 +2606,11 @@ select.te-cell {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 48px;
height: 24px;
padding: 0 8px;
border-radius: 6px;
font-size: 12px;
min-width: 36px;
height: 20px;
padding: 0 6px;
border-radius: 5px;
font-size: 11px;
font-weight: 700;
background: linear-gradient(135deg, #ecfeff, #cffafe);
color: #155e75;
@@ -2361,10 +2618,11 @@ select.te-cell {
&--coin {
border-radius: 50%;
width: 32px;
height: 32px;
min-width: 32px;
width: 24px;
height: 24px;
min-width: 24px;
padding: 0;
font-size: 10px;
background: linear-gradient(135deg, #fef9c3, #fde68a);
color: #854d0e;
border-color: #fcd34d;
@@ -2374,16 +2632,16 @@ select.te-cell {
.te-denom-stepper {
display: inline-flex;
align-items: center;
gap: 6px;
gap: 4px;
margin-left: auto;
button {
width: 28px;
height: 28px;
width: 22px;
height: 22px;
border-radius: 50%;
border: 1.5px solid #e2e8f0;
background: #f8fafc;
font-size: 16px;
font-size: 14px;
font-weight: 600;
color: #475569;
cursor: pointer;
@@ -2408,12 +2666,12 @@ select.te-cell {
}
input {
width: 64px;
height: 32px;
width: 50px;
height: 24px;
border: 1.5px solid #e2e8f0;
border-radius: 8px;
border-radius: 6px;
text-align: center;
font-size: 14px;
font-size: 11px;
font-weight: 700;
color: #1e293b;
background: #fff;
@@ -2441,9 +2699,9 @@ select.te-cell {
.te-denom-actions {
display: flex;
gap: 8px;
margin-top: 10px;
padding-top: 10px;
gap: 6px;
margin-top: 6px;
padding-top: 6px;
border-top: 1px solid #e2e8f0;
}
@@ -2470,7 +2728,7 @@ select.te-cell {
align-items: flex-start;
border-right: 1px solid #f1f5f9;
border-bottom: none;
padding: 10px 16px;
padding: 6px 12px;
&:last-child {
border-right: none;
@@ -2478,18 +2736,18 @@ select.te-cell {
&--total {
border-top: none;
padding-top: 10px;
padding-top: 6px;
margin-top: 0;
}
.te-bal-label {
font-size: 11px;
font-size: 10px;
color: #94a3b8;
margin-bottom: 4px;
margin-bottom: 2px;
}
.te-bal-value {
font-size: 15px;
font-size: 13px;
min-width: unset;
}
}