'use client';
import { useState, useEffect, useCallback } from 'react';
import type { Customer } from '@/types';
import { customersApi } from '@/lib/api-client';
const PAGE_SIZE = 20;
// ── Modal genérico ────────────────────────────────────────────────────────────
function Modal({ title, onClose, children }: { title: string; onClose: () => void; children: React.ReactNode }) {
return (
e.stopPropagation()}>
{children}
);
}
// ── Formulario crear cliente ─────────────────────────────────────────────────
function CreateForm({ onClose, onCreated }: { onClose: () => void; onCreated: () => void }) {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [displayName, setDisplayName] = useState('');
const [phone, setPhone] = useState('');
const [saving, setSaving] = useState(false);
const [error, setError] = useState('');
const handle = async (e: React.FormEvent) => {
e.preventDefault();
setSaving(true); setError('');
try {
await customersApi.create({ email, password, displayName: displayName || undefined, phone: phone || undefined });
onCreated();
onClose();
} catch (err) {
setError(err instanceof Error ? err.message : 'Error al crear cliente');
} finally {
setSaving(false);
}
};
return (
);
}
// ── Formulario editar cliente ────────────────────────────────────────────────
function EditForm({ customer, onClose, onSaved }: { customer: Customer; onClose: () => void; onSaved: () => void }) {
const [displayName, setDisplayName] = useState('');
const [phone, setPhone] = useState('');
const [saving, setSaving] = useState(false);
const [error, setError] = useState('');
useEffect(() => {
setDisplayName(customer.displayName || '');
setPhone(customer.phone || '');
}, [customer]);
const handle = async (e: React.FormEvent) => {
e.preventDefault();
setSaving(true); setError('');
try {
await customersApi.update(customer.id, {
displayName: displayName || undefined,
phone: phone || undefined,
});
onSaved();
onClose();
} catch (err) {
setError(err instanceof Error ? err.message : 'Error al guardar');
} finally {
setSaving(false);
}
};
return (
);
}
// ── Página principal ───────────────────────────────────────────────────────────
export default function CustomersPage() {
const [customers, setCustomers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [search, setSearch] = useState('');
const [debounced, setDebounced] = useState('');
const [page, setPage] = useState(0);
const [total, setTotal] = useState(0);
const [showCreate, setShowCreate] = useState(false);
const [editing, setEditing] = useState(null);
const [msg, setMsg] = useState('');
useEffect(() => {
const t = setTimeout(() => setDebounced(search), 400);
return () => clearTimeout(t);
}, [search]);
useEffect(() => { setPage(0); }, [debounced]);
const load = useCallback(async () => {
setLoading(true); setError('');
try {
const data = await customersApi.list({ limit: PAGE_SIZE, offset: page * PAGE_SIZE, q: debounced || undefined });
setCustomers(data.items ?? []);
setTotal(data.total ?? 0);
} catch (e) {
setError(e instanceof Error ? e.message : 'Error');
} finally {
setLoading(false);
}
}, [page, debounced]);
useEffect(() => { load(); }, [load]);
const handleCreated = () => { setMsg('Cliente creado correctamente'); setTimeout(() => setMsg(''), 3000); load(); };
const handleSaved = () => { setMsg('Cliente actualizado'); setTimeout(() => setMsg(''), 3000); load(); };
return (
{/* Header */}
Clientes
{total > 0 ? `${total} cliente${total !== 1 ? 's' : ''}` : ''}
{msg && (
{msg}
)}
{/* Buscador */}
{/* Tabla */}
{loading ? (
) : error ? (
) : customers.length === 0 ? (
) : (
<>
{['Email', 'Nombre', 'Teléfono', 'Rol', 'Alta', ''].map((h) => (
| {h} |
))}
{customers.map((c) => (
| {c.email} |
{c.displayName || '—'} |
{c.phone || '—'} |
{c.role}
|
{c.createdAt ? new Date(c.createdAt).toLocaleDateString('es-ES') : '—'}
|
|
))}
{/* Paginación */}
Página {page + 1}
>
)}
{/* Modal crear */}
{showCreate && (
setShowCreate(false)}>
setShowCreate(false)} onCreated={handleCreated} />
)}
{/* Modal editar */}
{editing && (
setEditing(null)}>
setEditing(null)} onSaved={handleSaved} />
)}
);
}