Table ordering
Open Order for the selected venue. The app requires a table number before exposing the menu. Choose categories, select an item, set options and quantity, then review the basket in the existing slide-up sheet. The basket and table belong to one venue.
Current limitations
The browser presenter simulates an order result. The native source does not yet have a complete live catalogue/SQLite driver/settled-payment integration. A timeout must not cause a duplicate server draft; preserve the same request idempotency key until reconciliation. Do not consider an on-screen demo receipt a real kitchen order.
The intended table-ordering sequence
HSLG's ordering flow is venue-scoped and table-first. Select the correct venue, enter or scan the table number, then browse the menu. This ordering prevents a customer from preparing a basket without a restaurant/table context. Each item and its options belong to the selected venue's catalogue. The customer can add quantities, inspect selections in the existing slide-up basket, change quantities and continue towards checkout. Switching venue must never silently carry a table assignment or priced basket into the new venue.
The shared application contains the table flow and visual basket interaction, but the WordPress presenter currently demonstrates ordering with sample products. Its example receipt is not a kitchen instruction. In native source the catalogue is intentionally empty until a real content/price provider is connected, and order submission currently refuses unsupported actions. That is a safety rule, not a missing success animation.
Table number and QR use
Customers should first check that the venue shown in the header matches their physical venue. Enter the table number printed at the table, or use the Scan Table control when the genuine native QR scanner is available. A QR value is treated as a proposed destination and passes an allowlisted URL resolver. A malformed code, unknown host or mismatched venue must not change the basket or submit an order. Scanning does not authenticate the customer or authorize payment. If the camera is denied or cancelled, the normal table-entry method must remain usable.
Building a basket
Choose a category, product and configured options. Use the quantity control to adjust items before adding them. The basket should show an understandable label, selected options, quantity, subtotal and venue/table context. A quantity or option change can make an earlier server quote invalid, so any displayed price must be updated using current server-owned pricing rather than trusting a client calculation. If a product becomes unavailable or an option is no longer permitted, the app needs a clear correction state instead of discarding the whole basket.
The current UI is more complete than the backend integration. Draft persistence exists in source but not as a completed end-to-end native flow with SQLite, live menu availability and kitchen acknowledgement. Until that work is tested, the app should not present the draft as a paid or accepted order.
What an order draft means
An unpriced server draft records the customer, venue, table and proposed line items. Its idempotency key identifies one logical create request. The server can return an existing matching draft when the same request is retried. A draft is not a final amount, card authorization, kitchen ticket or commitment that stock is available. The backend explicitly labels its response as saved only—not priced, paid or submitted. This distinction needs to be visible in every customer state and support record.
When connectivity disappears after submission, the app cannot know whether the server received the request merely from the timeout. It must look up the original idempotency key and reconcile. Generating a fresh key and submitting blindly could create duplicate drafts. Payments require even stricter provider reconciliation because an uncertain card result must not cause a second charge. Preserve the basket while the result is unresolved.
Offline behaviour
Without network access, keep the local editing context and show an offline indication. The source includes an outbox design, but the required native SQLite integration and device verification are unfinished. Do not promise that an unfinished outbox will reliably survive force-quit, low storage, OS eviction or phone replacement. Once supported, queued changes should have a clear state: local only, pending transmission, server draft saved, quote received, payment pending, accepted, failed or needs attention. Only a server-confirmed state may drive a real restaurant fulfilment action.
If the HSLG health endpoint is unavailable even though Wi-Fi/mobile data is connected, label the problem as a service outage. Do not substitute a cached demo catalogue or successful checkout response in a production build.
Checkout and payment
The final payable amount must come from server pricing based on authenticated venue/catalogue data. Before taking a payment, the app needs a server quote with its expiry/identifier, configured Stripe account mapping for the correct venue, a native PaymentSheet integration and provider webhook reconciliation. The customer must see the venue being paid, accurate total, any fees, cancellation policy and confirmed next step. The current source has payment boundary components but does not have a verified live PaymentSheet, so payment submission is disabled.
Do not ask for full card details in a custom HSLG form or store PAN/CVC in MariaDB, logs or WordPress posts. The payment provider manages sensitive card entry. A returned client-side success screen is not authoritative if provider/server settlement evidence is missing.
Example troubleshooting cases
If the menu is empty, verify whether the live menu provider is configured before assuming the restaurant has no items. If a QR resolves to the wrong venue, reject it and reselect the venue. If a basket displays a stale amount, require a new quote. If checkout reports an unknown result, retain the request identifier and reconcile instead of creating a new payment. If kitchen acceptance is unavailable, do not treat payment alone as proof that food is being prepared. Every support ticket should retain the non-secret order/draft identifier, venue, table, client version and server response category.
Operator evidence needed before live ordering
A real MariaDB migration must pass, server prices must match a known menu, API authorization must reject cross-customer reads, a draft must survive a timeout/retry, the native SQLite store must survive app restart, and the payment account must belong to the intended venue. Test one successful and one deliberately failed sandbox payment, provider webhook receipt, duplicate webhook delivery and refund/timeout reconciliation. Record the phone model, APK version, server plugin versions and logs stripped of customer secrets. Until these tests pass, the ordering journey remains a demonstration rather than an available service.