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,163 @@
|
||||
import { emptyBilingual } from '@/components/ui/BilingualInput'
|
||||
import type { AdditionalDriverDraft, Customer, ReservationDraft } from './reservationWizard.types'
|
||||
|
||||
function readCustomerAddressValue(customer: Customer | undefined, key: string) {
|
||||
const address = customer?.address
|
||||
if (!address || typeof address !== 'object' || Array.isArray(address)) return ''
|
||||
const value = address[key]
|
||||
return typeof value === 'string' ? value : ''
|
||||
}
|
||||
|
||||
export function createAdditionalDriver(): AdditionalDriverDraft {
|
||||
return {
|
||||
id: crypto.randomUUID(),
|
||||
firstName: emptyBilingual(),
|
||||
lastName: emptyBilingual(),
|
||||
email: '',
|
||||
phone: '',
|
||||
driverLicense: '',
|
||||
licenseExpiry: '',
|
||||
licenseIssuedAt: '',
|
||||
dateOfBirth: '',
|
||||
nationality: emptyBilingual(),
|
||||
}
|
||||
}
|
||||
|
||||
export function createInitialDraft(): ReservationDraft {
|
||||
return {
|
||||
customer: {
|
||||
mode: 'existing',
|
||||
selectedCustomerId: null,
|
||||
createdCustomerId: null,
|
||||
firstName: emptyBilingual(),
|
||||
lastName: emptyBilingual(),
|
||||
email: '',
|
||||
phone: '',
|
||||
hydratedFromCustomerId: null,
|
||||
},
|
||||
identity: {
|
||||
dateOfBirth: '',
|
||||
nationality: '',
|
||||
fullAddress: '',
|
||||
identityDocumentNumber: '',
|
||||
internationalLicenseNumber: '',
|
||||
},
|
||||
license: {
|
||||
number: '',
|
||||
country: '',
|
||||
issuedAt: '',
|
||||
expiry: '',
|
||||
category: '',
|
||||
existingImageUrl: null,
|
||||
newImageFile: null,
|
||||
},
|
||||
rental: {
|
||||
vehicleId: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
pickupLocation: '',
|
||||
returnLocation: '',
|
||||
},
|
||||
payment: {
|
||||
depositAmount: '0',
|
||||
paymentMode: 'CASH',
|
||||
notes: '',
|
||||
},
|
||||
additionalDrivers: [],
|
||||
}
|
||||
}
|
||||
|
||||
export type ReservationDraftAction =
|
||||
| { type: 'setCustomerMode'; mode: 'existing' | 'new' }
|
||||
| { type: 'selectExistingCustomer'; customer: Customer }
|
||||
| { type: 'setCreatedCustomerId'; customerId: string }
|
||||
| { type: 'updateCustomer'; field: keyof ReservationDraft['customer']; value: any }
|
||||
| { type: 'updateIdentity'; field: keyof ReservationDraft['identity']; value: string }
|
||||
| { type: 'updateLicense'; field: keyof ReservationDraft['license']; value: any }
|
||||
| { type: 'updateRental'; field: keyof ReservationDraft['rental']; value: string }
|
||||
| { type: 'updatePayment'; field: keyof ReservationDraft['payment']; value: string }
|
||||
| { type: 'addAdditionalDriver' }
|
||||
| { type: 'removeAdditionalDriver'; id: string }
|
||||
| { type: 'updateAdditionalDriver'; id: string; field: keyof AdditionalDriverDraft; value: any }
|
||||
| { type: 'reset' }
|
||||
|
||||
export function reservationDraftReducer(draft: ReservationDraft, action: ReservationDraftAction): ReservationDraft {
|
||||
switch (action.type) {
|
||||
case 'setCustomerMode':
|
||||
if (action.mode === draft.customer.mode) return draft
|
||||
if (action.mode === 'new') {
|
||||
return {
|
||||
...draft,
|
||||
customer: {
|
||||
...createInitialDraft().customer,
|
||||
mode: 'new',
|
||||
createdCustomerId: draft.customer.createdCustomerId,
|
||||
},
|
||||
identity: createInitialDraft().identity,
|
||||
license: createInitialDraft().license,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...draft,
|
||||
customer: createInitialDraft().customer,
|
||||
identity: createInitialDraft().identity,
|
||||
license: createInitialDraft().license,
|
||||
}
|
||||
case 'selectExistingCustomer':
|
||||
return {
|
||||
...draft,
|
||||
customer: {
|
||||
mode: 'existing',
|
||||
selectedCustomerId: action.customer.id,
|
||||
createdCustomerId: null,
|
||||
firstName: { fr: action.customer.firstName ?? '', ar: action.customer.firstNameAr ?? '' },
|
||||
lastName: { fr: action.customer.lastName ?? '', ar: action.customer.lastNameAr ?? '' },
|
||||
email: action.customer.email ?? '',
|
||||
phone: action.customer.phone ?? '',
|
||||
hydratedFromCustomerId: action.customer.id,
|
||||
},
|
||||
identity: {
|
||||
dateOfBirth: action.customer.dateOfBirth ? action.customer.dateOfBirth.slice(0, 10) : '',
|
||||
nationality: action.customer.nationality ?? '',
|
||||
fullAddress: readCustomerAddressValue(action.customer, 'fullAddress'),
|
||||
identityDocumentNumber: readCustomerAddressValue(action.customer, 'identityDocumentNumber'),
|
||||
internationalLicenseNumber: readCustomerAddressValue(action.customer, 'internationalLicenseNumber'),
|
||||
},
|
||||
license: {
|
||||
number: action.customer.driverLicense ?? action.customer.licenseNumber ?? '',
|
||||
country: action.customer.licenseCountry ?? '',
|
||||
issuedAt: action.customer.licenseIssuedAt ? action.customer.licenseIssuedAt.slice(0, 10) : '',
|
||||
expiry: action.customer.licenseExpiry ? action.customer.licenseExpiry.slice(0, 10) : '',
|
||||
category: action.customer.licenseCategory ?? '',
|
||||
existingImageUrl: action.customer.licenseImageUrl ?? null,
|
||||
newImageFile: null,
|
||||
},
|
||||
}
|
||||
case 'setCreatedCustomerId':
|
||||
return { ...draft, customer: { ...draft.customer, createdCustomerId: action.customerId } }
|
||||
case 'updateCustomer':
|
||||
return { ...draft, customer: { ...draft.customer, [action.field]: action.value } }
|
||||
case 'updateIdentity':
|
||||
return { ...draft, identity: { ...draft.identity, [action.field]: action.value } }
|
||||
case 'updateLicense':
|
||||
return { ...draft, license: { ...draft.license, [action.field]: action.value } }
|
||||
case 'updateRental':
|
||||
return { ...draft, rental: { ...draft.rental, [action.field]: action.value } }
|
||||
case 'updatePayment':
|
||||
return { ...draft, payment: { ...draft.payment, [action.field]: action.value } }
|
||||
case 'addAdditionalDriver':
|
||||
return { ...draft, additionalDrivers: [...draft.additionalDrivers, createAdditionalDriver()] }
|
||||
case 'removeAdditionalDriver':
|
||||
return { ...draft, additionalDrivers: draft.additionalDrivers.filter((driver) => driver.id !== action.id) }
|
||||
case 'updateAdditionalDriver':
|
||||
return {
|
||||
...draft,
|
||||
additionalDrivers: draft.additionalDrivers.map((driver) =>
|
||||
driver.id === action.id ? { ...driver, [action.field]: action.value } : driver,
|
||||
),
|
||||
}
|
||||
case 'reset':
|
||||
return createInitialDraft()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user