5649ab02c7
Build & Push / Pipeline Tests (push) Failing after 1m31s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Successful in 55s
Test / API Unit Tests (push) Successful in 1m8s
Test / Homepage Unit Tests (push) Successful in 47s
Test / Carplace Unit Tests (push) Successful in 44s
Test / Admin Unit Tests (push) Successful in 43s
Test / Dashboard Unit Tests (push) Failing after 46s
Test / API Integration Tests (push) Successful in 1m7s
166 lines
6.1 KiB
TypeScript
166 lines
6.1 KiB
TypeScript
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',
|
|
spareWheel: false,
|
|
radioCd: false,
|
|
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 | boolean }
|
|
| { 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()
|
|
}
|
|
}
|