"use client"; import { useState, useEffect, useCallback } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle, CardFooter } from "@/components/ui/card"; import { cn, formatCurrency, formatDate } from "@/lib/utils"; interface Client { id: string; firstName: string; lastName: string; email: string | null; phone: string | null; } interface ClientsResponse { data: Client[]; pagination: { total: number; limit: number; offset: number; hasMore: boolean; }; } interface MembershipPlan { id: string; name: string; price: number | string; durationMonths: number; courtHours: number | null; discountPercent: number | string | null; } interface AssignMembershipDialogProps { plans: MembershipPlan[]; onClose: () => void; onAssign: (data: { clientId: string; planId: string; startDate: string; endDate: string; }) => Promise; isLoading?: boolean; preselectedClient?: Client; } const durationOptions = [ { value: 1, label: "1 mes" }, { value: 3, label: "3 meses" }, { value: 6, label: "6 meses" }, { value: 12, label: "12 meses" }, ]; export function AssignMembershipDialog({ plans, onClose, onAssign, isLoading = false, preselectedClient, }: AssignMembershipDialogProps) { const [searchQuery, setSearchQuery] = useState(""); const [clients, setClients] = useState([]); const [selectedClient, setSelectedClient] = useState(preselectedClient || null); const [loadingClients, setLoadingClients] = useState(false); const [selectedPlanId, setSelectedPlanId] = useState(plans[0]?.id || ""); const [startDate, setStartDate] = useState(() => { const today = new Date(); return today.toISOString().split("T")[0]; }); const [duration, setDuration] = useState(1); const [endDate, setEndDate] = useState(""); const [error, setError] = useState(null); // Calculate end date based on start date and duration useEffect(() => { if (startDate && duration) { const start = new Date(startDate); start.setMonth(start.getMonth() + duration); setEndDate(start.toISOString().split("T")[0]); } }, [startDate, duration]); // Fetch clients based on search const fetchClients = useCallback(async (search: string) => { if (!search || search.trim().length < 2) { setClients([]); return; } setLoadingClients(true); try { const response = await fetch( `/api/clients?search=${encodeURIComponent(search)}&limit=10` ); if (!response.ok) { throw new Error("Error al buscar clientes"); } const data: ClientsResponse = await response.json(); setClients(data.data); } catch (err) { console.error("Error fetching clients:", err); setClients([]); } finally { setLoadingClients(false); } }, []); // Debounce client search useEffect(() => { const timer = setTimeout(() => { fetchClients(searchQuery); }, 300); return () => clearTimeout(timer); }, [searchQuery, fetchClients]); // Get selected plan details const selectedPlan = plans.find(p => p.id === selectedPlanId); const handleSubmit = async () => { if (!selectedClient) { setError("Selecciona un cliente"); return; } if (!selectedPlanId) { setError("Selecciona un plan"); return; } if (!startDate || !endDate) { setError("Selecciona las fechas"); return; } setError(null); await onAssign({ clientId: selectedClient.id, planId: selectedPlanId, startDate: new Date(startDate).toISOString(), endDate: new Date(endDate).toISOString(), }); }; // Handle click outside to close const handleOverlayClick = (e: React.MouseEvent) => { if (e.target === e.currentTarget) { onClose(); } }; return (
Asignar Membresia
{error && (
{error}
)} {/* Client Selection */} {!preselectedClient && (
setSearchQuery(e.target.value)} autoFocus /> {/* Client search results */}
{loadingClients && (
)} {!loadingClients && searchQuery.length >= 2 && clients.length === 0 && (

No se encontraron clientes.

)} {!loadingClients && clients.map((client) => ( ))}
)} {/* Selected client summary */} {selectedClient && (

Cliente seleccionado:

{selectedClient.firstName} {selectedClient.lastName}

{!preselectedClient && ( )}
)} {/* Plan Selection */}
{/* Selected plan details */} {selectedPlan && (
Precio: {formatCurrency(Number(selectedPlan.price))}
{selectedPlan.courtHours && (
Horas incluidas: {selectedPlan.courtHours}h
)} {selectedPlan.discountPercent && Number(selectedPlan.discountPercent) > 0 && (
Descuento: {Number(selectedPlan.discountPercent)}%
)}
)}
{/* Date Selection */}
setStartDate(e.target.value)} min={new Date().toISOString().split("T")[0]} />
{/* Calculated End Date */} {endDate && (

La membresia expirara el:

{formatDate(endDate)}

)}
); }