-
-
+ {/* Ornament top */}
+
+
+
+
+
+
+ {/* Status icon */}
+
+
+
+
+ {/* Ref number */}
+
+ {ref}
+
+
+ {/* Status label */}
+
+ {error ? 'Could not load status' : label}
+
+
+ {/* Rejection reason */}
+ {rejectionReason && (
+
+ Reason: {rejectionReason}
+
+ )}
+
+ {/* Subtext */}
+ {orderStatus === 'delivered' && (
+
+ Thank you for your order! Enjoy your meal.
+
+ )}
+ {orderStatus === 'rejected' && (
+
+ We're sorry we couldn't take your order this time. Please try again or speak to staff.
+
+ )}
+ {!TERMINAL.has(orderStatus) && !error && (
+
+ We'll update this page automatically. Keep it open.
+
+ )}
+
+ {/* Spinner */}
+ {!TERMINAL.has(orderStatus) && !error && (
+
+ )}
-
-
{ref}
-
- {error ? 'Could not load status' : label}
-
- {rejectionReason && (
-
Reason: {rejectionReason}
- )}
-
-
- {!TERMINAL.has(orderStatus) && !error && (
-
- We'll update this page automatically. Keep it open.
-
- )}
-
- {orderStatus === 'rejected' && (
-
- We're sorry we couldn't take your order this time. Please try again or visit us in person.
-
- )}
-
- {orderStatus === 'delivered' && (
-
Thank you for your order! Enjoy your meal.
- )}
-
- {!TERMINAL.has(orderStatus) && !error && (
-
- )}
+ {/* Ornament bottom */}
+
+
+
+
)
diff --git a/connect_frontend/menu-app/src/pages/ProductModal.jsx b/connect_frontend/menu-app/src/pages/ProductModal.jsx
deleted file mode 100644
index e7ea4ea..0000000
--- a/connect_frontend/menu-app/src/pages/ProductModal.jsx
+++ /dev/null
@@ -1,136 +0,0 @@
-import { useState } from 'react'
-import { X, Plus, Minus } from 'lucide-react'
-
-export default function ProductModal({ product, onClose, onAdd }) {
- const [quantity, setQuantity] = useState(1)
- const [selectedOptions, setSelectedOptions] = useState([])
-
- const basePrice = product.digital_price ?? product.base_price
- const hasDiscount = product.digital_discount > 0 && !product.digital_price
- const displayPrice = hasDiscount
- ? basePrice * (1 - product.digital_discount / 100)
- : basePrice
-
- function toggleOption(opt) {
- setSelectedOptions(prev =>
- prev.find(o => o.id === opt.id)
- ? prev.filter(o => o.id !== opt.id)
- : [...prev, opt]
- )
- }
-
- const optionsTotal = selectedOptions.reduce((s, o) => s + (o.price || 0), 0)
- const lineTotal = (displayPrice + optionsTotal) * quantity
-
- return (
-
-
-
-
- {/* Image */}
- {(product.digital_image_url || product.image_url) && (
-

- )}
-
-
-
-
-
-
- {product.digital_name || product.name}
-
- {product.digital_description && (
-
{product.digital_description}
- )}
-
-
- {/* Price */}
-
-
- €{displayPrice.toFixed(2)}
-
- {hasDiscount && (
-
- €{basePrice.toFixed(2)}
-
- )}
- {hasDiscount && (
-
- -{product.digital_discount}%
-
- )}
-
-
- {/* Quick options */}
- {product.quick_options?.length > 0 && (
-
-
Options
-
- {product.quick_options.map(opt => {
- const active = selectedOptions.find(o => o.id === opt.id)
- return (
-
- )
- })}
-
-
- )}
-
- {/* Quantity */}
-
-
Quantity
-
-
-
{quantity}
-
-
-
-
- {/* Add to cart */}
- {product.digital_available ? (
-
- ) : (
-
- Currently unavailable
-
- )}
-
-
-
- )
-}
diff --git a/connect_frontend/menu-app/tailwind.config.js b/connect_frontend/menu-app/tailwind.config.js
index 43efcdf..f011f5c 100644
--- a/connect_frontend/menu-app/tailwind.config.js
+++ b/connect_frontend/menu-app/tailwind.config.js
@@ -3,7 +3,49 @@ export default {
content: ['./index.html', './src/**/*.{js,jsx}'],
theme: {
extend: {
- fontFamily: { sans: ['Geist', 'system-ui', 'sans-serif'] },
+ fontFamily: {
+ display: ['Bricolage Grotesque', 'serif'],
+ sans: ['Hanken Grotesk', 'system-ui', 'sans-serif'],
+ },
+ colors: {
+ brand: {
+ dark: '#2d3b2d',
+ hover: '#26331f',
+ },
+ cream: '#faf7f0',
+ card: '#fcfbf7',
+ gold: '#c9a24b',
+ terracotta: '#c2602f',
+ sage: '#9caf88',
+ success: '#3f7d4e',
+ },
+ borderRadius: {
+ card: '20px',
+ section: '22px',
+ sheet: '24px',
+ },
+ boxShadow: {
+ card: '0 5px 16px -10px rgba(45,42,31,0.45)',
+ 'card-hover': '0 10px 24px -12px rgba(45,42,31,0.5)',
+ cart: '0 12px 28px -8px rgba(45,59,45,0.55)',
+ },
+ keyframes: {
+ fade: { from: { opacity: 0 }, to: { opacity: 1 } },
+ slideup: {
+ from: { transform: 'translateY(100%)' },
+ to: { transform: 'translateY(0)' },
+ },
+ pop: {
+ '0%': { transform: 'scale(1)' },
+ '50%': { transform: 'scale(1.06)' },
+ '100%': { transform: 'scale(1)' },
+ },
+ },
+ animation: {
+ fade: 'fade 0.2s ease',
+ slideup: 'slideup 0.28s cubic-bezier(0.22,1,0.36,1)',
+ pop: 'pop 0.32s ease',
+ },
},
},
plugins: [],