solve problem tree rerender
This commit is contained in:
@@ -5,28 +5,42 @@ import { Alert, ArchiveButton, ConfirmDialog } from "@/src/Components/UI";
|
||||
import { ArchivedDrivers } from "@/src/Components/Driver/archive/ArchivedDrivers";
|
||||
import { DriverTable } from "@/src/Components/Driver/DriverTable";
|
||||
import { useDrivers } from "@/src/hooks/useDriver";
|
||||
import { CreateDriverPayload, Driver, UpdateDriverPayload } from "@/src/types/driver";
|
||||
import { DriverDetailPanel, DriverFormModal , } from "@/src/Components/Driver";
|
||||
import {
|
||||
CreateDriverPayload,
|
||||
Driver,
|
||||
UpdateDriverPayload,
|
||||
} from "@/src/types/driver";
|
||||
import { DriverDetailPanel, DriverFormModal } from "@/src/Components/Driver";
|
||||
|
||||
// ── Page Component ────────────────────────────────────────────────────────────
|
||||
|
||||
export default function DriversPage() {
|
||||
const {
|
||||
drivers, loading, error, total, pages, page,
|
||||
search, setPage, handleSearch, clearError,
|
||||
createDriver, updateDriver, deleteDriver,
|
||||
drivers,
|
||||
loading,
|
||||
error,
|
||||
total,
|
||||
pages,
|
||||
page,
|
||||
search,
|
||||
setPage,
|
||||
handleSearch,
|
||||
clearError,
|
||||
createDriver,
|
||||
updateDriver,
|
||||
deleteDriver,
|
||||
notification,
|
||||
} = useDrivers();
|
||||
|
||||
// ── Panel / modal state ───────────────────────────────────────────────────
|
||||
const [selectedDriverId, setSelectedDriverId] = useState<string | null>(null);
|
||||
const [formDriver, setFormDriver] = useState<Driver | null | "new">(null);
|
||||
const [deleteTarget, setDeleteTarget] = useState<Driver | null>(null);
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
const [formDriver, setFormDriver] = useState<Driver | null | "new">(null);
|
||||
const [deleteTarget, setDeleteTarget] = useState<Driver | null>(null);
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
// Bumped after a successful edit to force the detail panel to re-fetch
|
||||
const [panelRefreshKey, setPanelRefreshKey] = useState(0);
|
||||
const [panelRefreshKey, setPanelRefreshKey] = useState(0);
|
||||
// Archive browser modal open/closed
|
||||
const [archiveOpen, setArchiveOpen] = useState(false);
|
||||
const [archiveOpen, setArchiveOpen] = useState(false);
|
||||
|
||||
// ── Handlers ──────────────────────────────────────────────────────────────
|
||||
const handleEdit = useCallback((driver: Driver) => {
|
||||
@@ -84,39 +98,95 @@ export default function DriversPage() {
|
||||
// ── Render ────────────────────────────────────────────────────────────────
|
||||
return (
|
||||
<>
|
||||
<section style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}>
|
||||
|
||||
<section
|
||||
style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}
|
||||
>
|
||||
{/* ── Header ── */}
|
||||
<header style={{
|
||||
borderRadius: "var(--radius-xl)",
|
||||
border: "1px solid var(--color-border)",
|
||||
background: "var(--color-surface)",
|
||||
padding: "1.5rem 2rem",
|
||||
boxShadow: "var(--shadow-card)",
|
||||
}}>
|
||||
<p style={{ fontSize: 11, letterSpacing: "0.3em", textTransform: "uppercase", color: "#2563EB", fontWeight: 600 }}>
|
||||
<header
|
||||
style={{
|
||||
borderRadius: "var(--radius-xl)",
|
||||
border: "1px solid var(--color-border)",
|
||||
background: "var(--color-surface)",
|
||||
padding: "1.5rem 2rem",
|
||||
boxShadow: "var(--shadow-card)",
|
||||
}}
|
||||
>
|
||||
<p
|
||||
style={{
|
||||
fontSize: 11,
|
||||
letterSpacing: "0.3em",
|
||||
textTransform: "uppercase",
|
||||
color: "#2563EB",
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
إدارة الكوادر
|
||||
</p>
|
||||
<div style={{ marginTop: "0.75rem", display: "flex", flexDirection: "column", gap: "1rem" }}>
|
||||
<div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", flexWrap: "wrap", gap: "1rem" }}>
|
||||
<div
|
||||
style={{
|
||||
marginTop: "0.75rem",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "1rem",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "flex-end",
|
||||
justifyContent: "space-between",
|
||||
flexWrap: "wrap",
|
||||
gap: "1rem",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<h1 style={{ fontSize: "1.5rem", fontWeight: 700, color: "var(--color-text-primary)", margin: 0 }}>
|
||||
<h1
|
||||
style={{
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: 700,
|
||||
color: "var(--color-text-primary)",
|
||||
margin: 0,
|
||||
}}
|
||||
>
|
||||
السائقون
|
||||
</h1>
|
||||
<p style={{ marginTop: "0.25rem", fontSize: 13, color: "var(--color-text-muted)" }}>
|
||||
<p
|
||||
style={{
|
||||
marginTop: "0.25rem",
|
||||
fontSize: 13,
|
||||
color: "var(--color-text-muted)",
|
||||
}}
|
||||
>
|
||||
إجمالي{" "}
|
||||
<strong style={{ color: "var(--color-text-primary)" }}>{total}</strong>{" "}
|
||||
<strong style={{ color: "var(--color-text-primary)" }}>
|
||||
{total}
|
||||
</strong>{" "}
|
||||
سائق مسجل
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style={{ display: "flex", gap: "0.75rem", alignItems: "center", flexWrap: "wrap" }}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: "0.75rem",
|
||||
alignItems: "center",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
{/* Search */}
|
||||
<div style={{ position: "relative", width: 288 }}>
|
||||
<i
|
||||
className="ti ti-search"
|
||||
aria-hidden="true"
|
||||
style={{ position: "absolute", right: 12, top: "50%", transform: "translateY(-50%)", fontSize: 16, color: "var(--color-text-hint)", pointerEvents: "none" }}
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: 12,
|
||||
top: "50%",
|
||||
transform: "translateY(-50%)",
|
||||
fontSize: 16,
|
||||
color: "var(--color-text-hint)",
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
@@ -125,12 +195,17 @@ export default function DriversPage() {
|
||||
onChange={(e) => handleSearch(e.target.value)}
|
||||
dir="rtl"
|
||||
style={{
|
||||
width: "100%", height: 40, paddingRight: 36, paddingLeft: 12,
|
||||
width: "100%",
|
||||
height: 40,
|
||||
paddingRight: 36,
|
||||
paddingLeft: 12,
|
||||
borderRadius: "var(--radius-lg)",
|
||||
border: "1px solid var(--color-border)",
|
||||
background: "var(--color-surface)",
|
||||
fontSize: 13, color: "var(--color-text-primary)",
|
||||
outline: "none", fontFamily: "var(--font-sans)",
|
||||
fontSize: 13,
|
||||
color: "var(--color-text-primary)",
|
||||
outline: "none",
|
||||
fontFamily: "var(--font-sans)",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -140,18 +215,27 @@ export default function DriversPage() {
|
||||
type="button"
|
||||
onClick={() => setFormDriver("new")}
|
||||
style={{
|
||||
height: 40, padding: "0 1.25rem",
|
||||
height: 40,
|
||||
padding: "0 1.25rem",
|
||||
borderRadius: "var(--radius-lg)",
|
||||
border: "none",
|
||||
background: "var(--color-brand-600)",
|
||||
fontSize: 13, fontWeight: 700, color: "#FFF",
|
||||
fontSize: 13,
|
||||
fontWeight: 700,
|
||||
color: "#FFF",
|
||||
cursor: "pointer",
|
||||
display: "flex", alignItems: "center", gap: 8,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
fontFamily: "var(--font-sans)",
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
<i className="ti ti-plus" style={{ fontSize: 15 }} aria-hidden="true" />
|
||||
<i
|
||||
className="ti ti-plus"
|
||||
style={{ fontSize: 15 }}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
إضافة سائق
|
||||
</button>
|
||||
</div>
|
||||
@@ -163,9 +247,7 @@ export default function DriversPage() {
|
||||
{notification && (
|
||||
<Alert type={notification.type} message={notification.message} />
|
||||
)}
|
||||
{error && (
|
||||
<Alert type="error" message={error} onClose={clearError} />
|
||||
)}
|
||||
{error && <Alert type="error" message={error} onClose={clearError} />}
|
||||
|
||||
{/* ── Table ── */}
|
||||
<DriverTable
|
||||
@@ -195,6 +277,11 @@ export default function DriversPage() {
|
||||
{/* ── Form modal ── */}
|
||||
{formDriver !== null && (
|
||||
<DriverFormModal
|
||||
// CHANGE: added key — forces remount on switching between "new" and
|
||||
// different edit targets, same fix applied to UserFormModal, so
|
||||
// useForm's defaultValues (roleId/branchId/status/etc.) always match
|
||||
// the correct driver instead of possibly reusing stale form state.
|
||||
key={formDriver === "new" ? "new" : formDriver.id}
|
||||
editDriver={formDriver === "new" ? null : formDriver}
|
||||
branches={[]}
|
||||
onClose={() => setFormDriver(null)}
|
||||
@@ -213,12 +300,10 @@ export default function DriversPage() {
|
||||
/>
|
||||
|
||||
{/* ── Archive browser modal ── */}
|
||||
{archiveOpen && (
|
||||
<ArchivedDrivers onClose={() => setArchiveOpen(false)} />
|
||||
)}
|
||||
{archiveOpen && <ArchivedDrivers onClose={() => setArchiveOpen(false)} />}
|
||||
|
||||
{/* ── Floating button to open the archive browser ── */}
|
||||
<ArchiveButton onClick={() => setArchiveOpen(true)} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user