make the booking in many steps
Build & Deploy / Build & Push Docker Image (push) Successful in 8m27s
Test / Type Check (all packages) (push) Successful in 3m34s
Build & Deploy / Deploy to VPS (push) Successful in 2s
Test / API Unit Tests (push) Failing after 3m16s
Test / Homepage Unit Tests (push) Failing after 2m40s
Test / Storefront Unit Tests (push) Failing after 24s
Test / Admin Unit Tests (push) Failing after 22s
Test / Dashboard Unit Tests (push) Failing after 24s
Test / API Integration Tests (push) Failing after 33s
Build & Deploy / Build & Push Docker Image (push) Successful in 8m27s
Test / Type Check (all packages) (push) Successful in 3m34s
Build & Deploy / Deploy to VPS (push) Successful in 2s
Test / API Unit Tests (push) Failing after 3m16s
Test / Homepage Unit Tests (push) Failing after 2m40s
Test / Storefront Unit Tests (push) Failing after 24s
Test / Admin Unit Tests (push) Failing after 22s
Test / Dashboard Unit Tests (push) Failing after 24s
Test / API Integration Tests (push) Failing after 33s
This commit is contained in:
@@ -0,0 +1,634 @@
|
||||
# Progressive Reservation Creation: Action Plan
|
||||
|
||||
## 1. Objective
|
||||
|
||||
Replace the single long reservation form at:
|
||||
|
||||
`/dashboard/reservations/new`
|
||||
|
||||
with a progressive wizard that:
|
||||
|
||||
* Shows one focused section at a time.
|
||||
* Validates only the current section before continuing.
|
||||
* Preserves entered information when moving backward or forward.
|
||||
* Provides a final review before creating the reservation.
|
||||
* Works correctly in English, French, and Arabic.
|
||||
* Supports desktop, mobile, light mode, dark mode, LTR, and RTL.
|
||||
* Prevents duplicate submissions and handles partial API failures safely.
|
||||
|
||||
The reservation should not be created until the user confirms the final review step.
|
||||
|
||||
---
|
||||
|
||||
## 2. Problems in the Current Implementation
|
||||
|
||||
The existing page combines all responsibilities inside one component:
|
||||
|
||||
* Customer search and selection.
|
||||
* New customer creation.
|
||||
* Customer identity information.
|
||||
* Driver license information.
|
||||
* License image upload.
|
||||
* Vehicle selection.
|
||||
* Rental dates and locations.
|
||||
* Deposit and payment method.
|
||||
* Additional driver information.
|
||||
* Notes.
|
||||
* Validation.
|
||||
* Customer creation and updates.
|
||||
* Reservation submission.
|
||||
* Translated copy.
|
||||
|
||||
This creates several practical problems:
|
||||
|
||||
1. The user sees too much information at once.
|
||||
2. Validation returns one generic error instead of identifying the exact field.
|
||||
3. Adding a customer is confusing because required identity and license fields appear outside the customer creation panel.
|
||||
4. Navigation away from the page loses the entire form.
|
||||
5. Customer updates, license uploads, and reservation creation can partially succeed.
|
||||
6. The component will become increasingly difficult to maintain.
|
||||
7. Vehicle availability is currently based only on `status === 'AVAILABLE'`, not the selected rental dates. That does not reliably prevent conflicting reservations.
|
||||
|
||||
---
|
||||
|
||||
## 3. Proposed Wizard Structure
|
||||
|
||||
Use six fixed steps. Six is the upper reasonable limit here. More steps would create needless clicking; fewer would leave several sections overloaded.
|
||||
|
||||
### Step 1: Customer
|
||||
|
||||
Purpose: Identify who is making the reservation.
|
||||
|
||||
Fields and actions:
|
||||
|
||||
* Choose `Existing customer` or `New customer`.
|
||||
* Search existing customers.
|
||||
* Select an existing customer.
|
||||
* For a new customer:
|
||||
|
||||
* First name.
|
||||
* Arabic first name.
|
||||
* Last name.
|
||||
* Arabic last name.
|
||||
* Email.
|
||||
* Phone.
|
||||
|
||||
Completion requirements:
|
||||
|
||||
* Existing customer mode: a customer must be selected.
|
||||
* New customer mode: first name, last name, email, and phone must be valid.
|
||||
|
||||
Important behavior:
|
||||
|
||||
* Selecting an existing customer preloads known identity and license data.
|
||||
* Creating a new customer should not call the API at this step.
|
||||
* Switching between existing and new customer modes must not silently mix the two records.
|
||||
* Changing the selected customer after editing loaded data should display a confirmation before replacing those edits.
|
||||
|
||||
### Step 2: Identity
|
||||
|
||||
Purpose: Verify the renter’s personal information.
|
||||
|
||||
Fields:
|
||||
|
||||
* Date of birth.
|
||||
* Nationality.
|
||||
* CIN or passport number.
|
||||
* Full address.
|
||||
* International permit number, optional.
|
||||
|
||||
Completion requirements:
|
||||
|
||||
* Date of birth is present and in the past.
|
||||
* Nationality is present.
|
||||
* Identity document number is present.
|
||||
* Full address is present.
|
||||
|
||||
The section should display whether values were loaded from an existing customer and allow the user to correct them.
|
||||
|
||||
### Step 3: Driver License
|
||||
|
||||
Purpose: Verify that the primary renter is legally eligible to drive.
|
||||
|
||||
Fields:
|
||||
|
||||
* Driver license number.
|
||||
* License country.
|
||||
* License issue date.
|
||||
* License expiry date.
|
||||
* License category.
|
||||
* License image, optional unless business rules later require it.
|
||||
|
||||
Completion requirements:
|
||||
|
||||
* Required license fields are complete.
|
||||
* Issue date is not in the future.
|
||||
* Expiry date is after the issue date.
|
||||
* Expiry date has not already passed.
|
||||
* Uploaded file is a supported image type and within the configured size limit.
|
||||
|
||||
The current image and newly selected preview should be clearly distinguished.
|
||||
|
||||
### Step 4: Rental Details
|
||||
|
||||
Purpose: Define what is being rented and when.
|
||||
|
||||
Recommended field order:
|
||||
|
||||
1. Start date and time.
|
||||
2. End date and time.
|
||||
3. Vehicle.
|
||||
4. Pickup location.
|
||||
5. Return location.
|
||||
|
||||
Completion requirements:
|
||||
|
||||
* Start date is valid.
|
||||
* End date is later than the start date.
|
||||
* A vehicle is selected.
|
||||
* The vehicle remains available for the chosen period.
|
||||
|
||||
Important correction:
|
||||
|
||||
The current implementation lists vehicles using only their general `AVAILABLE` status. The final implementation should request or revalidate date-based availability. A vehicle can be marked available now while already reserved for the requested dates.
|
||||
|
||||
If the API does not currently support date-based availability, this must be recorded as a backend dependency rather than pretending the status filter is sufficient.
|
||||
|
||||
### Step 5: Payment and Extras
|
||||
|
||||
Purpose: Collect optional and commercial details.
|
||||
|
||||
Main fields:
|
||||
|
||||
* Deposit amount.
|
||||
* Payment method.
|
||||
* Notes.
|
||||
|
||||
Optional additional driver:
|
||||
|
||||
* Display a compact `Add another driver` control.
|
||||
* Opening it reveals an additional-driver panel or nested form.
|
||||
* Allow removal before submission.
|
||||
* Structure the state as an array even if the current interface initially supports only one driver.
|
||||
|
||||
Additional-driver fields:
|
||||
|
||||
* First and last name.
|
||||
* Arabic first and last name.
|
||||
* Email, optional.
|
||||
* Phone, optional.
|
||||
* Date of birth, optional.
|
||||
* Nationality, optional.
|
||||
* License number.
|
||||
* License issue date, optional.
|
||||
* License expiry date, optional.
|
||||
|
||||
Completion requirements:
|
||||
|
||||
* Deposit cannot be negative.
|
||||
* A payment method must be selected.
|
||||
* If an additional driver is enabled, name and license number are required.
|
||||
* Any entered additional-driver dates must be logically valid.
|
||||
|
||||
### Step 6: Review and Confirm
|
||||
|
||||
Purpose: Prevent avoidable mistakes before committing data.
|
||||
|
||||
Display concise summaries for:
|
||||
|
||||
* Customer.
|
||||
* Identity.
|
||||
* Primary driver license.
|
||||
* Vehicle.
|
||||
* Rental period.
|
||||
* Pickup and return locations.
|
||||
* Payment.
|
||||
* Additional drivers.
|
||||
* Notes.
|
||||
|
||||
Each summary section should include an `Edit` action that returns directly to the relevant step.
|
||||
|
||||
Final actions:
|
||||
|
||||
* Back.
|
||||
* Cancel.
|
||||
* Create reservation.
|
||||
|
||||
The final button must display a loading state and remain disabled after the first click until the request succeeds or fails.
|
||||
|
||||
---
|
||||
|
||||
## 4. Navigation and Progress Behavior
|
||||
|
||||
### Desktop
|
||||
|
||||
Use a horizontal stepper containing:
|
||||
|
||||
* Step number.
|
||||
* Short step label.
|
||||
* Completed state.
|
||||
* Current state.
|
||||
* Future state.
|
||||
|
||||
### Mobile
|
||||
|
||||
Use a compact header:
|
||||
|
||||
`Step 3 of 6 · Driver license`
|
||||
|
||||
Include a progress bar rather than compressing all six labels into unusable decorative confetti.
|
||||
|
||||
### Navigation rules
|
||||
|
||||
* `Continue` validates the current step.
|
||||
* `Back` never discards information.
|
||||
* Completed steps may be revisited.
|
||||
* Future incomplete steps cannot be opened directly.
|
||||
* The final review step is available only after all previous steps are valid.
|
||||
* Pressing Enter must not accidentally submit the final reservation from an earlier step.
|
||||
* The footer containing Back and Continue should remain visible on long steps where practical.
|
||||
|
||||
---
|
||||
|
||||
## 5. Validation Strategy
|
||||
|
||||
Replace the current generic `Please fill all required fields` behavior with step-specific validation.
|
||||
|
||||
Use Zod, which is already installed, to create separate schemas:
|
||||
|
||||
* `customerStepSchema`
|
||||
* `identityStepSchema`
|
||||
* `licenseStepSchema`
|
||||
* `rentalStepSchema`
|
||||
* `paymentExtrasStepSchema`
|
||||
* `completeReservationSchema`
|
||||
|
||||
Validation behavior:
|
||||
|
||||
* Validate on Continue.
|
||||
* Show the message beside the invalid field.
|
||||
* Focus the first invalid field.
|
||||
* Clear an error once the value becomes valid.
|
||||
* Run complete validation again before final submission.
|
||||
* Translate validation messages into English, French, and Arabic.
|
||||
|
||||
Do not depend on disabled buttons alone. A disabled button gives the user no useful explanation and is a remarkably efficient way to make software feel broken.
|
||||
|
||||
---
|
||||
|
||||
## 6. State Management Refactor
|
||||
|
||||
Replace the large collection of independent `useState` calls with one structured draft state managed by `useReducer`.
|
||||
|
||||
Suggested shape:
|
||||
|
||||
```ts
|
||||
type ReservationDraft = {
|
||||
customer: {
|
||||
mode: 'existing' | 'new'
|
||||
selectedCustomerId: string | null
|
||||
firstName: BilingualField
|
||||
lastName: BilingualField
|
||||
email: string
|
||||
phone: string
|
||||
}
|
||||
identity: {
|
||||
dateOfBirth: string
|
||||
nationality: string
|
||||
fullAddress: string
|
||||
identityDocumentNumber: string
|
||||
internationalLicenseNumber: string
|
||||
}
|
||||
license: {
|
||||
number: string
|
||||
country: string
|
||||
issuedAt: string
|
||||
expiry: string
|
||||
category: string
|
||||
existingImageUrl: string | null
|
||||
newImageFile: File | null
|
||||
}
|
||||
rental: {
|
||||
vehicleId: string
|
||||
startDate: string
|
||||
endDate: string
|
||||
pickupLocation: string
|
||||
returnLocation: string
|
||||
}
|
||||
payment: {
|
||||
depositAmount: string
|
||||
paymentMode: string
|
||||
notes: string
|
||||
}
|
||||
additionalDrivers: AdditionalDriverDraft[]
|
||||
}
|
||||
```
|
||||
|
||||
The reducer should support explicit actions such as:
|
||||
|
||||
* Select existing customer.
|
||||
* Start new customer.
|
||||
* Update step field.
|
||||
* Add additional driver.
|
||||
* Remove additional driver.
|
||||
* Hydrate customer information.
|
||||
* Clear customer information.
|
||||
* Store a newly created customer ID after partial submission.
|
||||
* Reset the entire draft.
|
||||
|
||||
This makes state transitions testable and prevents unrelated fields from being scattered throughout the page.
|
||||
|
||||
---
|
||||
|
||||
## 7. Component Structure
|
||||
|
||||
Reduce `page.tsx` to a data-loading and route-level shell.
|
||||
|
||||
Suggested structure:
|
||||
|
||||
```text
|
||||
src/components/reservations/new/
|
||||
├── ReservationWizard.tsx
|
||||
├── ReservationStepper.tsx
|
||||
├── ReservationWizardActions.tsx
|
||||
├── ReservationReview.tsx
|
||||
├── reservationWizard.types.ts
|
||||
├── reservationWizard.reducer.ts
|
||||
├── reservationWizard.schemas.ts
|
||||
├── reservationWizard.copy.ts
|
||||
├── reservationWizard.submit.ts
|
||||
├── steps/
|
||||
│ ├── CustomerStep.tsx
|
||||
│ ├── IdentityStep.tsx
|
||||
│ ├── LicenseStep.tsx
|
||||
│ ├── RentalDetailsStep.tsx
|
||||
│ ├── PaymentExtrasStep.tsx
|
||||
│ └── ReviewStep.tsx
|
||||
└── __tests__/
|
||||
```
|
||||
|
||||
Responsibilities:
|
||||
|
||||
* `page.tsx`: load customers and vehicles, render the wizard.
|
||||
* `ReservationWizard`: control current step and draft state.
|
||||
* Step components: render fields only.
|
||||
* Schemas: validation only.
|
||||
* Reducer: state transitions only.
|
||||
* Submission module: API orchestration only.
|
||||
* Copy file: typed English, French, and Arabic labels.
|
||||
* Review component: display formatted summaries only.
|
||||
|
||||
---
|
||||
|
||||
## 8. API Submission Strategy
|
||||
|
||||
No customer or reservation records should be created merely because the user moved to another step.
|
||||
|
||||
On final confirmation:
|
||||
|
||||
1. Validate the complete draft.
|
||||
2. Revalidate vehicle availability.
|
||||
3. For a new customer:
|
||||
|
||||
* Create the customer using the accumulated customer, identity, and license fields.
|
||||
4. For an existing customer:
|
||||
|
||||
* Patch only changed customer fields.
|
||||
5. Upload the license image when a new image was selected.
|
||||
6. Create the reservation.
|
||||
7. Redirect to the new reservation details page.
|
||||
|
||||
### Partial-failure handling
|
||||
|
||||
The current operations are not atomic. For example, customer creation may succeed while reservation creation fails.
|
||||
|
||||
The wizard must therefore:
|
||||
|
||||
* Remember the newly created customer ID in memory.
|
||||
* Retry using that customer instead of creating another duplicate.
|
||||
* Show which operation failed.
|
||||
* Keep all form data available for correction or retry.
|
||||
* Never redirect until reservation creation succeeds.
|
||||
|
||||
### Recommended backend improvement
|
||||
|
||||
The strongest solution is a dedicated backend operation that creates or updates the customer, uploads document metadata, validates vehicle availability, and creates the reservation as one controlled workflow.
|
||||
|
||||
Without such an endpoint, the frontend can handle retries carefully, but it cannot provide a true database transaction across the current independent requests.
|
||||
|
||||
---
|
||||
|
||||
## 9. Data Loading and Customer Hydration
|
||||
|
||||
Current customer and vehicle loading should be extracted from the form component.
|
||||
|
||||
Required behavior:
|
||||
|
||||
* Show a proper loading state for the wizard shell.
|
||||
* Show separate customer-load and vehicle-load errors where possible.
|
||||
* Do not overwrite user-edited customer data when background data refreshes.
|
||||
* Hydrate fields only when the selected customer actually changes.
|
||||
* Cancel or ignore stale requests when the component unmounts.
|
||||
* Avoid loading arbitrary large lists indefinitely as the database grows.
|
||||
|
||||
Future improvement:
|
||||
|
||||
Replace `pageSize=100` customer loading with server-side customer search. Loading the first 100 customers and searching them in the browser will eventually fail as a business grows, which is traditionally when software chooses to reveal its assumptions.
|
||||
|
||||
---
|
||||
|
||||
## 10. Draft-Loss Protection
|
||||
|
||||
For the first implementation:
|
||||
|
||||
* Keep all information when navigating between wizard steps.
|
||||
* Warn before leaving the page when unsaved changes exist.
|
||||
* Do not persist license images in browser storage.
|
||||
* Clear the draft after successful creation.
|
||||
* Clear object URLs used for image previews.
|
||||
|
||||
Do not automatically store sensitive customer identity and license information in long-lived local storage.
|
||||
|
||||
A server-side draft feature can be designed separately if staff need to resume reservations across devices or sessions.
|
||||
|
||||
---
|
||||
|
||||
## 11. Accessibility and Localization
|
||||
|
||||
The wizard must preserve the application’s existing multilingual requirements.
|
||||
|
||||
Requirements:
|
||||
|
||||
* English and French use LTR.
|
||||
* Arabic uses true RTL.
|
||||
* Step order and navigation layout adapt correctly in RTL.
|
||||
* Every field has an associated label.
|
||||
* Required fields are announced to assistive technology.
|
||||
* Errors use `aria-describedby`.
|
||||
* The active step uses `aria-current="step"`.
|
||||
* Focus moves to the step heading after navigation.
|
||||
* Keyboard users can operate all controls.
|
||||
* Color is not the only indicator of progress or error.
|
||||
* Buttons and inputs remain usable in dark mode.
|
||||
* Dates and amounts are presented using the active locale on the review screen.
|
||||
|
||||
The current hardcoded English license-image alt text must also be localized.
|
||||
|
||||
---
|
||||
|
||||
## 12. Testing Plan
|
||||
|
||||
### Unit tests
|
||||
|
||||
Test:
|
||||
|
||||
* Reducer actions.
|
||||
* Step validation schemas.
|
||||
* Date relationships.
|
||||
* Deposit normalization.
|
||||
* Existing customer hydration.
|
||||
* Switching customer modes.
|
||||
* Additional-driver add and remove behavior.
|
||||
* Final payload construction.
|
||||
|
||||
### Component tests
|
||||
|
||||
Test:
|
||||
|
||||
* Only the active step is displayed.
|
||||
* Continue blocks invalid data.
|
||||
* Back preserves data.
|
||||
* Completed steps can be revisited.
|
||||
* Existing customer details are prefilled.
|
||||
* New customer information remains in draft state.
|
||||
* Additional-driver fields appear conditionally.
|
||||
* Edit actions on the review page open the correct step.
|
||||
* Arabic step layout uses RTL correctly.
|
||||
|
||||
### Submission tests
|
||||
|
||||
Test:
|
||||
|
||||
* Existing customer reservation.
|
||||
* New customer reservation.
|
||||
* License image upload.
|
||||
* Customer update failure.
|
||||
* Image upload failure.
|
||||
* Reservation creation failure after customer creation.
|
||||
* Retry without duplicate customer creation.
|
||||
* Double-click prevention.
|
||||
* Vehicle availability conflict.
|
||||
|
||||
### Required verification
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm run type-check
|
||||
npm run test
|
||||
npm run build
|
||||
```
|
||||
|
||||
for the dashboard workspace after implementation.
|
||||
|
||||
---
|
||||
|
||||
## 13. Implementation Sequence
|
||||
|
||||
### Phase 1: Extract and stabilize
|
||||
|
||||
* Create typed draft models.
|
||||
* Extract copy, validation, and payload-building logic.
|
||||
* Add tests around current behavior.
|
||||
* Do not change the visible interface yet.
|
||||
|
||||
### Phase 2: Build the wizard shell
|
||||
|
||||
* Add stepper.
|
||||
* Add reducer.
|
||||
* Add navigation.
|
||||
* Add shared action footer.
|
||||
* Render one step at a time.
|
||||
|
||||
### Phase 3: Move form sections
|
||||
|
||||
* Move customer fields.
|
||||
* Move identity fields.
|
||||
* Move license fields.
|
||||
* Move rental fields.
|
||||
* Move payment and optional driver fields.
|
||||
* Build the review screen.
|
||||
|
||||
### Phase 4: Correct submission behavior
|
||||
|
||||
* Delay new-customer creation until final confirmation.
|
||||
* Add partial-failure recovery.
|
||||
* Prevent duplicate requests.
|
||||
* Revalidate vehicle availability.
|
||||
* Preserve the draft after recoverable errors.
|
||||
|
||||
### Phase 5: Accessibility and responsive refinement
|
||||
|
||||
* Add keyboard and screen-reader behavior.
|
||||
* Verify mobile presentation.
|
||||
* Verify dark mode.
|
||||
* Verify Arabic RTL.
|
||||
* Verify translated error messages.
|
||||
|
||||
### Phase 6: Testing and regression review
|
||||
|
||||
* Complete unit and component tests.
|
||||
* Run type-check, tests, and production build.
|
||||
* Verify both existing-customer and new-customer flows manually.
|
||||
* Confirm redirect to the created reservation.
|
||||
|
||||
---
|
||||
|
||||
## 14. Acceptance Criteria
|
||||
|
||||
The work is complete only when:
|
||||
|
||||
* Exactly one focused step is displayed at a time.
|
||||
* The user can see their current position and progress.
|
||||
* Invalid current-step fields prevent progression and explain why.
|
||||
* Going backward does not lose information.
|
||||
* New customers are not created before final confirmation.
|
||||
* Existing-customer data is loaded without repeatedly overwriting edits.
|
||||
* Additional drivers remain optional.
|
||||
* The final review contains all reservation information.
|
||||
* Every review section can be edited.
|
||||
* Duplicate reservations cannot be created by repeated clicks.
|
||||
* Partial API failures do not force the user to restart.
|
||||
* Vehicle availability is revalidated for the selected dates.
|
||||
* English, French, and Arabic are complete.
|
||||
* Arabic layout is true RTL.
|
||||
* Mobile, desktop, light mode, and dark mode work.
|
||||
* Type-check, tests, and production build pass.
|
||||
|
||||
---
|
||||
|
||||
## 15. Scope Boundaries
|
||||
|
||||
Included:
|
||||
|
||||
* Progressive reservation wizard.
|
||||
* Refactoring of the current new-reservation page.
|
||||
* Step validation.
|
||||
* Review screen.
|
||||
* Existing and new customer flows.
|
||||
* License image handling.
|
||||
* Additional-driver handling.
|
||||
* API failure recovery.
|
||||
* Responsive, multilingual, and accessible behavior.
|
||||
* Relevant tests.
|
||||
|
||||
Not included unless separately approved:
|
||||
|
||||
* Redesigning the reservation details page.
|
||||
* Server-side saved drafts.
|
||||
* OCR extraction from driver licenses.
|
||||
* Multiple primary renters.
|
||||
* Payment processing.
|
||||
* Contract generation.
|
||||
* Changing unrelated dashboard pages.
|
||||
* Broad customer-management redesign.
|
||||
Reference in New Issue
Block a user