mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 21:20:57 +00:00
337 lines
9.2 KiB
Markdown
337 lines
9.2 KiB
Markdown
# EDR Passenger Portal
|
|
|
|
Modern Next.js 14 web application for the Ethio-Djibouti Railway passenger booking system.
|
|
|
|
## Features
|
|
|
|
### Complete Booking Flow
|
|
1. **Search** - Find trains by route, date, and passenger count
|
|
2. **Results** - View available schedules with pricing
|
|
3. **Auth Check** - Sign in or continue as guest
|
|
4. **Passengers** - Collect passenger details with Fayda verification
|
|
5. **Seats** - Select seats with visual seat map
|
|
6. **Review** - Confirm booking details and fare breakdown
|
|
7. **Payment** - Choose payment method and process payment
|
|
8. **Confirmation** - View PNR, tickets with QR codes
|
|
|
|
### Key Capabilities
|
|
- **Fayda 2.0 Integration** - Ethiopian national ID verification
|
|
- **Age-Based Pricing** - First child travels free
|
|
- **Multi-Currency Support** - ETB, DJF, USD display
|
|
- **Seat Hold System** - 2-hour seat reservation
|
|
- **Guest Booking** - Book without account, optional registration
|
|
- **QR Code Tickets** - Digital tickets with QR codes
|
|
- **Responsive Design** - Mobile-first, works on all devices
|
|
|
|
## Tech Stack
|
|
|
|
- **Framework:** Next.js 14 with App Router
|
|
- **Styling:** Tailwind CSS
|
|
- **State Management:**
|
|
- TanStack Query (React Query) for server state
|
|
- Zustand for client state (booking flow, auth, payment)
|
|
- **Forms:** React Hook Form with Zod validation
|
|
- **API Client:** Axios with interceptors
|
|
- **Date Handling:** date-fns
|
|
- **QR Codes:** qrcode.react
|
|
|
|
## Getting Started
|
|
|
|
### Prerequisites
|
|
- Node.js >= 20.x
|
|
- pnpm >= 9.x
|
|
- EDR Passenger API running on port 3002
|
|
|
|
### Installation
|
|
|
|
```bash
|
|
# Install dependencies
|
|
pnpm install
|
|
|
|
# Create environment file
|
|
cp .env.example .env.local
|
|
|
|
# Update .env.local with API URL
|
|
NEXT_PUBLIC_API_URL=http://localhost:3002
|
|
```
|
|
|
|
### Development
|
|
|
|
```bash
|
|
# Run development server
|
|
pnpm dev
|
|
|
|
# Access at http://localhost:5174
|
|
```
|
|
|
|
### Build
|
|
|
|
```bash
|
|
# Build for production
|
|
pnpm build
|
|
|
|
# Start production server
|
|
pnpm start
|
|
```
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
src/
|
|
├── app/ # Next.js App Router pages
|
|
│ ├── booking/
|
|
│ │ ├── search/ # Search trains
|
|
│ │ ├── results/ # Search results
|
|
│ │ ├── auth-check/ # Login or guest
|
|
│ │ ├── passengers/ # Passenger details + Fayda
|
|
│ │ ├── seats/ # Seat selection
|
|
│ │ ├── review/ # Booking review
|
|
│ │ ├── payment/ # Payment processing
|
|
│ │ └── confirmation/ # Booking confirmation
|
|
│ ├── login/ # Login page
|
|
│ ├── layout.tsx # Root layout
|
|
│ ├── page.tsx # Home (redirects to search)
|
|
│ ├── providers.tsx # React Query provider
|
|
│ └── globals.css # Global styles
|
|
├── components/ # Reusable components
|
|
├── lib/ # Core utilities
|
|
│ ├── api-client.ts # Axios client with interceptors
|
|
│ ├── auth-store.ts # Auth state (Zustand)
|
|
│ ├── booking-store.ts # Booking flow state (Zustand)
|
|
│ └── payment-store.ts # Payment state (Zustand)
|
|
├── types/ # TypeScript types
|
|
│ └── index.ts
|
|
└── hooks/ # Custom React hooks
|
|
```
|
|
|
|
## State Management
|
|
|
|
### Booking Store (Zustand)
|
|
Persists booking flow state across pages:
|
|
- Search criteria
|
|
- Selected schedule
|
|
- Passenger details
|
|
- Seat hold information
|
|
- Booking ID and PNR
|
|
- Payment method
|
|
|
|
### Auth Store (Zustand)
|
|
Manages user authentication:
|
|
- User profile
|
|
- JWT token
|
|
- Login/logout/register
|
|
- Persisted to localStorage
|
|
|
|
### Payment Store (Zustand)
|
|
Tracks payment flow:
|
|
- Payment intent ID
|
|
- Payment status
|
|
- Selected currency
|
|
|
|
## API Integration
|
|
|
|
### Endpoints Used
|
|
|
|
| Endpoint | Method | Purpose |
|
|
|----------|--------|---------|
|
|
| `/stations` | GET | Fetch all stations |
|
|
| `/search` | POST | Search available trains |
|
|
| `/passengers/verify-fayda` | POST | Verify Ethiopian national ID |
|
|
| `/seatmap/{scheduleId}` | GET | Get coaches and seats |
|
|
| `/seatmap/{scheduleId}/hold` | POST | Hold seats (2 hours) |
|
|
| `/bookings/create` | POST | Create booking + generate PNR |
|
|
| `/bookings/{id}/confirm` | PATCH | Confirm booking after payment |
|
|
| `/payments/intent` | POST | Create payment intent |
|
|
| `/auth/login` | POST | User login |
|
|
| `/auth/register` | POST | User registration |
|
|
|
|
## Booking Flow
|
|
|
|
### 1. Search
|
|
- User selects origin, destination, date, passengers
|
|
- Validates form with Zod schema
|
|
- Stores criteria in booking store
|
|
- Navigates to results
|
|
|
|
### 2. Results
|
|
- Fetches schedules from API
|
|
- Displays available trains with pricing
|
|
- User selects a schedule
|
|
- Stores selection and navigates to auth check
|
|
|
|
### 3. Auth Check
|
|
- Checks if user is authenticated
|
|
- Offers "Sign In" or "Continue as Guest"
|
|
- Authenticated users can use saved profiles
|
|
|
|
### 4. Passengers
|
|
- Collects details for each passenger
|
|
- **Ethiopian nationals:** Fayda verification
|
|
- Calls `/passengers/verify-fayda`
|
|
- Auto-fills name and DOB on success
|
|
- Allows manual entry on failure
|
|
- **Non-Ethiopians:** Passport details
|
|
- Optional account creation checkbox
|
|
- Stores passenger data in booking store
|
|
|
|
### 5. Seats
|
|
- Fetches coaches and seat map
|
|
- Visual seat selection (4-column grid)
|
|
- Color-coded seat status:
|
|
- Green: Available
|
|
- Blue: Selected
|
|
- Yellow: Held by others
|
|
- Gray: Booked/Blocked
|
|
- Calls `/seatmap/{scheduleId}/hold` on selection
|
|
- Stores hold ID and expiry (2 hours)
|
|
- Option to skip (auto-assign)
|
|
|
|
### 6. Review
|
|
- Displays trip summary
|
|
- Lists all passengers
|
|
- Shows fare breakdown
|
|
- Displays seat hold countdown timer
|
|
- Calls `/bookings/create` on confirm
|
|
- Generates 6-character PNR
|
|
- Navigates to payment
|
|
|
|
### 7. Payment
|
|
- Displays PNR prominently
|
|
- Payment method selection:
|
|
- Telebirr
|
|
- CBE Birr
|
|
- eBirr
|
|
- Card
|
|
- Wallet
|
|
- Shows order summary
|
|
- Calls `/payments/intent`
|
|
- Processes payment (simulated for now)
|
|
|
|
### 8. Confirmation
|
|
- Calls `/bookings/{id}/confirm`
|
|
- Displays success message
|
|
- Shows PNR with copy button
|
|
- Generates QR codes for each ticket
|
|
- Lists all passenger tickets
|
|
- Download and share options
|
|
- "Book Another Trip" button clears state
|
|
|
|
## Form Validation
|
|
|
|
All forms use React Hook Form + Zod:
|
|
|
|
```typescript
|
|
// Example: Search form validation
|
|
const searchSchema = z.object({
|
|
originStationId: z.string().min(1, 'Please select origin'),
|
|
destinationStationId: z.string().min(1, 'Please select destination'),
|
|
departureDate: z.string().min(1, 'Please select date'),
|
|
adultCount: z.number().min(1).max(9),
|
|
childCount: z.number().min(0).max(9),
|
|
nationality: z.enum(['ETHIOPIAN', 'DJIBOUTIAN', 'OTHER']),
|
|
}).refine((data) => data.originStationId !== data.destinationStationId, {
|
|
message: 'Origin and destination must be different',
|
|
path: ['destinationStationId'],
|
|
});
|
|
```
|
|
|
|
## Styling
|
|
|
|
### Tailwind Utility Classes
|
|
Custom component classes in `globals.css`:
|
|
|
|
```css
|
|
.btn-primary /* Primary action button */
|
|
.btn-secondary /* Secondary action button */
|
|
.input-field /* Form input styling */
|
|
.card /* Card container */
|
|
```
|
|
|
|
### Theme Colors
|
|
Primary brand color: `rgb(20, 113, 76)` (EDR green)
|
|
|
|
Shades available: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900
|
|
|
|
## Error Handling
|
|
|
|
- Network errors: Retry button with exponential backoff
|
|
- Validation errors: Inline field-level messages
|
|
- API errors: User-friendly error messages
|
|
- Seat hold expiry: Alert and re-selection option
|
|
- 401 Unauthorized: Auto-redirect to login
|
|
|
|
## Accessibility
|
|
|
|
- Semantic HTML elements
|
|
- ARIA labels on interactive elements
|
|
- Keyboard navigation support
|
|
- Color contrast WCAG AA compliant
|
|
- Screen reader announcements for validation errors
|
|
|
|
## Mobile Responsiveness
|
|
|
|
- Mobile-first design approach
|
|
- Responsive grid layouts (md: breakpoint)
|
|
- Touch-friendly button sizes
|
|
- Scrollable seat maps on small screens
|
|
- Optimized forms for mobile input
|
|
|
|
## Testing Checklist
|
|
|
|
- [ ] Search form validation
|
|
- [ ] Results display and selection
|
|
- [ ] Guest vs authenticated flow
|
|
- [ ] Fayda verification (Ethiopian)
|
|
- [ ] Passport form (non-Ethiopian)
|
|
- [ ] Seat selection and hold
|
|
- [ ] Hold countdown timer
|
|
- [ ] PNR generation
|
|
- [ ] Payment method selection
|
|
- [ ] Confirmation with QR codes
|
|
- [ ] Mobile responsiveness
|
|
- [ ] Error states
|
|
- [ ] Back navigation
|
|
|
|
## Environment Variables
|
|
|
|
```bash
|
|
NEXT_PUBLIC_API_URL=http://localhost:3002 # Passenger API URL
|
|
```
|
|
|
|
## Known Limitations
|
|
|
|
1. Payment processing is simulated (no real provider integration yet)
|
|
2. Ticket PDF download not implemented (placeholder button)
|
|
3. Share booking feature not implemented (placeholder button)
|
|
4. Seat hold release on expiry requires manual refresh
|
|
5. No internationalization (English only)
|
|
|
|
## Future Enhancements
|
|
|
|
- [ ] Real payment provider integration (Stripe, Telebirr, etc.)
|
|
- [ ] PDF ticket generation and download
|
|
- [ ] Email/SMS sharing functionality
|
|
- [ ] Real-time seat availability updates (WebSocket)
|
|
- [ ] Booking history page
|
|
- [ ] User profile management
|
|
- [ ] Saved passenger profiles
|
|
- [ ] Multi-language support (Amharic, Arabic)
|
|
- [ ] Accessibility improvements
|
|
- [ ] Analytics tracking
|
|
|
|
## Contributing
|
|
|
|
Follow the EDR Platform standards in `CLAUDE.md`:
|
|
- TypeScript strict mode
|
|
- Conventional commits
|
|
- ESLint + Prettier
|
|
- pnpm only (no npm/yarn)
|
|
|
|
## License
|
|
|
|
Proprietary - Ethio-Djibouti Railway Platform
|
|
|
|
## Support
|
|
|
|
For issues or questions, contact the EDR Platform team.
|