update reservation
This commit is contained in:
@@ -16,10 +16,22 @@ type Props = {
|
||||
const copy = {
|
||||
en: {
|
||||
title: 'Reserve this vehicle',
|
||||
renterIdentity: 'Renter identity',
|
||||
firstName: 'First name',
|
||||
lastName: 'Last name',
|
||||
dateOfBirth: 'Date of birth',
|
||||
nationality: 'Nationality',
|
||||
identityDocumentNumber: 'CIN / Passport number',
|
||||
fullAddress: 'Full address',
|
||||
driverLicenseSection: 'Driver license',
|
||||
email: 'Email',
|
||||
phone: 'Phone',
|
||||
driverLicense: 'License number',
|
||||
licenseIssuedAt: 'Issue date',
|
||||
licenseExpiry: 'Expiry date',
|
||||
licenseCountry: 'Country of issue',
|
||||
licenseCategory: 'License category',
|
||||
internationalLicenseNumber: 'International permit number (optional)',
|
||||
pickupLocation: 'Pick-up location',
|
||||
returnLocation: 'Drop-off location',
|
||||
sameDropoff: 'Same drop-off',
|
||||
@@ -42,10 +54,22 @@ const copy = {
|
||||
},
|
||||
fr: {
|
||||
title: 'Réserver ce véhicule',
|
||||
renterIdentity: 'Identité du locataire',
|
||||
firstName: 'Prénom',
|
||||
lastName: 'Nom',
|
||||
dateOfBirth: 'Date de naissance',
|
||||
nationality: 'Nationalité',
|
||||
identityDocumentNumber: 'N° CIN / passeport',
|
||||
fullAddress: 'Adresse complète',
|
||||
driverLicenseSection: 'Permis de conduire',
|
||||
email: 'E-mail',
|
||||
phone: 'Téléphone',
|
||||
driverLicense: 'Numéro du permis',
|
||||
licenseIssuedAt: 'Date de délivrance',
|
||||
licenseExpiry: 'Date d’expiration',
|
||||
licenseCountry: 'Pays de délivrance',
|
||||
licenseCategory: 'Catégorie du permis',
|
||||
internationalLicenseNumber: 'N° de permis international (optionnel)',
|
||||
pickupLocation: 'Lieu de départ',
|
||||
returnLocation: 'Lieu de retour',
|
||||
sameDropoff: 'Même retour',
|
||||
@@ -68,10 +92,22 @@ const copy = {
|
||||
},
|
||||
ar: {
|
||||
title: 'احجز هذه السيارة',
|
||||
renterIdentity: 'بيانات المستأجر',
|
||||
firstName: 'الاسم الأول',
|
||||
lastName: 'اسم العائلة',
|
||||
dateOfBirth: 'تاريخ الميلاد',
|
||||
nationality: 'الجنسية',
|
||||
identityDocumentNumber: 'رقم البطاقة الوطنية / جواز السفر',
|
||||
fullAddress: 'العنوان الكامل',
|
||||
driverLicenseSection: 'رخصة القيادة',
|
||||
email: 'البريد الإلكتروني',
|
||||
phone: 'الهاتف',
|
||||
driverLicense: 'رقم الرخصة',
|
||||
licenseIssuedAt: 'تاريخ الإصدار',
|
||||
licenseExpiry: 'تاريخ الانتهاء',
|
||||
licenseCountry: 'بلد الإصدار',
|
||||
licenseCategory: 'فئة الرخصة',
|
||||
internationalLicenseNumber: 'رقم الرخصة الدولية (اختياري)',
|
||||
pickupLocation: 'موقع الاستلام',
|
||||
returnLocation: 'موقع الإرجاع',
|
||||
sameDropoff: 'نفس موقع الإرجاع',
|
||||
@@ -110,8 +146,18 @@ export default function BookingForm({
|
||||
|
||||
const [firstName, setFirstName] = useState('')
|
||||
const [lastName, setLastName] = useState('')
|
||||
const [dateOfBirth, setDateOfBirth] = useState('')
|
||||
const [nationality, setNationality] = useState('')
|
||||
const [identityDocumentNumber, setIdentityDocumentNumber] = useState('')
|
||||
const [fullAddress, setFullAddress] = useState('')
|
||||
const [email, setEmail] = useState('')
|
||||
const [phone, setPhone] = useState('')
|
||||
const [driverLicense, setDriverLicense] = useState('')
|
||||
const [licenseIssuedAt, setLicenseIssuedAt] = useState('')
|
||||
const [licenseExpiry, setLicenseExpiry] = useState('')
|
||||
const [licenseCountry, setLicenseCountry] = useState('')
|
||||
const [licenseCategory, setLicenseCategory] = useState('')
|
||||
const [internationalLicenseNumber, setInternationalLicenseNumber] = useState('')
|
||||
const [pickupLocation, setPickupLocation] = useState(pickupOptions[0] ?? '')
|
||||
const [dropoffMode, setDropoffMode] = useState<'same' | 'different'>('same')
|
||||
const [returnLocation, setReturnLocation] = useState(dropoffOptions[0] ?? '')
|
||||
@@ -131,7 +177,23 @@ export default function BookingForm({
|
||||
e.preventDefault()
|
||||
setError(null)
|
||||
|
||||
if (!firstName.trim() || !lastName.trim() || !email.trim() || !phone.trim() || !startDate || !endDate) {
|
||||
if (
|
||||
!firstName.trim() ||
|
||||
!lastName.trim() ||
|
||||
!dateOfBirth ||
|
||||
!nationality.trim() ||
|
||||
!identityDocumentNumber.trim() ||
|
||||
!fullAddress.trim() ||
|
||||
!email.trim() ||
|
||||
!phone.trim() ||
|
||||
!driverLicense.trim() ||
|
||||
!licenseIssuedAt ||
|
||||
!licenseExpiry ||
|
||||
!licenseCountry.trim() ||
|
||||
!licenseCategory.trim() ||
|
||||
!startDate ||
|
||||
!endDate
|
||||
) {
|
||||
setError(t.required)
|
||||
return
|
||||
}
|
||||
@@ -154,8 +216,18 @@ export default function BookingForm({
|
||||
companySlug,
|
||||
firstName: firstName.trim(),
|
||||
lastName: lastName.trim(),
|
||||
dateOfBirth: new Date(dateOfBirth).toISOString(),
|
||||
nationality: nationality.trim(),
|
||||
identityDocumentNumber: identityDocumentNumber.trim(),
|
||||
fullAddress: fullAddress.trim(),
|
||||
email: email.trim(),
|
||||
phone: phone.trim(),
|
||||
driverLicense: driverLicense.trim(),
|
||||
licenseIssuedAt: new Date(licenseIssuedAt).toISOString(),
|
||||
licenseExpiry: new Date(licenseExpiry).toISOString(),
|
||||
licenseCountry: licenseCountry.trim(),
|
||||
licenseCategory: licenseCategory.trim(),
|
||||
internationalLicenseNumber: internationalLicenseNumber.trim() || undefined,
|
||||
startDate: start.toISOString(),
|
||||
endDate: end.toISOString(),
|
||||
pickupLocation: pickupLocation || undefined,
|
||||
@@ -190,22 +262,68 @@ export default function BookingForm({
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="space-y-4 rounded-2xl border border-stone-200 bg-stone-50 p-4 dark:border-blue-800 dark:bg-[#0d1b38]">
|
||||
<p className="text-sm font-semibold text-stone-900 dark:text-stone-100">{t.renterIdentity}</p>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.firstName} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
required
|
||||
value={firstName}
|
||||
onChange={(e) => setFirstName(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.lastName} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
required
|
||||
value={lastName}
|
||||
onChange={(e) => setLastName(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.dateOfBirth} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
required
|
||||
type="date"
|
||||
value={dateOfBirth}
|
||||
onChange={(e) => setDateOfBirth(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.nationality} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
required
|
||||
value={nationality}
|
||||
onChange={(e) => setNationality(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.firstName} <span className="text-red-500">*</span></label>
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.identityDocumentNumber} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
required
|
||||
value={firstName}
|
||||
onChange={(e) => setFirstName(e.target.value)}
|
||||
value={identityDocumentNumber}
|
||||
onChange={(e) => setIdentityDocumentNumber(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.lastName} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.fullAddress} <span className="text-red-500">*</span></label>
|
||||
<textarea
|
||||
required
|
||||
value={lastName}
|
||||
onChange={(e) => setLastName(e.target.value)}
|
||||
value={fullAddress}
|
||||
onChange={(e) => setFullAddress(e.target.value)}
|
||||
rows={3}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
@@ -222,6 +340,72 @@ export default function BookingForm({
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4 rounded-2xl border border-stone-200 bg-stone-50 p-4 dark:border-blue-800 dark:bg-[#0d1b38]">
|
||||
<p className="text-sm font-semibold text-stone-900 dark:text-stone-100">{t.driverLicenseSection}</p>
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.driverLicense} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
required
|
||||
value={driverLicense}
|
||||
onChange={(e) => setDriverLicense(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.licenseIssuedAt} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
required
|
||||
type="date"
|
||||
value={licenseIssuedAt}
|
||||
onChange={(e) => setLicenseIssuedAt(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.licenseExpiry} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
required
|
||||
type="date"
|
||||
value={licenseExpiry}
|
||||
onChange={(e) => setLicenseExpiry(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.licenseCountry} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
required
|
||||
value={licenseCountry}
|
||||
onChange={(e) => setLicenseCountry(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.licenseCategory} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
required
|
||||
value={licenseCategory}
|
||||
onChange={(e) => setLicenseCategory(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.internationalLicenseNumber}</label>
|
||||
<input
|
||||
value={internationalLicenseNumber}
|
||||
onChange={(e) => setInternationalLicenseNumber(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2 text-sm text-stone-900 outline-none focus:border-stone-400 dark:border-blue-800 dark:bg-[#162038] dark:text-stone-100 dark:focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs font-medium text-stone-600 dark:text-stone-400">{t.phone} <span className="text-red-500">*</span></label>
|
||||
<input
|
||||
|
||||
Reference in New Issue
Block a user