Initial commit

This commit is contained in:
Jose Selesan
2026-04-08 22:53:11 -03:00
commit 9ae270609d
179 changed files with 28096 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
import { useQuery } from '@tanstack/react-query'
import { useNavigate } from '@tanstack/react-router'
import { Button } from '@/components/ui/button'
import { ApiClientError, apiClient } from '@/lib/api-client'
type PublicBookingConfirmationPageProps = {
complexSlug: string
bookingCode: string
}
function extractMessage(error: unknown, fallback: string) {
if (error instanceof ApiClientError) {
return error.message || fallback
}
return fallback
}
function formatDateLabel(isoDate: string) {
const [year, month, day] = isoDate.split('-').map(Number)
const date = new Date(year, (month ?? 1) - 1, day ?? 1)
return new Intl.DateTimeFormat('es-AR', {
weekday: 'long',
day: '2-digit',
month: 'long',
year: 'numeric',
}).format(date)
}
export function PublicBookingConfirmationPage({
complexSlug,
bookingCode,
}: PublicBookingConfirmationPageProps) {
const navigate = useNavigate()
const confirmationQuery = useQuery({
queryKey: ['public-booking-confirmation', complexSlug, bookingCode],
queryFn: () => apiClient.publicBookings.getConfirmation(complexSlug, bookingCode),
})
return (
<main className="min-h-screen bg-linear-to-b from-background via-background to-primary/5">
<div className="mx-auto flex min-h-screen w-full max-w-3xl items-center px-4 py-8 sm:px-6">
<section className="w-full rounded-3xl border bg-card p-5 shadow-lg sm:p-8">
{confirmationQuery.isLoading && (
<p className="text-sm text-muted-foreground">Cargando confirmacion...</p>
)}
{confirmationQuery.isError && (
<p className="text-sm text-destructive">
{extractMessage(
confirmationQuery.error,
'No pudimos cargar la confirmacion de la reserva.',
)}
</p>
)}
{confirmationQuery.data && (
<div className="space-y-6">
<div>
<p className="text-xs font-medium tracking-[0.2em] text-muted-foreground uppercase">
Reserva confirmada
</p>
<h1 className="mt-2 text-2xl font-semibold sm:text-3xl">
{confirmationQuery.data.complexName}
</h1>
</div>
<div className="rounded-2xl border border-primary/30 bg-primary/5 p-4 text-center sm:p-5">
<p className="text-xs text-muted-foreground">Codigo de reserva</p>
<p className="mt-1 text-3xl font-bold tracking-[0.25em] text-primary sm:text-4xl">
{confirmationQuery.data.bookingCode}
</p>
</div>
<div className="rounded-2xl border bg-background p-4 sm:p-5">
<p className="text-sm text-muted-foreground">Fecha</p>
<p className="mt-1 text-base font-medium capitalize sm:text-lg">
{formatDateLabel(confirmationQuery.data.date)}
</p>
<p className="mt-4 text-sm text-muted-foreground">Horario</p>
<p className="mt-1 text-base font-medium sm:text-lg">
{confirmationQuery.data.startTime} - {confirmationQuery.data.endTime}
</p>
<p className="mt-4 text-sm text-muted-foreground">Cancha</p>
<p className="mt-1 text-base font-medium sm:text-lg">
{confirmationQuery.data.courtName} · {confirmationQuery.data.sport.name}
</p>
</div>
<Button
type="button"
className="h-11 w-full text-sm sm:text-base"
onClick={() => {
void navigate({
to: '/$complexSlug/booking',
params: { complexSlug },
})
}}
>
Hacer otra reserva
</Button>
</div>
)}
</section>
</div>
</main>
)
}