diff --git a/microservices/apps/tpos-mvp-next/src/app/globals.css b/microservices/apps/tpos-mvp-next/src/app/globals.css index 61fca8f0..9cdf7644 100644 --- a/microservices/apps/tpos-mvp-next/src/app/globals.css +++ b/microservices/apps/tpos-mvp-next/src/app/globals.css @@ -2737,3 +2737,881 @@ button:disabled { grid-template-columns: repeat(2, minmax(0, 1fr)); } } + +/* TPOS reference scale pass - match web-client-tpos-net typography */ +:root { + --bg: #0a0a0b; + --bg-raised: #111113; + --surface: #1a1a1d; + --surface-strong: #2a2a2e; + --ink: #ffffff; + --muted: #adadb0; + --faint: #8b8b90; + --line: #2a2a2e; + --line-strong: #3a3a3e; + --orange: #ff5c00; + --radius: 10px; + --shadow: none; + --tpos-font: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; +} + +html, +body { + font-family: var(--tpos-font); + font-size: 14px; + line-height: 1.5; + background: var(--bg); +} + +body { + background: var(--bg); + color: var(--ink); +} + +h1, +h2, +h3, +h4, +h5, +h6, +button, +input, +select, +textarea { + font-family: var(--tpos-font); + letter-spacing: 0; +} + +/* Auth pages: centered TPOS card, not oversized landing hero */ +.auth-screen { + min-height: 100vh; + display: grid; + grid-template-columns: minmax(0, 440px); + justify-content: center; + align-content: center; + gap: 18px; + padding: 24px; + background: var(--bg); +} + +.auth-copy { + max-width: 440px; + align-self: auto; + text-align: center; +} + +.auth-copy h1 { + margin: 8px 0; + font-size: 26px; + font-weight: 700; + line-height: 1.2; +} + +.auth-copy p { + max-width: 360px; + margin: 0 auto; + color: var(--muted); + font-size: 14px; + line-height: 1.5; +} + +.auth-role-grid { + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 8px; + margin-top: 16px; +} + +.auth-role { + min-height: 62px; + border-radius: 10px; + color: var(--muted); + font-size: 12px; + font-weight: 600; +} + +.auth-role svg { + width: 16px; + height: 16px; +} + +.auth-role--active { + border-color: rgba(255, 92, 0, 0.35); + background: rgba(255, 92, 0, 0.12); +} + +.auth-card { + width: 100%; + max-width: 440px; + align-self: auto; + padding: 32px; + border-color: #1f1f23; + border-radius: 24px; + background: #111113; + box-shadow: none; +} + +.auth-card__head { + justify-content: center; + gap: 12px; + margin-bottom: 22px; + text-align: left; +} + +.auth-card__head h2, +.auth-state h2 { + font-size: 26px; + font-weight: 700; + line-height: 1.2; +} + +.auth-card__head span, +.auth-field span, +.eyebrow { + font-size: 11px; + font-weight: 700; + color: var(--faint); +} + +.auth-field { + gap: 6px; + margin-bottom: 14px; +} + +.auth-field > div { + border-color: #2a2a2e; + border-radius: 12px; + background: #0a0a0b; +} + +.auth-field input { + min-height: 48px; + font-size: 14px; +} + +.auth-submit, +.primary-action { + min-height: 44px; + border-radius: 10px; + font-size: 13px; + font-weight: 600; +} + +.ghost-action { + min-height: 40px; + border-radius: 10px; + font-size: 13px; + font-weight: 600; +} + +/* Portal pages: compact admin scale from admin.css */ +.portal-shell { + grid-template-columns: 260px minmax(0, 1fr); + background: #0a0a0b; + color: #ffffff; + font-family: var(--tpos-font); +} + +.portal-sidebar { + gap: 0; + padding: 0; + border-right-color: #1f1f23; + background: #1a1a1d; +} + +.portal-brand { + min-height: 88px; + align-items: center; + padding: 24px; + border-bottom: 1px solid #1f1f23; +} + +.portal-brand span { + font-size: 16px; + font-weight: 700; +} + +.portal-brand b { + color: #8b8b90; + font-size: 11px; + font-weight: 500; +} + +.portal-nav { + gap: 4px; + padding: 16px 12px; +} + +.portal-nav__item, +.workflow-link { + min-height: 44px; + gap: 12px; + padding: 0 12px; + border-radius: 10px; + color: #adadb0; + font-size: 14px; + font-weight: 500; +} + +.portal-nav__item svg, +.workflow-link svg { + width: 20px; + height: 20px; +} + +.portal-nav__item--active, +.portal-nav__item:hover, +.workflow-link--active, +.workflow-link:hover { + background: #ff5c00; + color: #ffffff; +} + +.portal-session { + padding: 16px; + border-top: 1px solid #1f1f23; + color: #22c55e; + font-size: 11px; +} + +.portal-main { + padding: 28px; +} + +.portal-top { + align-items: center; + margin-bottom: 20px; + padding-bottom: 18px; + border-bottom: 1px solid #1f1f23; +} + +.portal-top h1 { + margin: 3px 0; + font-size: 22px; + font-weight: 700; + line-height: 1.2; +} + +.portal-top p { + color: #8b8b90; + font-size: 13px; +} + +.portal-actions { + gap: 12px; +} + +.metric-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 20px; + margin-bottom: 20px; +} + +.metric-card { + min-height: 108px; + display: flex; + flex-direction: column; + gap: 12px; + justify-content: center; + padding: 16px 20px; + border: 1px solid #1f1f23; + border-radius: 16px; + background: #1a1a1d; +} + +.metric-card::after { + display: none; +} + +.metric-card span { + color: #8b8b90; + font-size: 13px; + font-weight: 500; +} + +.metric-card strong { + color: #ffffff; + font-size: 28px; + font-weight: 700; + line-height: 1; +} + +.portal-grid { + gap: 20px; +} + +.portal-panel { + padding: 20px; + border-color: #1f1f23; + border-radius: 16px; + background: #1a1a1d; +} + +.panel-head h2 { + font-size: 18px; + font-weight: 700; +} + +.portal-list__item { + min-height: 54px; + padding: 10px 12px; + border-color: #2a2a2e; + border-radius: 10px; + background: #202024; +} + +.portal-list__item strong { + font-size: 14px; + font-weight: 600; +} + +.portal-list__item span, +.workflow-card span, +.shop-section span { + font-size: 12px; + color: #8b8b90; +} + +.portal-list__item b { + font-size: 13px; + font-weight: 600; +} + +.shop-section { + min-height: 104px; + border-radius: 10px; + background: #202024; +} + +/* POS desktop: remove extra giant treatment and follow pos.css dimensions */ +.pos-layout.pos-clone { + max-height: 100vh; + background: #0a0a0b; + color: #ffffff; + font-family: var(--tpos-font); + font-size: 14px; +} + +.pos-status-bar { + height: 48px; + padding: 0 16px; + border-bottom-color: #1f1f23; + background: #1a1a1d; +} + +.pos-status-bar__left { + gap: 12px; +} + +.pos-status-bar__right { + gap: 8px; +} + +.pos-status-bar__logo { + font-size: 15px; + font-weight: 700; +} + +.pos-status-bar__store, +.pos-status-bar__time { + color: #adadb0; + font-size: 13px; + font-weight: 400; +} + +.pos-status-bar__indicator { + min-height: 24px; + padding: 4px 10px; + border-radius: 6px; + font-size: 11px; + font-weight: 600; +} + +.pos-payment-header__back, +.pos-admin-btn { + width: 32px; + height: 32px; + border-color: #2a2a2e; + border-radius: 8px; + background: transparent; + color: #adadb0; +} + +.pos-clone .pos-main { + display: flex; + min-height: 0; +} + +.pos-clone .pos-sidebar { + display: none; +} + +.pos-clone .pos-page-content { + flex: 1; + min-width: 0; + display: grid; + grid-template-columns: minmax(0, 1fr) 64px; +} + +.pos-clone .pos-content-area { + min-width: 0; + min-height: 0; + display: grid; + grid-template-columns: minmax(0, 1fr) 380px; + overflow: hidden; +} + +.pos-product-panel { + background: #0a0a0b; +} + +.pos-sale-toolbar { + padding: 12px 16px 4px; +} + +.pos-sale-toolbar h1 { + font-size: 20px; + font-weight: 700; +} + +.pos-kicker { + font-size: 10px; + font-weight: 700; +} + +.pos-search { + width: min(360px, 100%); +} + +.pos-search input { + min-height: 40px; + border-radius: 10px; + font-size: 14px; +} + +.pos-category-tabs { + gap: 8px; + padding: 12px 16px; +} + +.pos-category-tab { + min-height: 34px; + padding: 8px 16px; + border: 0; + border-radius: 12px; + background: #2a2a2e; + color: #adadb0; + font-size: 13px; + font-weight: 500; +} + +.pos-category-tab--active { + background: #ff5c00; + color: #ffffff; + font-weight: 600; +} + +.pos-product-grid { + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 12px; + padding: 16px; +} + +.pos-product-card { + min-height: 0; + display: flex; + flex-direction: column; + gap: 8px; + padding: 12px; + border-radius: 12px; + background: #1a1a1d; +} + +.pos-product-card:hover { + transform: translateY(-2px); +} + +.pos-product-card__image { + aspect-ratio: 1; + border-radius: 8px; + background: #2a2a2e; + color: #8b8b90; +} + +.pos-product-card__name { + font-size: 13px; + font-weight: 600; +} + +.pos-product-card__price { + font-size: 14px; + font-weight: 700; +} + +.pos-product-card small { + padding: 0; + background: transparent; + color: #8b8b90; + font-size: 11px; + font-weight: 500; +} + +.pos-cart-panel { + width: 380px; + min-width: 380px; + gap: 0; + padding: 0; + border-left-color: #1f1f23; + background: #1a1a1d; +} + +.pos-cart-header { + padding: 14px 16px; + border-bottom: 1px solid #1f1f23; +} + +.pos-cart-header__title { + font-size: 15px; + font-weight: 600; +} + +.pos-cart-items { + padding: 8px; +} + +.pos-cart-item { + min-height: 0; + gap: 12px; + padding: 10px; + border-radius: 12px; + background: transparent; +} + +.pos-cart-item:hover { + background: #2a2a2e; +} + +.pos-cart-item__name { + font-size: 13px; + font-weight: 500; +} + +.pos-cart-item__price { + font-size: 12px; +} + +.pos-cart-item__qty { + display: flex; + gap: 8px; +} + +.pos-cart-item__qty button { + width: 28px; + height: 28px; + background: transparent; +} + +.pos-cart-footer { + padding: 16px; + border-top: 1px solid #1f1f23; +} + +.pos-voucher-row input, +.pos-cash-box input { + min-height: 36px; + border-radius: 8px; + font-size: 12px; +} + +.pos-voucher-row button { + border-radius: 8px; + font-size: 11px; + font-weight: 600; +} + +.pos-payment-methods { + gap: 10px; + padding: 0; +} + +.pos-payment-method-btn { + min-height: 82px; + flex-direction: column; + gap: 8px; + border: 2px solid #2a2a2e; + border-radius: 12px; + background: #0a0a0b; + font-size: 13px; + font-weight: 600; +} + +.pos-payment-quick-amounts { + grid-template-columns: repeat(3, 1fr); +} + +.pos-payment-quick-amounts button { + min-height: 36px; + font-size: 10px; + font-weight: 700; +} + +.pos-total-box { + gap: 8px 12px; + color: #adadb0; + font-size: 14px; +} + +.pos-total-box strong:last-child { + font-size: 22px; + font-weight: 700; +} + +.pos-btn-checkout { + height: 48px; + border-radius: 12px; + font-size: 15px; + font-weight: 600; +} + +.pos-clone .pos-bottom-nav { + width: 64px; + display: flex; + flex-direction: column; + gap: 2px; + padding: 8px 0; + border-left: 1px solid #1f1f23; + border-right: 0; + background: #1a1a1d; +} + +.pos-bottom-nav__tab { + min-height: auto; + gap: 3px; + margin: 0 6px; + padding: 10px 4px; + border: 0; + border-radius: 8px; + color: #8b8b90; + font-size: 10px; + font-weight: 500; +} + +.pos-bottom-nav__tab--active, +.pos-bottom-nav__tab:hover { + background: rgba(255, 92, 0, 0.08); + color: #ff5c00; +} + +.workflow-shell { + background: #0a0a0b; +} + +.workflow-main { + padding: 24px 28px; +} + +.workflow-hero h1 { + font-size: 28px; + font-weight: 700; +} + +.workflow-card { + min-height: 96px; + border-radius: 12px; + background: #1a1a1d; +} + +/* Customer QR menu follows the original compact white mobile menu */ +.customer-menu { + min-height: 100vh; + background: #ffffff; + color: #1f2937; + font-family: var(--tpos-font); +} + +.customer-menu__hero { + position: sticky; + top: 0; + z-index: 50; + min-height: 0; + max-width: 640px; + margin: 0 auto; + padding: 12px 16px; + background: #ffffff; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); +} + +.customer-menu__hero h1 { + margin: 0; + color: #1f2937; + font-size: 16px; + font-weight: 700; + line-height: 1.25; +} + +.customer-menu__hero p { + margin: 2px 0 0; + color: #9ca3af; + font-size: 12px; +} + +.customer-menu__hero .eyebrow { + display: none; +} + +.customer-menu__hero svg { + width: 28px; + height: 28px; + color: #ff5c00; +} + +.customer-menu__content { + max-width: 640px; + padding: 12px 16px 24px; +} + +.menu-category { + margin-bottom: 20px; +} + +.menu-category__head { + padding-bottom: 8px; + margin-bottom: 12px; + border-bottom: 1px solid #f3f4f6; + color: #1f2937; +} + +.menu-category__head svg { + display: none; +} + +.menu-category__head h2 { + margin: 0; + font-size: 16px; + font-weight: 700; +} + +.menu-items { + gap: 12px; +} + +.menu-item { + min-height: 76px; + align-items: center; + border: 1px solid #f3f4f6; + border-radius: 14px; + background: #ffffff; + padding: 14px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); +} + +.menu-item strong { + color: #1f2937; + font-size: 14px; + font-weight: 600; +} + +.menu-item span { + color: #9ca3af; + font-size: 13px; +} + +.menu-item b { + color: #ff5c00; + font-size: 14px; + font-weight: 700; +} + +.customer-menu__footer { + max-width: 640px; + margin: 0 auto; + padding: 0 16px 16px; + border-top: 0; + background: #ffffff; +} + +.customer-menu__footer .primary-action { + max-width: none; + min-height: 48px; + border-radius: 14px; + box-shadow: 0 4px 20px rgba(255, 92, 0, 0.28); +} + +@media (max-width: 920px) { + .auth-role-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .portal-shell { + grid-template-columns: 72px minmax(0, 1fr); + } + + .portal-brand { + justify-content: center; + padding: 18px 8px; + } + + .portal-brand b, + .portal-nav__item span, + .portal-session span { + display: none; + } + + .portal-nav__item { + justify-content: center; + padding: 0; + } + + .metric-grid, + .portal-grid, + .workflow-grid--data { + grid-template-columns: 1fr; + } + + .pos-clone .pos-content-area { + grid-template-columns: minmax(0, 1fr); + } + + .pos-cart-panel { + display: none; + } +} + +@media (max-width: 760px) { + .portal-main { + padding: 16px; + } + + .portal-top { + align-items: flex-start; + flex-direction: column; + } + + .portal-actions { + width: 100%; + } + + .portal-actions .ghost-action, + .portal-actions .primary-action { + flex: 1; + } + + .pos-clone .pos-page-content { + height: calc(100vh - 48px); + display: flex; + } + + .pos-clone .pos-bottom-nav { + width: 64px; + height: auto; + order: 2; + } + + .pos-product-panel { + height: calc(100vh - 48px); + } + + .pos-product-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} diff --git a/microservices/apps/tpos-mvp-next/src/components/TposPortal.tsx b/microservices/apps/tpos-mvp-next/src/components/TposPortal.tsx index 1ba59d2b..4c118a6a 100644 --- a/microservices/apps/tpos-mvp-next/src/components/TposPortal.tsx +++ b/microservices/apps/tpos-mvp-next/src/components/TposPortal.tsx @@ -40,6 +40,11 @@ export function TposPortal({ }) { const nav = portalNav[kind]; const active = labelFromPath(kind, path); + const currentHref = `/${kind}${path.length ? `/${path.join("/")}` : ""}`; + const isActiveHref = (href: string) => { + if (href === `/${kind}`) return path.length === 0; + return href === currentHref || currentHref.startsWith(`${href}/`); + }; return (
@@ -50,7 +55,7 @@ export function TposPortal({