fix(form): improve mobile layout for order form and admin toolbar

Stop phone-width sideways scroll from the admin toolbar, stack meal cards
and bump touch targets on coarse pointers, and respect safe-area insets.
This commit is contained in:
Adam Moussa 2026-07-29 19:19:55 -04:00
parent 452312b5e5
commit 2a985c1940
No known key found for this signature in database

View file

@ -248,13 +248,14 @@ async function submitOrder() {
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>Sea Haven — Meal Order ({week})</title> <title>Sea Haven — Meal Order ({week})</title>
<link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABX0lEQVRYhe3TPWsUURjF8d+dnSxhoxA1xEJnQQsJGbBTrIIIvoEDNqkNiJ9BrPwI4jeY2kmVoKWkSVALK6MgwWLsJIWIBBFZLGaLTTLrJrX3X96X5znnPPcSiUQikf+dcHAhr+qLuIrT2MV77Owv9ycWy6u6i3tnOu5maTg/FUzjOz5gHe/KImsXkFf1ZTzH9ZbaNdbwElvby/0fwzsJFnANN3uJO/00zJ5MxmrcwqOyyD7uE5BX9Q08xh5O4BL+ZXkXvzQp9RKcS4OzaUukh9nDg7LIVkcFGI04r2pDZw+xgrlx1U516KdB93DnGhvYxBd8w08M0MXnssgmCx7O9RZuYzEw30sszATpXCeY2R/3AC/wTMu420gnHbgyHeY1sb3FH9wfc28DT8oiezOx63EE4DeeYqllb4BXGsevj+L4IEd4M6ysf6X5HUu4oEniE9bKIts5dtdIJBKJREb4C8ngTD+C9DtvAAAAAElFTkSuQmCC"> <link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABX0lEQVRYhe3TPWsUURjF8d+dnSxhoxA1xEJnQQsJGbBTrIIIvoEDNqkNiJ9BrPwI4jeY2kmVoKWkSVALK6MgwWLsJIWIBBFZLGaLTTLrJrX3X96X5znnPPcSiUQikf+dcHAhr+qLuIrT2MV77Owv9ycWy6u6i3tnOu5maTg/FUzjOz5gHe/KImsXkFf1ZTzH9ZbaNdbwElvby/0fwzsJFnANN3uJO/00zJ5MxmrcwqOyyD7uE5BX9Q08xh5O4BL+ZXkXvzQp9RKcS4OzaUukh9nDg7LIVkcFGI04r2pDZw+xgrlx1U516KdB93DnGhvYxBd8w08M0MXnssgmCx7O9RZuYzEw30sszATpXCeY2R/3AC/wTMu420gnHbgyHeY1sb3FH9wfc28DT8oiezOx63EE4DeeYqllb4BXGsevj+L4IEd4M6ysf6X5HUu4oEniE9bKIts5dtdIJBKJREb4C8ngTD+C9DtvAAAAAElFTkSuQmCC">
<style> <style>
* {{ margin: 0; padding: 0; box-sizing: border-box; }} * {{ margin: 0; padding: 0; box-sizing: border-box; }}
body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f7; color: #1d1d1f; }} body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f7; color: #1d1d1f; padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px)); }}
.container {{ max-width: 800px; margin: 0 auto; padding: 16px; }} .container {{ max-width: 1400px; margin: 0 auto; padding: 16px; }}
#meals-list {{ display: grid; grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); gap: 12px; }}
header {{ background: #1a1a2e; color: #fff; padding: 24px 16px; text-align: center; margin-bottom: 24px; border-radius: 12px; }} header {{ background: #1a1a2e; color: #fff; padding: 24px 16px; text-align: center; margin-bottom: 24px; border-radius: 12px; }}
header h1 {{ font-size: 1.5rem; margin-bottom: 4px; }} header h1 {{ font-size: 1.5rem; margin-bottom: 4px; }}
header p {{ font-size: 0.85rem; opacity: 0.8; }} header p {{ font-size: 0.85rem; opacity: 0.8; }}
@ -265,7 +266,7 @@ header p {{ font-size: 0.85rem; opacity: 0.8; }}
.filters {{ display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }} .filters {{ display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }}
.filters button {{ padding: 6px 14px; border: 1px solid #d1d5db; border-radius: 20px; background: #fff; font-size: 0.8rem; cursor: pointer; transition: all 0.2s; }} .filters button {{ padding: 6px 14px; border: 1px solid #d1d5db; border-radius: 20px; background: #fff; font-size: 0.8rem; cursor: pointer; transition: all 0.2s; }}
.filters button.active {{ background: #1a1a2e; color: #fff; border-color: #1a1a2e; }} .filters button.active {{ background: #1a1a2e; color: #fff; border-color: #1a1a2e; }}
.meal-card {{ background: #fff; border-radius: 12px; padding: 12px; margin-bottom: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); display: flex; gap: 12px; align-items: center; }} .meal-card {{ background: #fff; border-radius: 12px; padding: 12px; margin-bottom: 0; box-shadow: 0 1px 3px rgba(0,0,0,0.08); display: flex; gap: 12px; align-items: center; }}
.meal-img {{ width: 80px; height: 80px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }} .meal-img {{ width: 80px; height: 80px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }}
.meal-info {{ flex: 1; min-width: 0; }} .meal-info {{ flex: 1; min-width: 0; }}
.meal-name {{ font-weight: 600; font-size: 0.95rem; margin-bottom: 2px; }} .meal-name {{ font-weight: 600; font-size: 0.95rem; margin-bottom: 2px; }}
@ -279,8 +280,8 @@ header p {{ font-size: 0.85rem; opacity: 0.8; }}
.qty-control button:last-child {{ border-radius: 0 8px 8px 0; }} .qty-control button:last-child {{ border-radius: 0 8px 8px 0; }}
.qty-control .qty {{ width: 36px; height: 32px; text-align: center; border: 1px solid #d1d5db; border-left: 0; border-right: 0; font-size: 0.95rem; font-weight: 600; }} .qty-control .qty {{ width: 36px; height: 32px; text-align: center; border: 1px solid #d1d5db; border-left: 0; border-right: 0; font-size: 0.95rem; font-weight: 600; }}
.meal-card.selected {{ border: 2px solid #1a1a2e; }} .meal-card.selected {{ border: 2px solid #1a1a2e; }}
.sticky-footer {{ position: fixed; bottom: 0; left: 0; right: 0; background: #fff; border-top: 1px solid #e5e7eb; padding: 12px 16px; box-shadow: 0 -2px 8px rgba(0,0,0,0.1); z-index: 100; }} .sticky-footer {{ position: fixed; bottom: 0; left: 0; right: 0; background: #fff; border-top: 1px solid #e5e7eb; padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px)); box-shadow: 0 -2px 8px rgba(0,0,0,0.1); z-index: 100; }}
.sticky-footer .inner {{ max-width: 800px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center; }} .sticky-footer .inner {{ max-width: 1400px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center; }}
.total {{ font-size: 1.1rem; font-weight: 700; }} .total {{ font-size: 1.1rem; font-weight: 700; }}
.submit-btn {{ background: #1a1a2e; color: #fff; border: none; padding: 12px 32px; border-radius: 8px; font-size: 1rem; font-weight: 600; cursor: pointer; transition: opacity 0.2s; }} .submit-btn {{ background: #1a1a2e; color: #fff; border: none; padding: 12px 32px; border-radius: 8px; font-size: 1rem; font-weight: 600; cursor: pointer; transition: opacity 0.2s; }}
.submit-btn:disabled {{ opacity: 0.4; cursor: not-allowed; }} .submit-btn:disabled {{ opacity: 0.4; cursor: not-allowed; }}
@ -290,18 +291,18 @@ header p {{ font-size: 0.85rem; opacity: 0.8; }}
.back-btn {{ background: transparent; color: #1a1a2e; border: 2px solid #1a1a2e; padding: 12px 32px; border-radius: 8px; font-size: 1rem; font-weight: 600; cursor: pointer; transition: all 0.2s; margin-top: 20px; }} .back-btn {{ background: transparent; color: #1a1a2e; border: 2px solid #1a1a2e; padding: 12px 32px; border-radius: 8px; font-size: 1rem; font-weight: 600; cursor: pointer; transition: all 0.2s; margin-top: 20px; }}
.back-btn:hover {{ background: #1a1a2e; color: #fff; }} .back-btn:hover {{ background: #1a1a2e; color: #fff; }}
.duplicate-warning {{ background: #fef3c7; color: #92400e; padding: 10px 16px; border-radius: 8px; margin-bottom: 20px; font-size: 0.9rem; text-align: center; font-weight: 500; border: 1px solid #fcd34d; }} .duplicate-warning {{ background: #fef3c7; color: #92400e; padding: 10px 16px; border-radius: 8px; margin-bottom: 20px; font-size: 0.9rem; text-align: center; font-weight: 500; border: 1px solid #fcd34d; }}
.meal-desc {{ font-size: 0.8rem; color: #6b7280; margin-bottom: 4px; }} .meal-desc {{ font-size: 0.8rem; color: #6b7280; margin-bottom: 4px; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }}
.search-bar {{ width: 100%; padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 8px; font-size: 1rem; margin-bottom: 16px; }} .search-bar {{ width: 100%; padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 8px; font-size: 1rem; margin-bottom: 16px; }}
body {{ padding-bottom: 80px; }}
.closed-banner {{ background: #fee2e2; color: #991b1b; padding: 16px; border-radius: 8px; margin-bottom: 20px; text-align: center; font-weight: 600; font-size: 1rem; }} .closed-banner {{ background: #fee2e2; color: #991b1b; padding: 16px; border-radius: 8px; margin-bottom: 20px; text-align: center; font-weight: 600; font-size: 1rem; }}
@media (min-width: 768px) {{ @media (max-width: 480px) {{
.container {{ max-width: 1100px; }} .meal-card {{ display: grid; grid-template-columns: 80px minmax(0, 1fr); align-items: start; }}
#meals-list {{ display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }} .qty-control {{ grid-column: 1 / -1; justify-content: center; }}
#meals-list .meal-card {{ margin-bottom: 0; }}
}} }}
@media (min-width: 1200px) {{ @media (pointer: coarse) {{
.container {{ max-width: 1400px; }} .qty-control button {{ width: 44px; height: 44px; }}
#meals-list {{ grid-template-columns: repeat(3, 1fr); }} .qty-control .qty {{ width: 44px; height: 44px; }}
.edit-qty button {{ width: 44px; height: 44px; }}
.edit-qty span {{ width: 44px; height: 44px; line-height: 44px; }}
}} }}
.discount-banner {{ background: #dcfce7; color: #15803d; padding: 10px 16px; border-radius: 8px; margin-bottom: 20px; font-size: 0.85rem; text-align: center; font-weight: 500; }} .discount-banner {{ background: #dcfce7; color: #15803d; padding: 10px 16px; border-radius: 8px; margin-bottom: 20px; font-size: 0.85rem; text-align: center; font-weight: 500; }}
.price-retail {{ text-decoration: line-through; color: #9ca3af; font-size: 0.75rem; margin-right: 4px; }} .price-retail {{ text-decoration: line-through; color: #9ca3af; font-size: 0.75rem; margin-right: 4px; }}
@ -321,6 +322,15 @@ body {{ padding-bottom: 80px; }}
.admin-panel {{ background: #fff; border-radius: 12px; padding: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }} .admin-panel {{ background: #fff; border-radius: 12px; padding: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }}
.admin-header {{ display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; flex-wrap: wrap; gap: 12px; }} .admin-header {{ display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; flex-wrap: wrap; gap: 12px; }}
.admin-header h2 {{ font-size: 1.2rem; font-weight: 700; margin: 0; }} .admin-header h2 {{ font-size: 1.2rem; font-weight: 700; margin: 0; }}
.admin-toolbar {{ display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }}
.admin-toolbar select {{ padding: 8px 12px; border: 1px solid #d1d5db; border-radius: 8px; font-size: 0.9rem; }}
.admin-toolbar-btn {{ margin: 0; padding: 8px 16px; font-size: 0.85rem; background: #1a1a2e; color: #fff; border: none; border-radius: 8px; cursor: pointer; font-weight: 600; }}
.admin-toolbar-btn:disabled {{ opacity: 0.4; cursor: not-allowed; }}
.admin-toolbar .back-btn {{ margin: 0; padding: 8px 16px; font-size: 0.85rem; }}
@media (max-width: 600px) {{
.admin-toolbar {{ width: 100%; }}
.admin-toolbar > * {{ flex: 1 1 100%; }}
}}
.admin-stats {{ font-size: 0.9rem; color: #6b7280; margin-bottom: 16px; }} .admin-stats {{ font-size: 0.9rem; color: #6b7280; margin-bottom: 16px; }}
.admin-stats strong {{ color: #1d1d1f; }} .admin-stats strong {{ color: #1d1d1f; }}
.admin-table-wrap {{ overflow-x: auto; }} .admin-table-wrap {{ overflow-x: auto; }}
@ -416,11 +426,11 @@ body {{ padding-bottom: 80px; }}
<div class="admin-panel"> <div class="admin-panel">
<div class="admin-header"> <div class="admin-header">
<h2>Order Admin</h2> <h2>Order Admin</h2>
<div style="display:flex;gap:8px;align-items:center;"> <div class="admin-toolbar">
<select id="admin-week" onchange="loadWeekOrders(this.value)" style="padding:8px 12px;border:1px solid #d1d5db;border-radius:8px;font-size:0.9rem;"></select> <select id="admin-week" onchange="loadWeekOrders(this.value)"></select>
<button id="admin-download-btn" onclick="downloadOrderList()" style="margin:0;padding:8px 16px;font-size:0.85rem;background:#1a1a2e;color:#fff;border:none;border-radius:8px;cursor:pointer;font-weight:600;" disabled>Download order list</button> <button id="admin-download-btn" class="admin-toolbar-btn" onclick="downloadOrderList()" disabled>Download order list</button>
<button id="admin-pdf-btn" onclick="downloadSummaryPdf()" style="margin:0;padding:8px 16px;font-size:0.85rem;background:#1a1a2e;color:#fff;border:none;border-radius:8px;cursor:pointer;font-weight:600;">Download summary PDF</button> <button id="admin-pdf-btn" class="admin-toolbar-btn" onclick="downloadSummaryPdf()">Download summary PDF</button>
<button onclick="hideAdmin()" class="back-btn" style="margin:0;padding:8px 16px;font-size:0.85rem;">Back to Menu</button> <button onclick="hideAdmin()" class="back-btn">Back to Menu</button>
</div> </div>
</div> </div>
<div id="admin-stats" class="admin-stats"></div> <div id="admin-stats" class="admin-stats"></div>