Shitaye-FrontEnd/ADMIN_BOOKING_README.md
“kirukib” 1a37b91795 feat: soften brand gold, hero copy; OpenNext Cloudflare config
- Replace flat mustard with softer champagne tones and gentler shadows
- Hero eyebrow: Book direct · Shitaye Suite Hotel
- Lighter pattern grid, chips, badges, card hover ring; meetings band ring toned down
- Ignore .dev.vars and .wrangler for local secrets and cache

Made-with: Cursor
2026-03-25 00:18:51 +03:00

8.5 KiB
Raw Blame History

Booking & payments — administrator panel specification

This document describes the guest booking domain as implemented in the Shitaye FrontEnd demo today, and what a separate administrator application should support to manage bookings, holds, and payments. Use it as a blueprint when you build the admin API, database schema, and UI.

The public site lives in this repository (Shitaye-FrontEnd). The admin panel is not included here; this README is the handoff for that work.


1. Goals of the admin system

  • List and search reservations (by date, status, guest, reference, room, payment state).
  • Open a booking and see full guest, stay, pricing, flight/arrival, coupons, and payment metadata.
  • Reconcile payments (paid, pending, failed, refunded) against holds or confirmed bookings.
  • Operational actions (policy-dependent): cancel hold, extend hold, mark no-show, issue refund, add internal notes, export for finance.

2. Current public app (this repo) — important limitations

Today the storefront is a client-side mock:

  • State lives in React context (BookingProvider) in the browser — nothing is persisted to your backend when a guest “books”.
  • submitBookingHold and processPayment in src/lib/mocks/api.ts only simulate latency and return fake IDs (SHY-…, PAY-…).
  • No real card processing, no webhooks, no idempotent payment IDs.

Implication for admin: you will introduce a real backend (or extend an existing PMS/booking engine). The admin panel should talk to that system, not to the in-memory Next.js state.

Reference files in this repo

Area Path
Guest & stay state src/context/BookingContext.tsx
Guest shape GuestDetails in same file
Hold / payment mock API src/lib/mocks/api.ts
Room catalogue (ids, rates) src/lib/mocks/rooms.ts
Tax rate src/lib/mocks/site.ts (taxRate, e.g. 0.15 = 15%)

3. Domain model (what to persist)

3.1 Guest (contact + arrival)

Aligned with GuestDetails:

Field Type Notes
firstName string
lastName string
email string Primary contact; unique per booking or account policy TBD
phone string E.164 recommended in production
flightBookingNumber string PNR / record locator / ticket ref
arrivalTime string Currently HH:mm from UI; store as time or datetime with timezone (Addis Ababa) in production

3.2 Stay

Field Type Notes
checkIn date (ISO date) YYYY-MM-DD in UI
checkOut date (ISO date)
guests integer 112 in UI
roomId string Catalogue key: penthouse, standard, connecting-suite, junior-studio (see rooms.ts)
nights integer Derived; validate against check-in/out

3.3 Pricing (display currency vs ledger)

The storefront shows USD catalogue rates on the server-side math, with an optional display currency (EUR, GBP, AED, etc.) via CurrencyContext / src/lib/currency.ts.

Admin / accounting recommendation

  • Store amounts in a single base currency (e.g. ETB or USD) per property policy.
  • Store FX snapshot at booking or payment time if you show multi-currency to guests.
  • Line items to persist (mirroring checkout):
Concept Source in app
Nightly subtotal nightlyRate × nights from room catalogue
Coupon code string
Discount % e.g. 10 or 5 (mock codes SHITAYE10, WELCOME5)
Discount amount % of subtotal
Tax siteConfig.taxRate × taxable base (after discount)
Total Grand total charged or to be charged

3.4 Hold vs payment (lifecycle)

The UI distinguishes:

Concept Flag / field Meaning
Hold reference holdReference e.g. SHY-… — created when guest continues from /booking (pay now or pay later path)
Pay later payLaterHold true if guest chose “Reserve now — pay later” before visiting payment
Payment confirmation confirmationId e.g. PAY-… after successful (mock) payment
Paid timestamp paidAt ISO datetime string

