feat: add client management module
This commit is contained in:
130
src/app/(modules)/clients/page.tsx
Normal file
130
src/app/(modules)/clients/page.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
'use client';
|
||||
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { Building2, Plus } from 'lucide-react';
|
||||
|
||||
import { PageHeader } from '@/components/page-header';
|
||||
import { PoweredBy } from '@/components/powered-by';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { PERMISSIONS } from '@/constants/permissions';
|
||||
import { PermissionGuard } from '@/guards';
|
||||
import type { Client } from '@/types';
|
||||
|
||||
import { useClientColumns } from './components/ClientColumns';
|
||||
import { ClientFilters } from './components/ClientFilters';
|
||||
import { ClientSheet } from './components/ClientSheet';
|
||||
import { ClientTable } from './components/ClientTable';
|
||||
import { useClientFilters } from './hooks/useClientFilters';
|
||||
import { useClientForm } from './hooks/useClientForm';
|
||||
import { useClientStatusMutation } from './hooks/useClientMutations';
|
||||
import { useClientsQuery } from './hooks/useClientQueries';
|
||||
|
||||
export default function ClientsPage() {
|
||||
const [isSheetOpen, setIsSheetOpen] = useState(false);
|
||||
const {
|
||||
skip,
|
||||
setSkip,
|
||||
limit,
|
||||
searchTerm,
|
||||
debouncedSearchTerm,
|
||||
setSearchTerm,
|
||||
statusFilter,
|
||||
setStatusFilter,
|
||||
} = useClientFilters();
|
||||
|
||||
const clientsQuery = useClientsQuery({
|
||||
skip,
|
||||
limit,
|
||||
searchTerm: debouncedSearchTerm,
|
||||
statusFilter,
|
||||
});
|
||||
const clientForm = useClientForm({
|
||||
onSaved: () => setIsSheetOpen(false),
|
||||
});
|
||||
const { openCreate: prepareCreateClient, openEdit: prepareEditClient } = clientForm;
|
||||
const { register, handleSubmit, clientId, isSaving } = clientForm;
|
||||
const statusMutation = useClientStatusMutation();
|
||||
const { mutate: updateClientStatus, pendingClientId } = statusMutation;
|
||||
|
||||
const openCreate = useCallback(() => {
|
||||
prepareCreateClient();
|
||||
setIsSheetOpen(true);
|
||||
}, [prepareCreateClient]);
|
||||
|
||||
const openEdit = useCallback(
|
||||
(client: Client) => {
|
||||
prepareEditClient(client);
|
||||
setIsSheetOpen(true);
|
||||
},
|
||||
[prepareEditClient],
|
||||
);
|
||||
|
||||
const toggleStatus = useCallback(
|
||||
(client: Client) => {
|
||||
updateClientStatus(client);
|
||||
},
|
||||
[updateClientStatus],
|
||||
);
|
||||
|
||||
const columns = useClientColumns({
|
||||
onEdit: openEdit,
|
||||
onToggleStatus: toggleStatus,
|
||||
pendingClientId,
|
||||
});
|
||||
|
||||
const total = clientsQuery.data?.total ?? 0;
|
||||
const clients = clientsQuery.data?.items ?? [];
|
||||
const toolbar = useMemo(
|
||||
() => (
|
||||
<ClientFilters
|
||||
searchTerm={searchTerm}
|
||||
statusFilter={statusFilter}
|
||||
onSearchChange={setSearchTerm}
|
||||
onStatusChange={setStatusFilter}
|
||||
/>
|
||||
),
|
||||
[searchTerm, setSearchTerm, setStatusFilter, statusFilter],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<main className="relative z-10 space-y-5">
|
||||
<PageHeader
|
||||
title="Client Management"
|
||||
description="Manage client company and contact details"
|
||||
icon={Building2}
|
||||
actions={
|
||||
<PermissionGuard permissions={PERMISSIONS.CLIENT.CREATE}>
|
||||
<Button onClick={openCreate}>
|
||||
<Plus className="mr-2 size-4" />
|
||||
Add Client
|
||||
</Button>
|
||||
</PermissionGuard>
|
||||
}
|
||||
/>
|
||||
|
||||
<ClientTable
|
||||
columns={columns}
|
||||
clients={clients}
|
||||
isLoading={clientsQuery.isLoading}
|
||||
toolbar={toolbar}
|
||||
skip={skip}
|
||||
limit={limit}
|
||||
total={total}
|
||||
onPageChange={setSkip}
|
||||
/>
|
||||
|
||||
<PoweredBy />
|
||||
</main>
|
||||
|
||||
<ClientSheet
|
||||
open={isSheetOpen}
|
||||
onOpenChange={setIsSheetOpen}
|
||||
clientId={clientId}
|
||||
register={register}
|
||||
onSubmit={handleSubmit}
|
||||
isSaving={isSaving}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user