Skip to content

Govind9012/flight-management-system

Repository files navigation

SkyWay — Flight Management PWA

A production-grade Flight Management Progressive Web Application built for a hiring evaluation. Demonstrates real-world engineering patterns: atomic database operations, realtime subscriptions, SSR-safe auth, and strict TypeScript throughout.

Live stack: Next.js 16.2 (App Router + Turbopack) · Supabase · Zustand 5 · Tailwind CSS · shadcn/ui · TypeScript strict


Features

Feature Details
Flight search Filter by origin, destination, date, passenger count
Interactive seat map Supabase Realtime — seat state updates live across sessions
Booking flow Multi-step: search → seat selection → passenger details → PNR
My Bookings View, cancel, and reschedule with confirmation dialogs
Auth Email/password via Supabase Auth with SSR-safe session handling
PWA Installable; manual service worker (StaleWhileRevalidate + CacheFirst)
Accessibility ARIA labels, keyboard navigation, live regions on seat map

Architecture

src/
├── app/                         # Next.js App Router
│   ├── (main)/                  # Shell layout (Navbar + Footer)
│   │   ├── page.tsx             # Home (hero + search)
│   │   ├── flights/results/     # Flight results list
│   │   ├── flights/[id]/seats/  # Seat selection (SSR initial seats)
│   │   ├── booking/             # Passenger details + confirmation
│   │   └── my-bookings/         # Booking management
│   └── auth/                    # Login / signup pages
├── components/
│   ├── flights/                 # FlightCard, FlightSearchForm
│   ├── seat-map/                # SeatMap (Realtime)
│   └── ui/                      # shadcn/ui primitives
├── lib/
│   ├── supabase/                # client.ts, server.ts, middleware.ts
│   ├── constants/               # airports, aircraft configs
│   └── utils/                   # cn, format, date helpers
├── services/                    # Data access layer (bookings, flights, seats)
├── stores/                      # Zustand stores (useFlightStore, useUserStore)
└── types/                       # database.ts (generated Supabase types)

Key design decisions

Atomic seat booking (RPC) Seat reservation uses a Postgres function called via Supabase RPC. The function checks availability and inserts the booking inside a single transaction — preventing double-booking under concurrent load without application-level locking.

SSR-safe auth @supabase/ssr v0.6 with createServerClient / createBrowserClient. Session cookies are read/written in middleware (src/proxy.ts) on every request. No client-side token storage.

Zustand partialize useFlightStore persists only selectedSeat and optimisticSeatId to sessionStorage. Fields like bookingStep are intentionally excluded — they are derived from URL navigation, not state, avoiding stale-step bugs on page reload.

Realtime seat eviction When another user claims a seat the current user has selected, the Supabase Realtime handler detects the conflict (updated.is_available === false && selectedSeat.id === updated.id) and automatically clears the selection, showing a visible warning.

Manual service worker next-pwa is incompatible with Turbopack. A hand-written public/sw.js registers two strategies:

  • StaleWhileRevalidate for Supabase API calls
  • CacheFirst for static assets (/_next/static/)

TypeScript strict strict: true, noUncheckedIndexedAccess: true, exactOptionalPropertyTypes: true. All Supabase query results cast through as unknown as T to bridge the generated type/inference gap.


Database schema (Supabase)

Table Key columns
profiles id (FK → auth.users), full_name, email
flights id, origin, destination, departure_time, arrival_time, aircraft_type, base_price, status
seats id, flight_id, seat_number, class, is_available, extra_fee
bookings id, user_id, flight_id, seat_id, pnr_code, passenger_name, status, total_price

RLS policies restrict all reads/writes to the authenticated user's own rows. The seat-locking RPC runs with SECURITY DEFINER to atomically check + reserve within the same transaction.


Local development

Prerequisites

  • Node.js 20+
  • A Supabase project (free tier works)

Setup

git clone <repo>
cd <repo>
npm install

Create .env.local:

NEXT_PUBLIC_SUPABASE_URL=https://<project>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<anon-key>

Run the SQL migrations in supabase/migrations/ (or paste into the Supabase SQL editor), then:

npm run dev       # Turbopack dev server → http://localhost:3000
npm run build     # Production build
npm run lint      # ESLint
npx tsc --noEmit  # Type check

PWA / Lighthouse

The app passes all PWA installability checks:

  • public/manifest.json with 192×192 and 512×512 icons
  • public/sw.js service worker registered in root layout
  • HTTPS required in production (Vercel / any HTTPS host)

Recommended deployment: Vercel — zero-config Next.js with automatic Edge Functions for middleware.


Engineering notes

  • All data fetching in Server Components passes cookies() for SSR auth — no client waterfalls on initial load
  • SeatMap uses a single Supabase Realtime channel per flight, unsubscribed on unmount
  • MyBookingsClient uses a useRef cache pattern to prevent infinite useEffect re-runs when booking data changes
  • Error boundary (error.tsx) and 404 page (not-found.tsx) are airline-themed for UX consistency
  • BookingCard is extracted into its own component for single-responsibility and testability

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors