90 lines
3.7 KiB
TypeScript
90 lines
3.7 KiB
TypeScript
"use client";
|
|
|
|
import { motion, AnimatePresence } from "framer-motion";
|
|
import { X, Users, Table as TableIcon } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Mesa } from "@/types/mesa";
|
|
import { Reserva } from "@/types/reserva";
|
|
|
|
interface AssignTableModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
reserva: Reserva | null;
|
|
mesas: Mesa[];
|
|
onAssign: (mesa: Mesa) => void;
|
|
}
|
|
|
|
export function AssignTableModal({ isOpen, onClose, reserva, mesas, onAssign }: AssignTableModalProps) {
|
|
if (!reserva) return null;
|
|
|
|
const mesasDisponiveis = mesas.filter(
|
|
(m) => m.estado === "Livre" && m.capacidade >= reserva.pessoas
|
|
);
|
|
|
|
return (
|
|
<AnimatePresence>
|
|
{isOpen && (
|
|
<>
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
onClick={onClose}
|
|
className="fixed inset-0 z-[60] bg-background/80 backdrop-blur-sm"
|
|
/>
|
|
<motion.div
|
|
initial={{ opacity: 0, scale: 0.95, x: "-50%", y: "-50%" }}
|
|
animate={{ opacity: 1, scale: 1, x: "-50%", y: "-50%" }}
|
|
exit={{ opacity: 0, scale: 0.95, x: "-50%", y: "-50%" }}
|
|
className="fixed left-1/2 top-1/2 z-[70] w-[90%] max-w-lg -translate-x-1/2 -translate-y-1/2 rounded-2xl border border-border bg-card p-8 shadow-[0_0_50px_-12px_rgba(0,0,0,0.5)]"
|
|
>
|
|
<div className="flex items-center justify-between mb-6">
|
|
<h3 className="text-xl font-display font-bold">Atribuir Mesa</h3>
|
|
<button onClick={onClose} className="rounded-full p-1 hover:bg-muted">
|
|
<X className="h-5 w-5" />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="mb-6 rounded-lg bg-muted/50 p-4">
|
|
<p className="text-sm font-medium text-muted-foreground uppercase tracking-wider mb-1">Reserva de</p>
|
|
<p className="font-bold text-lg">{reserva.clienteEmail}</p>
|
|
<p className="text-sm text-muted-foreground">{reserva.pessoas} pessoas • {reserva.hora}</p>
|
|
</div>
|
|
|
|
<div className="space-y-4">
|
|
<p className="text-sm font-medium">Mesas Disponíveis (Capacidade ≥ {reserva.pessoas})</p>
|
|
|
|
<div className="grid grid-cols-2 gap-3 max-h-60 overflow-y-auto pr-2">
|
|
{mesasDisponiveis.map((mesa) => (
|
|
<button
|
|
key={mesa.id}
|
|
onClick={() => onAssign(mesa)}
|
|
className="flex flex-col items-center justify-center rounded-lg border border-border p-3 hover:border-primary/50 hover:bg-primary/5 transition-all group"
|
|
>
|
|
<TableIcon className="h-5 w-5 mb-1 text-muted-foreground group-hover:text-primary" />
|
|
<span className="font-bold text-lg">Mesa {mesa.numero}</span>
|
|
<span className="text-xs text-muted-foreground">{mesa.capacidade} lugares</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{mesasDisponiveis.length === 0 && (
|
|
<div className="text-center py-6 border-2 border-dashed rounded-lg">
|
|
<p className="text-sm text-muted-foreground text-destructive">Nenhuma mesa livre com capacidade suficiente.</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="mt-8 flex gap-3">
|
|
<Button variant="outline" className="flex-1" onClick={() => onAssign({ numero: 0 } as any)}>
|
|
Confirmar sem Mesa
|
|
</Button>
|
|
<Button variant="ghost" onClick={onClose}>Cancelar</Button>
|
|
</div>
|
|
</motion.div>
|
|
</>
|
|
)}
|
|
</AnimatePresence>
|
|
);
|
|
}
|