112 lines
4.2 KiB
TypeScript
112 lines
4.2 KiB
TypeScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
import { Alert, Input, Button } from "../../UI";
|
||
import { ArchivedClientAddressesTable } from "./ArchivedClientAddressesTable";
|
||
import { ArchivedClientAddressesDetailModal } from "./ArchivedClientAddressesDetailModal";
|
||
import { useArchivedClientAddresses } from "@/src/hooks/archive/useArchiveClientAdresses";
|
||
import type { ArchivedClientAddress } from "@/src/types/client_adresses";
|
||
|
||
interface ArchivedClientsAddressesModalProps {
|
||
onClose: () => void;
|
||
/** Optional — scopes the archive to a single client's addresses.
|
||
* Pass the current clientId when opened from a client's addresses page;
|
||
* omit to browse the full cross-client archive. */
|
||
clientId?: string;
|
||
}
|
||
|
||
export function ArchivedClientsAddressesModal({ onClose, clientId }: ArchivedClientsAddressesModalProps) {
|
||
const [viewAddress, setViewAddress] = useState<ArchivedClientAddress | null>(null);
|
||
|
||
const {
|
||
addresses, total, loading, error, search,
|
||
handleSearch, clearError,
|
||
} = useArchivedClientAddresses(clientId);
|
||
|
||
return (
|
||
<div
|
||
role="dialog" aria-modal="true" aria-labelledby="archive-address-modal-title"
|
||
onClick={e => { if (e.target === e.currentTarget) onClose(); }}
|
||
style={{
|
||
position: "fixed", inset: 0, zIndex: 70,
|
||
background: "rgba(15,23,42,0.6)", backdropFilter: "blur(4px)",
|
||
display: "flex", alignItems: "flex-start", justifyContent: "center",
|
||
padding: "2rem 1rem", overflowY: "auto",
|
||
}}
|
||
>
|
||
{viewAddress && (
|
||
<ArchivedClientAddressesDetailModal address={viewAddress} onClose={() => setViewAddress(null)} />
|
||
)}
|
||
|
||
<div
|
||
onClick={e => e.stopPropagation()}
|
||
style={{
|
||
width: "100%", maxWidth: 920,
|
||
background: "var(--color-surface-sunken)",
|
||
borderRadius: "var(--radius-xl)",
|
||
border: "1px solid var(--color-border)",
|
||
boxShadow: "0 24px 64px rgba(0,0,0,.2)",
|
||
overflow: "hidden",
|
||
}}
|
||
>
|
||
{/* header */}
|
||
<div dir="rtl" style={{
|
||
display: "flex", alignItems: "center", justifyContent: "space-between",
|
||
padding: "1.25rem 1.5rem",
|
||
borderBottom: "1px solid var(--color-border)",
|
||
background: "var(--color-surface)",
|
||
}}>
|
||
<div>
|
||
<p style={{ fontSize: 11, letterSpacing: "0.3em", textTransform: "uppercase", color: "#EA580C", fontWeight: 600, margin: 0 }}>
|
||
الأرشيف
|
||
</p>
|
||
<h2 id="archive-address-modal-title" style={{ fontSize: 17, fontWeight: 700, color: "var(--color-text-primary)", margin: "4px 0 0" }}>
|
||
العناوين المؤرشفة
|
||
<span style={{ marginInlineStart: 8, fontSize: 13, fontWeight: 500, color: "var(--color-text-muted)" }}>
|
||
({total})
|
||
</span>
|
||
</h2>
|
||
</div>
|
||
<Button
|
||
type="button"
|
||
variant="secondary"
|
||
onClick={onClose}
|
||
aria-label="إغلاق"
|
||
style={{ width: 34, height: 34, padding: 0, fontSize: 18, lineHeight: 1 }}
|
||
>
|
||
×
|
||
</Button>
|
||
</div>
|
||
|
||
{/* body */}
|
||
<div style={{ padding: "1.5rem", display: "flex", flexDirection: "column", gap: "1rem" }}>
|
||
{/* search — client-side only: this endpoint has no server-side search/pagination */}
|
||
<div style={{ maxWidth: 320 }}>
|
||
<Input
|
||
label="بحث"
|
||
type="text"
|
||
placeholder="بحث بالنوع أو المدينة أو الفرع..."
|
||
value={search}
|
||
onChange={e => handleSearch(e.target.value)}
|
||
dir="rtl"
|
||
icon={
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||
<circle cx="11" cy="11" r="8" /><path d="m21 21-4.35-4.35" />
|
||
</svg>
|
||
}
|
||
/>
|
||
</div>
|
||
|
||
{error && <Alert type="error" message={error} onClose={clearError} />}
|
||
|
||
<ArchivedClientAddressesTable
|
||
addresses={addresses}
|
||
loading={loading}
|
||
search={search}
|
||
onView={setViewAddress}
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
} |