Suggested persisted statuses (you can rename):

  1. draft — abandoned cart (optional)
  2. held — hold created, not paid (payLaterHold may be true or false; both paths create a hold in the current flow)
  3. payment_pending — guest on payment step (optional transient)
  4. confirmed — payment succeeded (confirmationId + paidAt)
  5. cancelled / expired — hold released or timeout

Map the mocks payLaterHold to your policy: e.g. held unpaid vs held with intent to pay later.


4. Mock API payloads (prototypes for real endpoints)

Todays TypeScript types in src/lib/mocks/api.ts:

4.1 Create hold (after guest details + flight)

BookingPayload:

  • roomId, email, flightBookingNumber, arrivalTime

Real API should also accept: checkIn, checkOut, guests, full guest name/phone, pricing breakdown, coupon fields — everything needed to reconstruct the reservation without trusting the client for totals.

Response (mock): { reference: string }

4.2 Process payment

PaymentPayload:

  • totalCents (integer; mock uses USD × 100)
  • last4 (optional; card last four — never store full PAN in admin DB)

Response (mock): { confirmationId: string, paidAt: string }

Production: integrate PSP (Stripe, Chapa, etc.), store payment intent ID, status, receipt URL, and audit trail; admin reads from your payment service or synced tables.


5. Room catalogue keys (admin filters & reports)

Use the same id values as src/lib/mocks/rooms.ts unless you migrate to UUIDs:

roomId Display name (short)
penthouse The 4 Bedroom Penthouse
standard Standard Rooms
connecting-suite Connecting Suite
junior-studio Junior Studios

Each room has nightlyRate (USD in mock), maxGuests, slug for public URLs.


6.1 Dashboard

  • Todays arrivals / departures
  • Unpaid holds (pay-later + overdue)
  • Revenue snapshot (range selector)

6.2 Bookings list

  • Filters: status, date range (stay or created), room, email, hold ref, payment ref
  • Sort: check-in, created at, total
  • Bulk export CSV (finance)

6.3 Booking detail

  • Guest, stay, room, pricing lines, coupon, flight/PNR, arrival time
  • Payment section: provider, amount, currency, status, timestamps, refund button (if allowed)
  • Internal notes (staff-only), activity log

6.4 Payments

  • List transactions linked to bookings
  • Reconciliation view (settled vs pending)
  • Manual “mark paid” only if you accept bank transfer / cash — with strict RBAC

6.5 Configuration (optional)

  • Tax rate, active coupon codes, hold TTL, room rates (or sync from PMS)

7. Security & compliance

  • RBAC: roles such as viewer, front_desk, finance, superadmin.
  • PII: encrypt at rest where required; minimize data in logs; GDPR-style export/erase if you serve EU/UK guests.
  • PCI: never store raw card data; use tokenization via your PSP; admin UI shows only last4 / brand if provided.
  • Audit: who changed status, refunds, or manual overrides.

8. Integrating the public Next.js app later

Replace src/lib/mocks/api.ts calls with fetch/axios to your backend:

  1. POST /bookings/hold — persist reservation + return real holdReference
  2. POST /bookings/:id/pay or PSP redirect + webhook — update status to confirmed
  3. Optional GET /bookings/:ref for guest “lookup my booking”

The admin app should use the same API (or an internal admin API with stronger scopes) so there is a single source of truth.


9. Open decisions (product / engineering)

  • Single vs multi-property admin
  • Whether “pay later” holds expire automatically and how guests resume payment (magic link vs login)
  • Official currency of record and whether ETB is required for local compliance
  • Connection to an existing PMS (Opera, Cloudbeds, etc.) vs custom DB only

10. Document maintenance

When you change the guest booking flow in Shitaye-FrontEnd, update:

  • Section 3 (fields), 4 (payloads), and 5 (room ids)
  • This file path: ADMIN_BOOKING_README.md (repository root)

Prepared for Yaltopia / Shitaye Suite Hotel — booking management administrator development.