'use client'; import { useState, useEffect } from 'react'; import Link from 'next/link'; import { useRouter, useSearchParams } from 'next/navigation'; import DeleteButton from './DeleteButton'; import Pagination from '@/lib/components/Pagination'; interface Customer { id: string; name: string; url: string; email: string; createdAt: string; modifiedAt: string; } interface PaginationInfo { page: number; pageSize: number; totalCount: number; totalPages: number; } interface CustomersResponse { data: Customer[]; pagination: PaginationInfo; } export default function AdminCustomers() { const router = useRouter(); const searchParams = useSearchParams(); // Get pagination values from URL params const initialPage = parseInt(searchParams.get('page') || '1'); const initialPageSize = parseInt(searchParams.get('pageSize') || '10'); // State for pagination const [page, setPage] = useState(initialPage); const [pageSize, setPageSize] = useState(initialPageSize); // Search filters state const [filters, setFilters] = useState({ name: '', email: '', url: '', hasEmail: false }); const [debouncedFilters, setDebouncedFilters] = useState(filters); // State for data const [customers, setCustomers] = useState([]); const [pagination, setPagination] = useState({ page: initialPage, pageSize: initialPageSize, totalCount: 0, totalPages: 0 }); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); // Fetch customers with pagination useEffect(() => { const fetchCustomers = async () => { setIsLoading(true); setError(null); try { // Build query string with pagination and filters const params = new URLSearchParams(); params.append('page', initialPage.toString()); params.append('pageSize', initialPageSize.toString()); if (debouncedFilters.name) params.append('name', debouncedFilters.name); if (debouncedFilters.email) params.append('email', debouncedFilters.email); if (debouncedFilters.url) params.append('url', debouncedFilters.url); if (debouncedFilters.hasEmail) params.append('hasEmail', 'true'); const response = await fetch(`/api/customers?${params.toString()}`); if (!response.ok) { throw new Error('Failed to fetch customers'); } const responseData: CustomersResponse = await response.json(); setCustomers(responseData.data); setPagination(responseData.pagination); } catch (err) { console.error('Error fetching customers:', err); setError(err instanceof Error ? err.message : 'An error occurred'); } finally { setIsLoading(false); } }; fetchCustomers(); }, [initialPage, initialPageSize, debouncedFilters]); // Debounce filter changes useEffect(() => { const timer = setTimeout(() => { setDebouncedFilters(filters); }, 300); return () => clearTimeout(timer); }, [filters]); // Handle filter changes const handleFilterChange = (key: keyof typeof filters, value: string | boolean) => { setFilters(prev => ({ ...prev, [key]: value })); }; // Clear all filters const handleClearFilters = () => { setFilters({ name: '', email: '', url: '', hasEmail: false }); }; // Handle page change const handlePageChange = (newPage: number) => { setPage(newPage); // Build query string with new page const params = new URLSearchParams(searchParams.toString()); params.set('page', newPage.toString()); // Update URL with new page router.push(`/admin/customers?${params.toString()}`); }; return (

Customers

{!isLoading && (

Total: {pagination.totalCount} customer{pagination.totalCount !== 1 ? 's' : ''}

)}
Add New Customer
{/* Search Filters */}

Filters

handleFilterChange('name', e.target.value)} className="block w-full rounded-md border-gray-300 pr-10 focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white sm:text-sm" placeholder="Enter name..." /> {filters.name && ( )}
handleFilterChange('email', e.target.value)} className="block w-full rounded-md border-gray-300 pr-10 focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white sm:text-sm" placeholder="Enter email..." /> {filters.email && ( )}
handleFilterChange('url', e.target.value)} className="block w-full rounded-md border-gray-300 pr-10 focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white sm:text-sm" placeholder="Enter URL..." /> {filters.url && ( )}
handleFilterChange('hasEmail', e.target.checked)} className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 dark:bg-gray-700 dark:border-gray-600" />
{(filters.name || filters.email || filters.url || filters.hasEmail) && (
Active filters: {[ filters.name && 'Name', filters.email && 'Email', filters.url && 'URL', filters.hasEmail && 'Has Email' ].filter(Boolean).join(', ')}
)}
{/* Error Message */} {error && (

{error}

)} {/* Loading State */} {isLoading ? (

Loading customers...

) : (
{customers.length > 0 ? ( customers.map((customer) => ( )) ) : ( )}
ID Name URL Email Created Modified Actions
{customer.id.substring(0, 8)}... {customer.name} {customer.url ? ( {customer.url} ) : ( - )} {customer.email} {new Date(customer.createdAt).toLocaleDateString()} {new Date(customer.modifiedAt).toLocaleDateString()} Edit
No customers found. Create your first customer!
{/* Pagination */}
)}
); }