"use client"; import {useState, useEffect, useMemo, useCallback} from "react"; import {Button} from "@/components/ui/button"; import {Input} from "@/components/ui/input"; import {Card, CardContent} from "@/components/ui/card"; import { Pagination, PaginationContent, PaginationItem, PaginationNext, PaginationPrevious } from "@/components/ui/pagination"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import {motion} from "framer-motion"; import {ArrowRight} from "lucide-react"; import {NewCustomerModal} from "@/components/customers/modal/NewCustomerModal"; import {Customer} from "@/services/customers/entities/customer"; import Link from "next/link"; import {useErrorHandler} from "@/components/error-boundary"; import {showError} from "@/lib/ui/showToast"; export default function CustomersPage() { const [customers, setCustomers] = useState([]); const [search, setSearch] = useState(""); const [loading, setLoading] = useState(true); const [page, setPage] = useState(1); const pageSize = 15; const handleError = useErrorHandler(); // Wrap the loadCustomers function with useCallback const loadCustomers = useCallback(async () => { setLoading(true); try { const response = await fetch('/api/customers'); if (!response.ok) { showError("Failed to fetch customers data"); throw new Error(`Failed to fetch customers: ${response.statusText}`); } const data = await response.json(); setCustomers(data); } catch (error) { showError("Failed to fetch customers data (1)"); handleError(error); setCustomers([]); } finally { setLoading(false); } }, [handleError]); // Include handleError as a dependency useEffect(() => { loadCustomers(); }, [loadCustomers]); // Add loadCustomers to the dependency array const filtered = useMemo(() => { if (customers.length === 0) return []; return customers.filter( (c) => c.name.toLowerCase().includes(search.toLowerCase()) || c.email.toLowerCase().includes(search.toLowerCase()) || c.companyName.toLowerCase().includes(search.toLowerCase()) || c.street.toLowerCase().includes(search.toLowerCase()) || c.zip.toLowerCase().includes(search.toLowerCase()) || c.city.toLowerCase().includes(search.toLowerCase()) || c.phoneNumbers?.[0]?.number?.toLowerCase().includes(search.toLowerCase()) ); }, [customers, search]); const paginated = useMemo(() => { const start = (page - 1) * pageSize; return filtered.slice(start, start + pageSize); }, [filtered, page]); const totalPages = Math.ceil(filtered.length / pageSize); return (
Kunden
{customers.length}
Demo-Statistik
Letzte Aktivität
setSearch(e.target.value)}/>
{customers.length === 0 && loading ? (
Lade Kunden...
) : (
Name E-Mail Firma Telefon Straße PLZ Ort Erstellt am Aktionen {paginated.map((customer) => ( {customer.name} {customer.email} {customer.companyName} {customer.phoneNumbers?.[0]?.number} {customer.street} {customer.zip} {customer.city} {new Date(customer.createdAt).toLocaleString()} ))}
)} setPage((p) => Math.max(1, p - 1))} className={page === 1 ? "pointer-events-none opacity-50" : ""} /> setPage((p) => Math.min(totalPages, p + 1))} className={page === totalPages ? "pointer-events-none opacity-50" : ""} />
); }