Reservation System Development Guide - Session 10
This guide helps developers understand how to implement, update, and maintain the ticket reservation system. It summarizes changes from commits and provides step-by-step actions, grouped by feature area. https://github.com/MehrdadShirvani/AlibabaClone-Frontend/commits/develop/
Fixes and Missing Things from Session 08
Authentication & Protected Routes
- Add session persistence in
authStore
to store token more persistently
import { create } from "zustand";
import { createJSONStorage, persist } from "zustand/middleware";
import { AuthResponseDto } from "@/shared/models/authentication/AuthResponseDto";
interface AuthState {
user: AuthResponseDto | null;
login: (user: AuthResponseDto) => void;
logout: () => void;
}
export const useAuthStore = create<AuthState>()(
persist(
(set) => ({
user: null,
login: (user: AuthResponseDto) => set({ user }),
logout: () => set({ user: null }),
}),
{
name: "auth-storage", // storage key in localStorage
storage: createJSONStorage(() => localStorage),
}
)
);
Profile and User Info Enhancements
- Fix and align
birthDate
types inPersonDto
,TransportationSearchResult
, andListOfTravelers
. Make sure to useDate | string
data type for them
Branching
- Create the feature/themes branch based on develop
🎨 Theming and UI Styling
- Install and import
preline
npm install preline
- Add theme colors and global styles (index.css). Take a look at their Documentation
- Add
ThemeSwitcher
and integrate it into the navbar - If you decide to do this part after implementing pages, make sure to add theme support to the following components:
-
transportationCard
,transportationSearchForm
,ReviewAndConfirm
- All modals:
LoginModal
,RegisterModal
,SelectFromPeopleModal
- Profile section:
ProfilePage
,ProfileSummary
,PersonalInformation
,AccountInfo
,PersonalAccountInfo
,BankAccountDetails
,MyTravels
,MyTransactions
,ListOfTravelers
- Reservation views and components
-
Merge
- Create a PR and merge the current branch with develop
Branching for reservation
- Create the feature/ticket-reservation branch based on develop
Backend Agent Methods
- Add
CreateTicketOrderDto
andCreateTravelerTicketDto
. Check backend endpoints for the dtos you need for this session - Add
TransportationSeatDto
- Add related methods in
TicketOrder
and add it to agent
const TicketOrder = {
create: (data : CreateTicketOrderDto) => request.post<number>('/ticketOrder/create', data),
downloadPdf: (ticketOrderId : number) => request.get<Blob>(`/ticketOrder/${ticketOrderId}/pdf`, {
responseType: 'blob',
}),
}
Reservation Process & Step Management
- Implement
useReservationStore
usingzustand
to manage reservation state
import { PersonDto } from '@/shared/models/account/PersonDto';
import { CreateTravelerTicketDto } from '@/shared/models/ticketOrder/createTravelerTicketDto';
import { TransportationSearchResult } from '@/shared/models/transportation/transportationSearchResult';
import { create } from 'zustand';
const defaultTraveler: CreateTravelerTicketDto = {
id: 0,
creatorAccountId: 0,
firstName: '',
lastName: '',
genderId: 0,
birthDate: '',
idNumber: '',
phoneNumber: '',
englishFirstName: '',
englishLastName: '',
isVIP: false,
seatId: null,
description: '',
};
type ReservationStep = "transportation" | "travelers" | "review" | "payment" | "success";
interface ReservationState {
transportation: TransportationSearchResult | null;
travelers: CreateTravelerTicketDto[];
ticketOrderId: number;
couponCode: string | null;
paymentInfo: any;
people: PersonDto[],
currentStep: ReservationStep,
isConfirmed: boolean,
isPayed: boolean,
isTravelerPartDone: boolean,
addTraveler: (traveler: CreateTravelerTicketDto) => void;
setTravelers: (travelers: CreateTravelerTicketDto[]) => void;
updateTraveler: (index: number, traveler: CreateTravelerTicketDto) => void;
removeTraveler: (index: number) => void;
setTicketOrderId: (newId: number) => void;
setTransportation: (transportation: TransportationSearchResult) => void;
setCouponCode: (code: string | null) => void;
setPaymentInfo: (info: any) => void;
setPeople: (people: PersonDto[]) => void;
setCurrentStep: (step: ReservationStep) => void;
setIsConfirmed: (value: boolean) => void;
setIsPayed: (value: boolean) => void;
setIsTravelerPartDone: (value: boolean) => void;
resetReservation: () => void;
}
export const useReservationStore = create<ReservationState>((set) => ({
transportation: null,
people: [],
travelers: [defaultTraveler],
couponCode: null,
paymentInfo: null,
ticketOrderId : 0,
currentStep: "transportation",
isConfirmed: false,
isPayed : false,
isTravelerPartDone : false,
setTicketOrderId: (newId) => set(() =>({
ticketOrderId : newId
})),
addTraveler: (traveler) => set((state) => ({ travelers: [...state.travelers, traveler] })),
setTravelers: (newTravelers) => set(() => ({
travelers : newTravelers
})),
setPeople: (newPeople) => set(() => ({
people : newPeople
})),
updateTraveler: (index, traveler) =>
set((state) => {
const updated = [...state.travelers];
updated[index] = traveler;
return { travelers: updated };
}),
removeTraveler: (index) =>
set((state) => {
if (state.travelers.length <= 1) return state;
const updated = [...state.travelers];
updated.splice(index, 1);
return { travelers: updated };
}),
setTransportation: (theTransportation) => set({ transportation: theTransportation }),
setCouponCode: (code) => set({ couponCode: code }),
setPaymentInfo: (info) => set({ paymentInfo: info }),
setCurrentStep: (step) => set({ currentStep: step }),
resetReservation: () =>
set({
transportation: null,
travelers: [],
ticketOrderId: 0,
couponCode: null,
paymentInfo: null,
people: [],
currentStep: "transportation",
isConfirmed: false,
isPayed: false,
isTravelerPartDone: false
}),
setIsConfirmed: (value) => set(() => ({
isConfirmed : value
})),
setIsPayed: (value) => set(() => ({
isPayed : value
})),
setIsTravelerPartDone: (value) => set(() => ({
isTravelerPartDone : value
})),
}));
-
Create step-based routing using
ReservationLayout
. Step-based routing, in the context of contact centers or workflow management, refers to a method of directing work items (like customer service calls or support tickets) to the most appropriate agent or resource based on a series of predefined steps or conditions. -
Add routing for reservation steps in
App.tsx
-
Add
StepIndicator
component to show step progress visually (optional)- Add
stepGuard
logic to prevent accessing future steps prematurely - Add logic to skip back only if previous steps are completed
- Add
-
Create
TravelerForm
to gather passenger info, with the possibility to load data from the related people of the account. -
Create
TravelerDetailsForm
to gather passengers info withTravelerForm
integration -
Create
ReviewAndConfirm
page to review selections -
Create
PaymentForm
for transaction process -
Create
TicketIssued
page for confirmation -
Add validation to show error if
seatId
is missing
Seat Selection
- Add DTO:
export interface transportationSeatDto{
id : number,
vehicleId : number,
row : number,
column : number,
isVIP : boolean,
isAvailable : boolean,
description : string | null,
isReserved : boolean,
genderId : number | null
}
- Add
getSeats()
method toagent.ts
- Add
SeatGridSelector
component for graphical seat layout inTravelerDetailForm
and integrate it with traveler list, only for Buses - Modify
TransportationCard
to integrate with seat selection - Add
SeatOnlyGridSeatMap
for simpler seat-only display
Coupon Integration
- Add
CouponValidationRequestDto
andDiscountDto
- Add
validateCoupon()
method toagent.ts
- Update
useReservationStore
to includeCouponCode
- Ensure
CreateTicketOrderDto
usesCouponCode
instead ofcouponId
- Connect coupon validation flow in
ReviewAndConfirm
Search, Filter, and Sort Functionality
- Add filters (company) and sorting (time or price) UI to
SearchResultPage
- Add company logo support in result cards and filters
- Add
previous/next day
buttons for time navigation - Add remaining capacity check to transportation cards
- Add refund policy info display
- Implement showing seat map in
TransportaionCard
usingReadOnlySeatMap
📎 Notes
- Ensure you run a full theme test after UI changes.
- Test step transitions with various invalid scenarios.
- Confirm persistent session and coupon behavior across refreshes.
- Validate all filters, sort, and search navigation works.
- Test seat selection and proper rendering of rotated layouts.
Merge
- Create a PR and merge the current branch with develop