137 lines
5.7 KiB
TypeScript
137 lines
5.7 KiB
TypeScript
"use client";
|
|
|
|
|
|
import { useState } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
|
|
// ── UI components ──────────────────────────────────────────────────────────
|
|
// NOTE: Toast is now imported from the canonical UI barrel, NOT from Client/Toast.
|
|
import { Alert, Toast, ArchiveButton, ConfirmDialog } from "@/src/Components/UI";
|
|
|
|
// ── Client-specific components ─────────────────────────────────────────────
|
|
import { useClients } from "@/src/hooks/useClients";
|
|
import type { Client, ClientFormData } from "@/src/types/client";
|
|
import { ClientFormModal , ClientTable } from "@/src/Components/Client";
|
|
import { ArchivedClientsModal } from "@/src/Components/Client/archive/ArchivedClientsModal";
|
|
import Header from "@/src/Components/UI/Header";
|
|
|
|
|
|
export default function ClientsPage() {
|
|
const router = useRouter();
|
|
|
|
// ── Modal state ──────────────────────────────────────────────────────────
|
|
// false = closed | null = create mode | Client = edit mode
|
|
const [formTarget, setFormTarget] = useState<Client | null | false>(false);
|
|
const [deleteTarget, setDeleteTarget] = useState<Client | null>(null);
|
|
const [deleting, setDeleting] = useState(false);
|
|
// Archive browser modal open/closed
|
|
const [archiveOpen, setArchiveOpen] = useState(false);
|
|
|
|
// ── Data hook ────────────────────────────────────────────────────────────
|
|
const {
|
|
clients, loading, total, pages, error,
|
|
page, search,
|
|
setPage, handleSearch, clearError,
|
|
createClient, updateClient, deleteClient,
|
|
notification,
|
|
} = useClients();
|
|
|
|
// ── Create / Update handler ──────────────────────────────────────────────
|
|
const handleFormSubmit = async (
|
|
data: ClientFormData,
|
|
isNew: boolean,
|
|
): Promise<boolean> => {
|
|
if (isNew) return createClient(data);
|
|
return updateClient((formTarget as Client).id, data);
|
|
};
|
|
|
|
// ── Delete handler ───────────────────────────────────────────────────────
|
|
const handleDeleteConfirm = async () => {
|
|
if (!deleteTarget || deleting) return;
|
|
setDeleting(true);
|
|
const ok = await deleteClient(deleteTarget.id);
|
|
setDeleting(false);
|
|
if (ok) setDeleteTarget(null);
|
|
};
|
|
|
|
// ── Navigate to address management ──────────────────────────────────────
|
|
// This is called both by the AddressBadge click and the "العناوين" button
|
|
// inside the ClientDetailPanel.
|
|
const handleManageAddresses = (client: Client) => {
|
|
router.push(`/dashboard/clients/${client.id}/addresses`);
|
|
};
|
|
|
|
// ── Render ───────────────────────────────────────────────────────────────
|
|
return (
|
|
<>
|
|
{/*
|
|
* Global toast notification.
|
|
* Using the new UI/Toast which accepts ToastNotification | null.
|
|
* The hook's `notification` shape { type, message } matches ToastNotification exactly.
|
|
*/}
|
|
<Toast notification={notification} />
|
|
|
|
{/* Create / Edit modal */}
|
|
{formTarget !== false && (
|
|
<ClientFormModal
|
|
editClient={formTarget}
|
|
onClose={() => setFormTarget(false)}
|
|
onSubmit={handleFormSubmit}
|
|
/>
|
|
)}
|
|
|
|
{/* Delete confirmation dialog */}
|
|
<ConfirmDialog
|
|
open={!!deleteTarget}
|
|
loading={deleting}
|
|
onCancel={() => { if (!deleting) setDeleteTarget(null); }}
|
|
onConfirm={handleDeleteConfirm}
|
|
title="حذف العميل"
|
|
description={`هل أنت متأكد من حذف ${deleteTarget?.name ?? ""}؟ سيتم حذف جميع عناوينه أيضاً. لا يمكن التراجع عن هذا الإجراء.`}
|
|
/>
|
|
|
|
{/* Archive browser modal */}
|
|
{archiveOpen && (
|
|
<ArchivedClientsModal onClose={() => setArchiveOpen(false)} />
|
|
)}
|
|
|
|
<section style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}>
|
|
|
|
{/* ── Page header ── */}
|
|
<Header
|
|
state={{ total }}
|
|
search={search}
|
|
setSearch={handleSearch}
|
|
module=""
|
|
setModule={() => {}}
|
|
title="العملاء"
|
|
mainTitle="إدارة العملاء"
|
|
setPage={setPage}
|
|
name={"عميل"}
|
|
isAudit={false}
|
|
onAdd={() => setFormTarget(null)}
|
|
/>
|
|
|
|
{/* General load error */}
|
|
{error && <Alert type="error" message={error} onClose={clearError} />}
|
|
|
|
{/* Clients table */}
|
|
<ClientTable
|
|
clients={clients}
|
|
loading={loading}
|
|
search={search}
|
|
page={page}
|
|
pages={pages}
|
|
onEdit={(client) => setFormTarget(client)}
|
|
onDelete={(client) => setDeleteTarget(client)}
|
|
onAddFirst={() => setFormTarget(null)}
|
|
onPageChange={setPage}
|
|
onManageAddresses={handleManageAddresses}
|
|
/>
|
|
</section>
|
|
|
|
{/* Floating button to open the archive browser */}
|
|
<ArchiveButton onClick={() => setArchiveOpen(true)} label="الأرشيف" />
|
|
</>
|
|
);
|
|
} |