fortune-icecream / index.html
Sahanabg's picture
Update index.html
f4b3f50 verified
Raw
History Blame Contribute Delete
31.2 kB
<!DOCTYPE html>
<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 &nbsp;<span>โœฆ</span>&nbsp; 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> &nbsp;ยท&nbsp; 7th Floor, SumUp Berlin &nbsp;ยท&nbsp; ๐Ÿ”ฎ 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>