Skip to content

rcadavos/ticketing

Repository files navigation

BonVoyage

A Next.js 15 ferry / sea-travel ticketing system for the Philippines. Reserve online, pay over the counter, board with an offline-capable QR e-ticket. Built to the conventions in CLAUDE.md.

Stack

Next.js 15 (App Router, RSC) · React 19 · TypeScript · Supabase (Postgres + Auth + RLS) · TanStack Query + Table · Tailwind v4 + shadcn/ui · Serwist (PWA) · Vercel.

Getting started

pnpm install
cp .env.example .env.local   # fill in Supabase + app secrets
pnpm dev

The app runs without Supabase for UI work — voyage search shows demo data. Booking, auth, and manifests require a connected database.

Database setup (Supabase)

Apply the migrations in order, then (optionally) the seed and the cron job:

# Using the Supabase SQL editor or psql against your project:
db/migrations/0001_schema.sql
db/migrations/0002_functions.sql
db/migrations/0003_rls.sql
db/migrations/0005_seed_cokaliong.sql   # REAL data: Cokaliong fleet/routes/schedules/fares
db/migrations/0006_booth.sql            # booth (agent) walk-in + voyage-manifest RPCs
db/cron.sql                             # schedules expire_holds() every minute

Use either 0004_seed.sql (tiny demo) or 0005_seed_cokaliong.sql (real Cokaliong network: 16 ports, 11 vessels, 37 routes, 197 sailings, real fares) — not both (their port codes collide). 0005 is the realistic dataset for the booth.

Regenerate typed bindings after schema changes:

pnpm db:types

Creating a booth agent (and other staff)

There is no public sign-up. Create the auth user first, then grant a role in the staff table. Roles: cashier (booth agent — sells walk-in tickets), purser (view + download manifests), ops, admin.

-- 1) create the auth user (Supabase dashboard → Authentication → Add user), then:
insert into staff (id, role, full_name)
values ('<auth-user-uuid>', 'cashier', 'Booth Agent 1');

Ticketing booth (agent) — the current focus

The customer-facing pages are temporarily hidden (they redirect to the agent app; remove the redirect() in app/(public)/layout.tsx to re-enable). The booth flow:

  1. Agent signs in at /login → lands on the dashboard.
  2. /admin/booth — filter by route/date and pick a vessel/voyage.
  3. /admin/booth/[voyageId] — choose a class, enter passenger details, take the cash, type the OR number, and Confirm & issue tickets. The seat hold, booking, passengers, payment, and e-tickets are written atomically (create_walkin_booking), so a voyage can never be oversold. The per-vessel passenger list updates live.

Manifest download (/admin/manifests, CSV) remains limited to purser/ops/admin.

Scripts

Command Description
pnpm dev Dev server
pnpm build Production build (also builds the Serwist service worker)
pnpm typecheck tsc --noEmit
pnpm lint ESLint
pnpm test Vitest unit tests
pnpm format Prettier

Key flows

  • Booth walk-in (agent). Agent picks a vessel/voyage → enters passengers → takes cash → create_walkin_booking holds seats, creates the confirmed booking + passengers + payment + e-tickets in one transaction. Overselling is impossible.
  • Manifests. Per-voyage passenger list is visible to the booth agent live; purser/ops/ admin can also download CSV at /admin/manifests.
  • Holds expire. expire_holds() (scheduled via db/cron.sql) releases unpaid online holds. (Booth sales are paid immediately, so they don't expire.)
  • (Hidden for now) Customer self-service (search → reserve → pay OTC → offline QR e-ticket) is built via create_reservation but disabled while the focus is the agent app.

Security

  • Nonce-based CSP in middleware.ts; static headers (HSTS, X-Frame-Options, etc.) in next.config.ts — targets securityheaders.com Grade A (Referrer-Policy intentionally omitted; see CLAUDE.md §8).
  • RLS on every table; service_role key is server-only.
  • All input validated with Zod at every boundary.

Deploy (Vercel)

Push to a Vercel project, set the environment variables from .env.example, and deploy. After deploy, scan the URL on https://securityheaders.com to confirm the grade.

About

Streamline ferry operations by managing routes, schedules, vessels, ticket sales, passenger manifests, boarding, fare collection, trip monitoring, and operational reports—all from one centralized dashboard.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors