Files
NaMesa_site/reserva-mesa-dashboard/app/(dashboard)/reservas/page.tsx

138 lines
5.9 KiB
TypeScript

"use client";
import { useReservas } from "@/hooks/useReservas";
import { useMesas } from "@/hooks/useMesas";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { CalendarDays, Check, X, Clock, User } from "lucide-react";
import { Reserva } from "@/types/reserva";
import { Mesa } from "@/types/mesa";
import { useToast } from "@/components/ui/toast";
export default function ReservasPage() {
const { reservas, loading, updateReservaEstado, concluirReserva, confirmarComMesa } = useReservas();
const { mesas } = useMesas();
const { toast } = useToast();
const handleConcluir = async (reserva: Reserva) => {
// Tentar encontrar a mesa se o estado for "Confirmada (Mesa X)"
let mesaId: string | undefined;
if (reserva.estado.includes("Mesa")) {
const match = reserva.estado.match(/Mesa (\d+)/);
if (match) {
const num = parseInt(match[1]);
const mesa = mesas.find(m => m.numero === num);
mesaId = mesa?.id;
}
}
const res = await concluirReserva(reserva.id, mesaId);
if (res.success) {
toast("Reserva concluída e mesa libertada.", "success");
}
};
const handleUpdate = async (id: string, estado: any) => {
const res = await updateReservaEstado(id, estado);
if (res.success) {
toast(`Reserva marcada como ${estado}`, "info");
}
};
const getStatusColor = (estado: string) => {
if (estado.startsWith("Confirmada")) return "bg-green-500/10 text-green-500 border-green-500/20";
switch (estado) {
case "Pendente": return "bg-amber-500/10 text-amber-500 border-amber-500/20";
case "Recusada":
case "Cancelada": return "bg-destructive/10 text-destructive border-destructive/20";
default: return "bg-muted text-muted-foreground border-border";
}
};
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<h1 className="text-3xl font-display font-bold text-foreground">Gestão de Reservas</h1>
<div className="flex items-center gap-2 text-sm text-muted-foreground bg-card px-3 py-1.5 rounded-full border border-border">
<CalendarDays className="h-4 w-4 text-primary" />
<span>{new Date().toLocaleDateString('pt-PT')}</span>
</div>
</div>
<div className="grid gap-4">
{loading ? (
<div className="flex items-center justify-center py-20">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
</div>
) : reservas.length > 0 ? (
reservas.map((reserva) => (
<Card key={reserva.id} className="overflow-hidden border-border/50 hover:border-primary/30 transition-all duration-200 shadow-sm">
<CardContent className="p-0">
<div className="flex flex-col md:flex-row md:items-center p-6 gap-6">
<div className="flex-1 space-y-2">
<div className="flex items-center gap-3">
<div className={`px-2.5 py-0.5 rounded-full text-[11px] font-bold uppercase border ${getStatusColor(reserva.estado)}`}>
{reserva.estado}
</div>
<span className="text-sm text-muted-foreground flex items-center gap-1">
<Clock className="h-3 w-3" /> {reserva.data} às {reserva.hora}
</span>
</div>
<h3 className="text-xl font-bold">{reserva.clienteEmail}</h3>
<div className="flex items-center gap-4 text-sm text-muted-foreground">
<span className="flex items-center gap-1">
<User className="h-4 w-4" /> {reserva.pessoas} pessoas
</span>
</div>
</div>
<div className="flex items-center gap-2">
{reserva.estado === "Pendente" && (
<>
<Button
onClick={() => handleUpdate(reserva.id, "Confirmada")}
className="bg-green-600 hover:bg-green-700 text-white"
size="sm"
>
<Check className="h-4 w-4 mr-2" /> Aceitar
</Button>
<Button
size="sm"
variant="ghost"
className="text-destructive hover:bg-destructive/10"
onClick={() => handleUpdate(reserva.id, "Recusada")}
>
<X className="h-4 w-4 mr-1" /> Recusar
</Button>
</>
)}
{reserva.estado.startsWith("Confirmada") && (
<Button
onClick={() => handleConcluir(reserva)}
variant="outline"
size="sm"
className="hover:bg-primary/10 hover:text-primary hover:border-primary/30"
>
<Check className="h-4 w-4 mr-2" /> Marcar como Concluída
</Button>
)}
</div>
</div>
</CardContent>
</Card>
))
) : (
<Card className="border-dashed border-2">
<CardContent className="flex flex-col items-center justify-center py-20 text-center">
<CalendarDays className="h-16 w-16 text-muted-foreground/20 mb-4" />
<h3 className="text-xl font-medium">Sem reservas registadas</h3>
<p className="text-muted-foreground max-w-xs mx-auto">
As reservas feitas pelos clientes através da App Android aparecerão aqui em tempo real.
</p>
</CardContent>
</Card>
)}
</div>
</div>
);
}