Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>Fortune Ice Cream โ SumUp</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet" /> | |
| <style> | |
| *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } | |
| :root { | |
| --blue: #0033FF; | |
| --blue-hover: #1A47FF; | |
| --blue-pale: #EEF1FF; | |
| --navy: #050F2C; | |
| --gold: #F5C842; | |
| --white: #FFFFFF; | |
| --surface: #F5F6FA; | |
| --border: #E2E5EF; | |
| --text: #0D1125; | |
| --muted: #6B7280; | |
| --green: #059669; | |
| --green-pale: #D1FAE5; | |
| --amber: #D97706; | |
| --amber-pale: #FEF3C7; | |
| --r: 12px; | |
| } | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background: var(--surface); | |
| color: var(--text); | |
| min-height: 100vh; | |
| } | |
| /* โโโ HEADER โโโ */ | |
| header { | |
| background: var(--navy); | |
| height: 60px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 0 24px; | |
| position: sticky; | |
| top: 0; | |
| z-index: 100; | |
| } | |
| .brand { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .brand-mark { | |
| width: 30px; | |
| height: 30px; | |
| background: var(--blue); | |
| border-radius: 8px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| /* SumUp wordmark SVG inline */ | |
| .brand-mark svg { display: block; } | |
| .brand-name { | |
| color: #fff; | |
| font-size: 14px; | |
| font-weight: 700; | |
| letter-spacing: -0.3px; | |
| } | |
| .brand-sep { | |
| width: 1px; | |
| height: 16px; | |
| background: rgba(255,255,255,0.2); | |
| margin: 0 2px; | |
| } | |
| .brand-sub { | |
| color: var(--gold); | |
| font-size: 13px; | |
| font-weight: 600; | |
| } | |
| .header-cta { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| background: var(--blue); | |
| color: #fff; | |
| border: none; | |
| border-radius: 8px; | |
| padding: 8px 16px; | |
| font-size: 13px; | |
| font-weight: 700; | |
| cursor: pointer; | |
| font-family: 'Inter', sans-serif; | |
| transition: background 0.15s; | |
| } | |
| .header-cta:hover { background: var(--blue-hover); } | |
| .cart-badge { | |
| background: var(--gold); | |
| color: var(--navy); | |
| border-radius: 50%; | |
| width: 18px; height: 18px; | |
| font-size: 10px; | |
| font-weight: 800; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| /* โโโ HERO โโโ */ | |
| .hero { | |
| background: var(--navy); | |
| padding: 56px 24px 52px; | |
| text-align: center; | |
| } | |
| .hero-tag { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 6px; | |
| background: rgba(255,255,255,0.07); | |
| border: 1px solid rgba(255,255,255,0.12); | |
| border-radius: 100px; | |
| padding: 5px 14px; | |
| font-size: 11px; | |
| font-weight: 600; | |
| color: rgba(255,255,255,0.7); | |
| letter-spacing: 0.5px; | |
| margin-bottom: 24px; | |
| } | |
| .hero-tag span { color: var(--gold); } | |
| .hero h1 { | |
| font-size: clamp(32px, 5vw, 54px); | |
| font-weight: 900; | |
| letter-spacing: -2px; | |
| color: #fff; | |
| line-height: 1; | |
| margin-bottom: 14px; | |
| } | |
| .hero h1 em { | |
| font-style: normal; | |
| color: var(--gold); | |
| } | |
| .hero-desc { | |
| font-size: 15px; | |
| color: rgba(255,255,255,0.5); | |
| max-width: 420px; | |
| margin: 0 auto 32px; | |
| line-height: 1.65; | |
| } | |
| .hero-chips { | |
| display: flex; | |
| justify-content: center; | |
| flex-wrap: wrap; | |
| gap: 8px; | |
| } | |
| .chip { | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| background: rgba(255,255,255,0.06); | |
| border: 1px solid rgba(255,255,255,0.1); | |
| border-radius: 100px; | |
| padding: 6px 14px; | |
| font-size: 12px; | |
| font-weight: 500; | |
| color: rgba(255,255,255,0.75); | |
| } | |
| .chip.accent { background: var(--gold); color: var(--navy); border-color: var(--gold); font-weight: 700; } | |
| /* โโโ SECTION โโโ */ | |
| .section { | |
| max-width: 880px; | |
| margin: 0 auto; | |
| padding: 52px 24px; | |
| } | |
| .section-label { | |
| font-size: 10px; | |
| font-weight: 700; | |
| letter-spacing: 2px; | |
| text-transform: uppercase; | |
| color: var(--blue); | |
| margin-bottom: 6px; | |
| } | |
| .section-title { | |
| font-size: 24px; | |
| font-weight: 800; | |
| letter-spacing: -0.8px; | |
| margin-bottom: 4px; | |
| } | |
| .section-hint { | |
| font-size: 13px; | |
| color: var(--muted); | |
| margin-bottom: 28px; | |
| } | |
| /* โโโ DELIVERY TOGGLE โโโ */ | |
| .delivery-row { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| flex-wrap: wrap; | |
| gap: 12px; | |
| margin-bottom: 28px; | |
| } | |
| .seg { | |
| display: flex; | |
| background: #fff; | |
| border: 1.5px solid var(--border); | |
| border-radius: 10px; | |
| padding: 3px; | |
| } | |
| .seg-btn { | |
| padding: 8px 18px; | |
| border: none; | |
| background: transparent; | |
| border-radius: 7px; | |
| font-size: 13px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| color: var(--muted); | |
| font-family: 'Inter', sans-serif; | |
| transition: all 0.15s; | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .seg-btn.active { | |
| background: var(--navy); | |
| color: #fff; | |
| } | |
| .delivery-info { | |
| font-size: 12px; | |
| font-weight: 500; | |
| color: var(--muted); | |
| } | |
| .delivery-info b { color: var(--blue); } | |
| /* โโโ MENU GRID โโโ */ | |
| .menu-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); | |
| gap: 14px; | |
| } | |
| .card { | |
| background: #fff; | |
| border-radius: var(--r); | |
| border: 1.5px solid var(--border); | |
| padding: 20px; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 12px; | |
| transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s; | |
| } | |
| .card:hover { | |
| border-color: var(--blue); | |
| box-shadow: 0 4px 20px rgba(0,51,255,0.10); | |
| transform: translateY(-2px); | |
| } | |
| .card.in-cart { | |
| border-color: var(--green); | |
| } | |
| .card-top { | |
| display: flex; | |
| align-items: flex-start; | |
| justify-content: space-between; | |
| } | |
| .card-icon { | |
| width: 52px; | |
| height: 52px; | |
| border-radius: 10px; | |
| background: var(--surface); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 28px; | |
| } | |
| .card-badges { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: flex-end; | |
| gap: 4px; | |
| } | |
| .badge-vegan { | |
| background: var(--green-pale); | |
| color: var(--green); | |
| font-size: 9px; | |
| font-weight: 700; | |
| letter-spacing: 0.5px; | |
| text-transform: uppercase; | |
| padding: 3px 8px; | |
| border-radius: 100px; | |
| } | |
| .card-name { | |
| font-size: 15px; | |
| font-weight: 800; | |
| letter-spacing: -0.3px; | |
| } | |
| .card-desc { | |
| font-size: 12px; | |
| color: var(--muted); | |
| line-height: 1.5; | |
| flex: 1; | |
| } | |
| /* vessel toggle */ | |
| .vessel-row { | |
| display: flex; | |
| gap: 6px; | |
| } | |
| .vessel-btn { | |
| flex: 1; | |
| border: 1.5px solid var(--border); | |
| background: #fff; | |
| border-radius: 8px; | |
| padding: 6px 4px; | |
| font-size: 11px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| font-family: 'Inter', sans-serif; | |
| color: var(--muted); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 4px; | |
| transition: all 0.12s; | |
| } | |
| .vessel-btn.sel { | |
| border-color: var(--blue); | |
| background: var(--blue-pale); | |
| color: var(--blue); | |
| } | |
| .card-footer { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| } | |
| .card-price { | |
| font-size: 20px; | |
| font-weight: 900; | |
| letter-spacing: -0.8px; | |
| color: var(--text); | |
| } | |
| .card-price .cents { | |
| font-size: 13px; | |
| font-weight: 600; | |
| vertical-align: super; | |
| letter-spacing: 0; | |
| } | |
| .card-price .delivery-add { | |
| font-size: 10px; | |
| font-weight: 500; | |
| color: var(--muted); | |
| display: block; | |
| letter-spacing: 0; | |
| } | |
| .add-btn { | |
| width: 36px; | |
| height: 36px; | |
| background: var(--blue); | |
| color: #fff; | |
| border: none; | |
| border-radius: 8px; | |
| font-size: 20px; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: background 0.15s, transform 0.1s; | |
| } | |
| .add-btn:hover { background: var(--blue-hover); } | |
| .add-btn:active { transform: scale(0.92); } | |
| .add-btn.done { background: var(--green); font-size: 14px; } | |
| /* โโโ FORTUNE BAND โโโ */ | |
| .fortune-band { | |
| background: var(--navy); | |
| padding: 52px 24px; | |
| text-align: center; | |
| } | |
| .fortune-inner { | |
| max-width: 560px; | |
| margin: 0 auto; | |
| } | |
| .fortune-band .section-label { color: var(--gold); } | |
| .fortune-band h2 { | |
| font-size: clamp(22px, 3vw, 34px); | |
| font-weight: 900; | |
| letter-spacing: -1px; | |
| color: #fff; | |
| margin-bottom: 12px; | |
| } | |
| .fortune-desc { | |
| font-size: 14px; | |
| color: rgba(255,255,255,0.5); | |
| line-height: 1.7; | |
| margin-bottom: 32px; | |
| } | |
| .fortune-steps { | |
| display: flex; | |
| justify-content: center; | |
| gap: 12px; | |
| flex-wrap: wrap; | |
| } | |
| .fstep { | |
| background: rgba(255,255,255,0.05); | |
| border: 1px solid rgba(255,255,255,0.1); | |
| border-radius: var(--r); | |
| padding: 18px 16px; | |
| width: 150px; | |
| text-align: center; | |
| } | |
| .fstep-icon { font-size: 26px; display: block; margin-bottom: 8px; } | |
| .fstep-text { font-size: 12px; color: rgba(255,255,255,0.6); line-height: 1.4; } | |
| /* โโโ ORDERS โโโ */ | |
| .orders-section { background: #fff; border-top: 1px solid var(--border); } | |
| .orders-inner { | |
| max-width: 880px; | |
| margin: 0 auto; | |
| padding: 52px 24px; | |
| } | |
| .show-orders-row { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| cursor: pointer; | |
| user-select: none; | |
| width: fit-content; | |
| } | |
| .show-orders-row input { accent-color: var(--blue); width: 16px; height: 16px; } | |
| .show-orders-row label { font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; } | |
| .orders-wrap { margin-top: 24px; display: none; } | |
| .orders-wrap.open { display: block; } | |
| .orders-stats { | |
| display: flex; | |
| gap: 16px; | |
| margin-bottom: 16px; | |
| flex-wrap: wrap; | |
| } | |
| .stat { | |
| font-size: 12px; | |
| font-weight: 700; | |
| padding: 4px 12px; | |
| border-radius: 100px; | |
| } | |
| .stat.total { background: var(--surface); color: var(--muted); } | |
| .stat.pend { background: var(--amber-pale); color: var(--amber); } | |
| .stat.prep { background: var(--blue-pale); color: var(--blue); } | |
| .tbl-wrap { overflow-x: auto; } | |
| table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| border-radius: var(--r); | |
| overflow: hidden; | |
| font-size: 13px; | |
| box-shadow: 0 0 0 1.5px var(--border); | |
| } | |
| thead th { | |
| background: var(--navy); | |
| color: rgba(255,255,255,0.7); | |
| text-align: left; | |
| padding: 12px 14px; | |
| font-size: 10px; | |
| font-weight: 700; | |
| letter-spacing: 1.2px; | |
| text-transform: uppercase; | |
| white-space: nowrap; | |
| } | |
| tbody td { | |
| padding: 12px 14px; | |
| border-bottom: 1px solid var(--border); | |
| vertical-align: middle; | |
| } | |
| tbody tr:last-child td { border-bottom: none; } | |
| tbody tr:hover td { background: var(--surface); } | |
| .sbadge { | |
| display: inline-block; | |
| padding: 3px 10px; | |
| border-radius: 100px; | |
| font-size: 11px; | |
| font-weight: 700; | |
| white-space: nowrap; | |
| } | |
| .sbadge.pending { background: var(--amber-pale); color: var(--amber); } | |
| .sbadge.prepared { background: var(--blue-pale); color: var(--blue); } | |
| .sbadge.delivered { background: var(--green-pale); color: var(--green); } | |
| .abtn { | |
| border: none; | |
| border-radius: 7px; | |
| padding: 5px 10px; | |
| font-size: 11px; | |
| font-weight: 700; | |
| cursor: pointer; | |
| font-family: 'Inter', sans-serif; | |
| margin-right: 4px; | |
| } | |
| .abtn.b { background: var(--blue); color: #fff; } | |
| .abtn.g { background: var(--green); color: #fff; } | |
| .abtn:disabled { background: var(--border); color: var(--muted); cursor: not-allowed; } | |
| .empty-orders { | |
| text-align: center; | |
| padding: 40px; | |
| color: var(--muted); | |
| font-size: 14px; | |
| } | |
| .empty-orders span { font-size: 36px; display: block; margin-bottom: 10px; } | |
| /* โโโ MODAL โโโ */ | |
| .overlay { | |
| display: none; | |
| position: fixed; | |
| inset: 0; | |
| background: rgba(5,15,44,0.6); | |
| backdrop-filter: blur(3px); | |
| z-index: 200; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 20px; | |
| } | |
| .overlay.open { display: flex; } | |
| .modal { | |
| background: #fff; | |
| border-radius: 16px; | |
| padding: 28px; | |
| width: 100%; | |
| max-width: 440px; | |
| max-height: 88vh; | |
| overflow-y: auto; | |
| box-shadow: 0 20px 60px rgba(0,0,0,0.2); | |
| } | |
| .modal-head { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| } | |
| .modal-head h3 { font-size: 17px; font-weight: 800; letter-spacing: -0.4px; } | |
| .x-btn { | |
| background: var(--surface); | |
| border: none; | |
| border-radius: 50%; | |
| width: 30px; height: 30px; | |
| cursor: pointer; | |
| font-size: 14px; | |
| color: var(--muted); | |
| display: flex; align-items: center; justify-content: center; | |
| } | |
| .ci { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: flex-start; | |
| padding: 10px 0; | |
| border-bottom: 1px solid var(--border); | |
| font-size: 13px; | |
| } | |
| .ci-name { font-weight: 700; } | |
| .ci-meta { font-size: 11px; color: var(--muted); margin-top: 2px; } | |
| .ci-price { font-weight: 800; color: var(--blue); margin-right: 6px; } | |
| .rm { background: none; border: none; color: #ccc; cursor: pointer; font-size: 15px; } | |
| .rm:hover { color: #e00; } | |
| .cart-total { | |
| display: flex; | |
| justify-content: space-between; | |
| padding: 14px 0 0; | |
| font-size: 16px; | |
| font-weight: 900; | |
| letter-spacing: -0.4px; | |
| } | |
| .fortune-opt { | |
| display: flex; | |
| align-items: flex-start; | |
| gap: 8px; | |
| margin-top: 14px; | |
| padding: 12px; | |
| background: var(--blue-pale); | |
| border-radius: 10px; | |
| font-size: 13px; | |
| font-weight: 500; | |
| line-height: 1.5; | |
| } | |
| .fortune-opt input { accent-color: var(--blue); flex-shrink: 0; margin-top: 2px; } | |
| .fortune-opt b { color: var(--blue); } | |
| .fl { font-size: 11px; font-weight: 700; color: var(--muted); letter-spacing: 0.8px; text-transform: uppercase; margin: 14px 0 5px; display: block; } | |
| .fi { | |
| width: 100%; | |
| padding: 10px 12px; | |
| border: 1.5px solid var(--border); | |
| border-radius: 9px; | |
| font-size: 13px; | |
| font-family: 'Inter', sans-serif; | |
| outline: none; | |
| background: var(--surface); | |
| transition: border-color 0.15s; | |
| } | |
| .fi:focus { border-color: var(--blue); background: #fff; } | |
| .place-btn { | |
| width: 100%; | |
| background: var(--blue); | |
| color: #fff; | |
| border: none; | |
| border-radius: 10px; | |
| padding: 14px; | |
| font-size: 14px; | |
| font-weight: 800; | |
| cursor: pointer; | |
| margin-top: 18px; | |
| font-family: 'Inter', sans-serif; | |
| transition: background 0.15s; | |
| } | |
| .place-btn:hover { background: var(--blue-hover); } | |
| .empty-cart { text-align: center; padding: 28px; color: var(--muted); font-size: 14px; } | |
| .empty-cart span { font-size: 36px; display: block; margin-bottom: 8px; } | |
| /* โโโ FOOTER โโโ */ | |
| footer { | |
| background: var(--navy); | |
| text-align: center; | |
| padding: 24px; | |
| font-size: 12px; | |
| color: rgba(255,255,255,0.35); | |
| border-top: 1px solid rgba(255,255,255,0.05); | |
| } | |
| footer b { color: rgba(255,255,255,0.7); } | |
| /* โโโ TOAST โโโ */ | |
| .toast { | |
| position: fixed; | |
| bottom: 24px; right: 24px; | |
| background: var(--navy); | |
| color: #fff; | |
| padding: 12px 18px; | |
| border-radius: 10px; | |
| font-size: 13px; | |
| font-weight: 600; | |
| z-index: 999; | |
| opacity: 0; | |
| transform: translateY(16px); | |
| transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| max-width: 260px; | |
| border: 1px solid rgba(255,255,255,0.08); | |
| pointer-events: none; | |
| } | |
| .toast.show { opacity: 1; transform: translateY(0); } | |
| @media (max-width: 600px) { | |
| .menu-grid { grid-template-columns: 1fr 1fr; } | |
| .fortune-steps { gap: 8px; } | |
| .fstep { width: 130px; } | |
| .hero h1 { letter-spacing: -1.5px; } | |
| } | |
| @media (max-width: 380px) { | |
| .menu-grid { grid-template-columns: 1fr; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- HEADER --> | |
| <header> | |
| <div class="brand"> | |
| <div class="brand-mark"> | |
| <!-- SumUp "S" simplified mark --> | |
| <svg width="18" height="18" viewBox="0 0 18 18" fill="none"> | |
| <path d="M13.5 5.5C13.5 3.567 11.933 2 10 2H8C5.791 2 4 3.791 4 6s1.791 4 4 4h2c2.209 0 4 1.791 4 4s-1.791 4-4 4H8C5.791 18 4 16.433 4 14.5" stroke="white" stroke-width="1.8" stroke-linecap="round"/> | |
| </svg> | |
| </div> | |
| <span class="brand-name">SumUp</span> | |
| <div class="brand-sep"></div> | |
| <span class="brand-sub">Fortune Ice Cream</span> | |
| </div> | |
| <button class="header-cta" onclick="openCart()"> | |
| <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/></svg> | |
| Order | |
| <span class="cart-badge" id="cartCount">0</span> | |
| </button> | |
| </header> | |
| <!-- HERO --> | |
| <section class="hero"> | |
| <div class="hero-tag">๐ข 7th Floor ยท SumUp Berlin <span>โฆ</span> Open today</div> | |
| <h1>Ice cream.<br/><em>Your fortune.</em></h1> | |
| <p class="hero-desc">Artisan scoops served on the 7th floor. Pick up yourself or order to your desk. Oh โ and your palm reading is always on us.</p> | |
| <div class="hero-chips"> | |
| <span class="chip">๐ข 7th floor pickup</span> | |
| <span class="chip">๐ฆ Desk delivery +โฌ1</span> | |
| <span class="chip accent">๐ฎ Free palm reading</span> | |
| </div> | |
| </section> | |
| <!-- MENU --> | |
| <section class="section"> | |
| <p class="section-label">Menu</p> | |
| <h2 class="section-title">Choose your scoop</h2> | |
| <p class="section-hint">All flavours โฌ3,00 ยท Pick bowl or waffle cone โ no extra charge</p> | |
| <div class="delivery-row"> | |
| <div class="seg"> | |
| <button class="seg-btn active" id="pickupBtn" onclick="setDelivery(false)">๐ข Pick up at 7F</button> | |
| <button class="seg-btn" id="deliveryBtn" onclick="setDelivery(true)">๐ฆ Deliver to desk</button> | |
| </div> | |
| <p class="delivery-info" id="deliveryNote">Collect from the 7th floor.</p> | |
| </div> | |
| <div class="menu-grid" id="menuGrid"></div> | |
| </section> | |
| <!-- FORTUNE --> | |
| <section class="fortune-band"> | |
| <div class="fortune-inner"> | |
| <p class="section-label">The experience</p> | |
| <h2>Your palm holds secrets.<br/>We'll read it โ free.</h2> | |
| <p class="fortune-desc">We believe everyone deserves to know what their palm says. Show us your hand when you collect, or ask via order note. No charge, ever.</p> | |
| <div class="fortune-steps"> | |
| <div class="fstep"> | |
| <span class="fstep-icon">๐ฆ</span> | |
| <p class="fstep-text">Pick your flavour & vessel</p> | |
| </div> | |
| <div class="fstep"> | |
| <span class="fstep-icon">๐ค</span> | |
| <p class="fstep-text">Show us your palm</p> | |
| </div> | |
| <div class="fstep"> | |
| <span class="fstep-icon">โจ</span> | |
| <p class="fstep-text">Get your fortune โ free</p> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- ORDERS DASHBOARD --> | |
| <section class="orders-section"> | |
| <div class="orders-inner"> | |
| <p class="section-label">Staff area</p> | |
| <h2 class="section-title">Order dashboard</h2> | |
| <p class="section-hint" style="margin-bottom:20px;">Track and manage incoming orders.</p> | |
| <label class="show-orders-row"> | |
| <input type="checkbox" id="ordersToggle" onchange="toggleOrders()" /> | |
| <label for="ordersToggle">Show live orders</label> | |
| </label> | |
| <div class="orders-wrap" id="ordersWrap"> | |
| <div id="ordersContent"></div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- FOOTER --> | |
| <footer> | |
| <b>Fortune Ice Cream</b> ยท 7th Floor, SumUp Berlin ยท ๐ฎ Trust your fortune | |
| </footer> | |
| <!-- ORDER MODAL --> | |
| <div class="overlay" id="overlay"> | |
| <div class="modal"> | |
| <div class="modal-head"> | |
| <h3>Your order ๐ฆ</h3> | |
| <button class="x-btn" onclick="closeCart()">โ</button> | |
| </div> | |
| <div id="cartBody"></div> | |
| <div id="fortuneOpt" style="display:none"> | |
| <div class="fortune-opt"> | |
| <input type="checkbox" id="fortuneCheck" checked /> | |
| <span>Include a <b>free palm reading</b> ๐ฎ โ show your hand on pickup or leave a note.</span> | |
| </div> | |
| </div> | |
| <div id="checkoutFields" style="display:none"> | |
| <span class="fl">Your name</span> | |
| <input class="fi" type="text" id="nameInput" placeholder="e.g. Alex K." /> | |
| <div id="deskWrap" style="display:none"> | |
| <span class="fl">Desk / location</span> | |
| <input class="fi" type="text" id="deskInput" placeholder="e.g. Floor 3, Desk 12B" /> | |
| </div> | |
| <span class="fl">Note (optional)</span> | |
| <input class="fi" type="text" id="noteInput" placeholder="Any special requests..." /> | |
| <button class="place-btn" onclick="placeOrder()">Place Order โ</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="toast" id="toast"></div> | |
| <script> | |
| const FLAVOURS = [ | |
| { id:1, icon:'๐ฟ', name:'Pistachio', desc:'Creamy gelato with real pistachio pieces', price:3, vegan:false }, | |
| { id:2, icon:'โ', name:'Tiramisu', desc:'Mascarpone gelato dusted with cocoa powder', price:3, vegan:false }, | |
| { id:3, icon:'๐ซ', name:'Chocolate', desc:'Rich, dark Belgian chocolate gelato', price:3, vegan:false }, | |
| { id:4, icon:'๐ฆ', name:'Vanilla', desc:'Classic vanilla bean gelato, smooth and pure', price:3, vegan:false }, | |
| { id:5, icon:'๐', name:'Strawberry Yogurt', desc:'Light, tangy strawberry yogurt sorbet', price:3, vegan:false }, | |
| { id:6, icon:'๐ฑ', name:'Vegan Vanilla', desc:'Plant-based vanilla โ just as creamy, entirely kind', price:3, vegan:true }, | |
| ]; | |
| const vessel = {}; | |
| FLAVOURS.forEach(f => vessel[f.id] = 'bowl'); | |
| let cart = [], delivery = false, orders = [], seq = 1; | |
| /* โโ delivery โโ */ | |
| function setDelivery(v) { | |
| delivery = v; | |
| document.getElementById('pickupBtn').classList.toggle('active', !v); | |
| document.getElementById('deliveryBtn').classList.toggle('active', v); | |
| document.getElementById('deliveryNote').innerHTML = v | |
| ? '<b>+โฌ1,00 delivery</b> added to total.' | |
| : 'Collect from the 7th floor.'; | |
| renderMenu(); renderCart(); | |
| } | |
| /* โโ vessel โโ */ | |
| function setVessel(id, v) { | |
| vessel[id] = v; | |
| ['bowl','cone'].forEach(t => { | |
| document.getElementById('v'+id+t)?.classList.toggle('sel', vessel[id]===t); | |
| }); | |
| } | |
| /* โโ menu โโ */ | |
| function renderMenu() { | |
| document.getElementById('menuGrid').innerHTML = FLAVOURS.map(f => { | |
| const total = f.price + (delivery ? 1 : 0); | |
| const inCart = cart.some(c => c.id === f.id); | |
| const v = vessel[f.id]; | |
| return ` | |
| <div class="card${inCart?' in-cart':''}"> | |
| <div class="card-top"> | |
| <div class="card-icon">${f.icon}</div> | |
| <div class="card-badges"> | |
| ${f.vegan ? '<span class="badge-vegan">๐ฑ Vegan</span>' : ''} | |
| </div> | |
| </div> | |
| <div> | |
| <div class="card-name">${f.name}</div> | |
| <div class="card-desc">${f.desc}</div> | |
| </div> | |
| <div class="vessel-row"> | |
| <button class="vessel-btn${v==='bowl'?' sel':''}" id="v${f.id}bowl" onclick="setVessel(${f.id},'bowl')">๐ฅฃ Bowl</button> | |
| <button class="vessel-btn${v==='cone'?' sel':''}" id="v${f.id}cone" onclick="setVessel(${f.id},'cone')">๐ฆ Cone</button> | |
| </div> | |
| <div class="card-footer"> | |
| <div class="card-price"> | |
| <span class="cents">โฌ</span>${total.toFixed(2).replace('.',',')} | |
| ${delivery ? '<span class="delivery-add">incl. delivery</span>' : ''} | |
| </div> | |
| <button class="add-btn${inCart?' done':''}" onclick="addToCart(${f.id})">${inCart?'โ':'+'}</button> | |
| </div> | |
| </div>`; | |
| }).join(''); | |
| } | |
| /* โโ cart โโ */ | |
| function addToCart(id) { | |
| const f = FLAVOURS.find(x => x.id===id); | |
| const ex = cart.find(c => c.id===id); | |
| if (!ex) cart.push({...f, qty:1, vessel:vessel[id]}); | |
| else { ex.qty++; ex.vessel=vessel[id]; } | |
| sync(); | |
| toast(`${f.icon} ${f.name} added!`); | |
| } | |
| function remove(id) { cart = cart.filter(c => c.id!==id); sync(); } | |
| function total() { return cart.reduce((s,c)=>s+c.price*c.qty,0)+(delivery?1:0); } | |
| function sync() { | |
| document.getElementById('cartCount').textContent = cart.reduce((s,c)=>s+c.qty,0); | |
| renderMenu(); | |
| if (document.getElementById('overlay').classList.contains('open')) renderCart(); | |
| } | |
| function openCart() { renderCart(); document.getElementById('overlay').classList.add('open'); } | |
| function closeCart() { document.getElementById('overlay').classList.remove('open'); } | |
| function renderCart() { | |
| const body = document.getElementById('cartBody'); | |
| const fopt = document.getElementById('fortuneOpt'); | |
| const fields = document.getElementById('checkoutFields'); | |
| const dw = document.getElementById('deskWrap'); | |
| if (!cart.length) { | |
| body.innerHTML = `<div class="empty-cart"><span>๐ฆ</span>Nothing here yet โ pick a scoop!</div>`; | |
| fopt.style.display = 'none'; | |
| fields.style.display = 'none'; | |
| return; | |
| } | |
| let html = cart.map(c => ` | |
| <div class="ci"> | |
| <div> | |
| <div class="ci-name">${c.icon} ${c.name}${c.qty>1?' ร'+c.qty:''}</div> | |
| <div class="ci-meta">${c.vessel==='cone'?'๐ฆ Waffle cone':'๐ฅฃ Bowl'}</div> | |
| </div> | |
| <span style="display:flex;align-items:center;gap:4px"> | |
| <span class="ci-price">โฌ${(c.price*c.qty).toFixed(2).replace('.',',')}</span> | |
| <button class="rm" onclick="remove(${c.id})">โ</button> | |
| </span> | |
| </div>`).join(''); | |
| if (delivery) html += `<div class="ci"><span>๐ฆ Delivery</span><span class="ci-price">โฌ1,00</span></div>`; | |
| html += `<div class="cart-total"><span>Total</span><span>โฌ${total().toFixed(2).replace('.',',')}</span></div>`; | |
| body.innerHTML = html; | |
| fopt.style.display = 'block'; | |
| fields.style.display = 'block'; | |
| dw.style.display = delivery ? 'block' : 'none'; | |
| } | |
| /* โโ place order โโ */ | |
| function placeOrder() { | |
| const name = document.getElementById('nameInput').value.trim(); | |
| if (!name) { toast('Enter your name ๐'); return; } | |
| if (delivery && !document.getElementById('deskInput').value.trim()) { toast('Enter your desk location ๐'); return; } | |
| orders.push({ | |
| id: seq++, name, | |
| desk: delivery ? document.getElementById('deskInput').value.trim() : '7F Pickup', | |
| items: cart.map(c=>`${c.icon} ${c.name} (${c.vessel==='cone'?'cone':'bowl'})${c.qty>1?' ร'+c.qty:''}`).join(', '), | |
| total: `โฌ${total().toFixed(2).replace('.',',')}`, | |
| fortune: document.getElementById('fortuneCheck').checked, | |
| time: new Date().toLocaleTimeString('en-GB',{hour:'2-digit',minute:'2-digit'}), | |
| status:'pending' | |
| }); | |
| cart = []; sync(); closeCart(); | |
| ['nameInput','deskInput','noteInput'].forEach(id => document.getElementById(id).value=''); | |
| renderOrders(); | |
| toast("๐ฆ Order placed!"); | |
| } | |
| /* โโ orders dashboard โโ */ | |
| function toggleOrders() { | |
| const show = document.getElementById('ordersToggle').checked; | |
| document.getElementById('ordersWrap').classList.toggle('open', show); | |
| if (show) renderOrders(); | |
| } | |
| function mark(id, status) { | |
| const o = orders.find(o=>o.id===id); | |
| if (o) { o.status=status; renderOrders(); } | |
| } | |
| function renderOrders() { | |
| const el = document.getElementById('ordersContent'); | |
| if (!orders.length) { | |
| el.innerHTML = `<div class="empty-orders"><span>๐</span>No orders yet.</div>`; | |
| return; | |
| } | |
| const pend = orders.filter(o=>o.status==='pending').length; | |
| const prep = orders.filter(o=>o.status==='prepared').length; | |
| const label = {pending:'โณ Pending', prepared:'๐ฆ Prepared', delivered:'โ Delivered'}; | |
| el.innerHTML = ` | |
| <div class="orders-stats"> | |
| <span class="stat total">${orders.length} order${orders.length!==1?'s':''}</span> | |
| <span class="stat pend">โณ ${pend} pending</span> | |
| <span class="stat prep">๐ฆ ${prep} prepared</span> | |
| </div> | |
| <div class="tbl-wrap"> | |
| <table> | |
| <thead><tr> | |
| <th>#</th><th>Name</th><th>Location</th><th>Items</th> | |
| <th>Total</th><th>๐ฎ</th><th>Time</th><th>Status</th><th>Actions</th> | |
| </tr></thead> | |
| <tbody> | |
| ${orders.map(o=>` | |
| <tr> | |
| <td><b>#${o.id}</b></td> | |
| <td style="font-weight:600">${o.name}</td> | |
| <td style="white-space:nowrap">${o.desk}</td> | |
| <td style="max-width:180px;color:var(--muted);font-size:12px">${o.items}</td> | |
| <td style="font-weight:800;color:var(--blue)">${o.total}</td> | |
| <td>${o.fortune?'๐ฎ':'โ'}</td> | |
| <td style="white-space:nowrap;color:var(--muted)">${o.time}</td> | |
| <td><span class="sbadge ${o.status}">${label[o.status]}</span></td> | |
| <td style="white-space:nowrap"> | |
| <button class="abtn b" onclick="mark(${o.id},'prepared')" ${o.status!=='pending'?'disabled':''}>Prepared</button> | |
| <button class="abtn g" onclick="mark(${o.id},'delivered')" ${o.status==='delivered'?'disabled':''}>Delivered</button> | |
| </td> | |
| </tr>`).join('')} | |
| </tbody> | |
| </table> | |
| </div>`; | |
| } | |
| /* โโ toast โโ */ | |
| function toast(msg) { | |
| const t = document.getElementById('toast'); | |
| t.textContent = msg; t.classList.add('show'); | |
| setTimeout(()=>t.classList.remove('show'), 2800); | |
| } | |
| document.getElementById('overlay').addEventListener('click', e => { | |
| if (e.target.id==='overlay') closeCart(); | |
| }); | |
| renderMenu(); | |
| </script> | |
| </body> | |
| </html> | |