prevent booking when no car added
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { formatCurrency } from '@rentaldrivego/types'
|
||||
import { apiFetch } from '@/lib/api'
|
||||
import { useDashboardI18n } from '@/components/I18nProvider'
|
||||
@@ -25,18 +26,26 @@ interface ReservationRow {
|
||||
customer: { firstName: string; lastName: string; email: string }
|
||||
}
|
||||
|
||||
interface VehicleRow {
|
||||
id: string
|
||||
}
|
||||
|
||||
export default function ReservationsPage() {
|
||||
const { dict, language } = useDashboardI18n()
|
||||
const router = useRouter()
|
||||
const r = dict.reservations
|
||||
const localeCode = language === 'fr' ? 'fr-FR' : language === 'ar' ? 'ar-MA' : 'en-US'
|
||||
|
||||
const [rows, setRows] = useState<ReservationRow[]>([])
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [loadError, setLoadError] = useState<string | null>(null)
|
||||
const [actionError, setActionError] = useState<string | null>(null)
|
||||
const [checkingNewReservation, setCheckingNewReservation] = useState(false)
|
||||
const [showNoVehiclesModal, setShowNoVehiclesModal] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
apiFetch<ReservationRow[]>('/reservations?pageSize=100')
|
||||
.then((result) => setRows(result ?? []))
|
||||
.catch((err) => setError(err.message))
|
||||
.catch((err) => setLoadError(err.message))
|
||||
}, [])
|
||||
|
||||
const formatDate = (iso: string) =>
|
||||
@@ -52,6 +61,40 @@ export default function ReservationsPage() {
|
||||
}
|
||||
return language === 'fr' ? 'Voir la réservation' : language === 'ar' ? 'عرض الحجز' : 'View reservation'
|
||||
}
|
||||
const noVehiclesMessage =
|
||||
language === 'fr'
|
||||
? 'Ajoutez au moins un véhicule à votre flotte avant de créer une réservation.'
|
||||
: language === 'ar'
|
||||
? 'أضف مركبة واحدة على الأقل إلى الأسطول قبل إنشاء حجز.'
|
||||
: 'Add at least one vehicle to your fleet before creating a reservation.'
|
||||
|
||||
async function handleNewReservationClick() {
|
||||
setActionError(null)
|
||||
setCheckingNewReservation(true)
|
||||
try {
|
||||
const vehicles = await apiFetch<VehicleRow[]>('/vehicles?pageSize=1')
|
||||
if (!vehicles || vehicles.length === 0) {
|
||||
setShowNoVehiclesModal(true)
|
||||
return
|
||||
}
|
||||
router.push('/reservations/new')
|
||||
} catch (err: any) {
|
||||
setActionError(err.message ?? (
|
||||
language === 'fr'
|
||||
? 'Impossible de vérifier la flotte avant de créer la réservation.'
|
||||
: language === 'ar'
|
||||
? 'تعذر التحقق من الأسطول قبل إنشاء الحجز.'
|
||||
: 'Failed to verify fleet before creating the reservation.'
|
||||
))
|
||||
} finally {
|
||||
setCheckingNewReservation(false)
|
||||
}
|
||||
}
|
||||
|
||||
function handleAddCar() {
|
||||
setShowNoVehiclesModal(false)
|
||||
router.push('/fleet?modal=add-car')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
@@ -60,13 +103,29 @@ export default function ReservationsPage() {
|
||||
<h2 className="text-xl font-semibold text-slate-900">{r.heading}</h2>
|
||||
<p className="text-sm text-slate-500 mt-1">{r.subtitle}</p>
|
||||
</div>
|
||||
<Link href="/reservations/new" className="btn-primary whitespace-nowrap">
|
||||
{language === 'fr' ? 'Réserver une voiture' : language === 'ar' ? 'حجز سيارة' : 'Book car'}
|
||||
</Link>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-primary whitespace-nowrap"
|
||||
onClick={handleNewReservationClick}
|
||||
disabled={checkingNewReservation}
|
||||
>
|
||||
{checkingNewReservation
|
||||
? language === 'fr'
|
||||
? 'Vérification…'
|
||||
: language === 'ar'
|
||||
? 'جارٍ التحقق…'
|
||||
: 'Checking…'
|
||||
: language === 'fr'
|
||||
? 'Réserver une voiture'
|
||||
: language === 'ar'
|
||||
? 'حجز سيارة'
|
||||
: 'Book car'}
|
||||
</button>
|
||||
</div>
|
||||
{actionError ? <div className="card p-4 text-sm text-red-600">{actionError}</div> : null}
|
||||
<div className="card overflow-hidden">
|
||||
{error ? (
|
||||
<div className="p-8 text-sm text-red-600">{error}</div>
|
||||
{loadError ? (
|
||||
<div className="p-8 text-sm text-red-600">{loadError}</div>
|
||||
) : (
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full">
|
||||
@@ -109,6 +168,29 @@ export default function ReservationsPage() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{showNoVehiclesModal ? (
|
||||
<div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center bg-blue-950/40 p-4"
|
||||
onClick={(event) => {
|
||||
if (event.target === event.currentTarget) setShowNoVehiclesModal(false)
|
||||
}}
|
||||
>
|
||||
<div className="w-full max-w-md rounded-2xl bg-white p-6 shadow-xl">
|
||||
<h3 className="text-lg font-semibold text-slate-900">
|
||||
{language === 'fr' ? 'Ajouter un véhicule' : language === 'ar' ? 'أضف مركبة' : 'Add a car'}
|
||||
</h3>
|
||||
<p className="mt-2 text-sm text-slate-600">{noVehiclesMessage}</p>
|
||||
<div className="mt-6 flex gap-3">
|
||||
<button type="button" className="btn-primary flex-1" onClick={handleAddCar}>
|
||||
{language === 'fr' ? 'Ajouter une voiture' : language === 'ar' ? 'إضافة مركبة' : 'Add car'}
|
||||
</button>
|
||||
<button type="button" className="btn-secondary flex-1" onClick={() => setShowNoVehiclesModal(false)}>
|
||||
{language === 'fr' ? 'Annuler' : language === 'ar' ? 'إلغاء' : 'Cancel'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user