fix: resolve permission fallback bug, remove debug code, and cleanup duplication
Logic Errors ------------ - Sidebar: fix permissions fallback so a user with no permissions gets zero access instead of falling back to the full nav list (user?.permissions ?? [] instead of ?? navSections.flatMap(...)) - carMaintanance.service / UseCarsMaintanance: add pagination to the maintenance records fetch instead of loading the entire list at once - api.ts: redact sensitive fields (password, token) before logging the request body in console.debug, to avoid leaking credentials/PII Code Flow Problems ------------------- - OrderFormModal: remove leftover console.log/debug statements and the redundant onClick handler on the submit button - auth: remove the unused src/service/auth.service.ts (axios) and keep only src/services/auth.service.ts (fetch); fix useAuth.ts import path from
This commit is contained in:
@@ -2,9 +2,8 @@
|
||||
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import { Spinner } from "@/src/Components/UI";
|
||||
import { ConfirmDialog, Spinner } from "@/src/Components/UI";
|
||||
import { TripFormModal } from "@/src/Components/Trip/Tripformmodal";
|
||||
import { TripDeleteModal } from "@/src/Components/Trip/Tripdeletemodal";
|
||||
import { TripReportPanel } from "@/src/Components/Trip_Report/Tripreportpanel";
|
||||
import { tripService } from "@/src/services/trip.service";
|
||||
import { getStoredToken } from "@/src/lib/auth";
|
||||
@@ -206,44 +205,42 @@ export default function TripDetailPage() {
|
||||
|
||||
// ── Load trip ─────────────────────────────────────────────────────────────
|
||||
const loadTrip = useCallback(async () => {
|
||||
if (!tripId) return;
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const token = getStoredToken();
|
||||
const res = await tripService.getById(tripId, token);
|
||||
setTrip((res as unknown as { data: Trip }).data);
|
||||
} catch (err: unknown) {
|
||||
setError(err instanceof Error ? err.message : "تعذّر تحميل بيانات الرحلة.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [tripId]);
|
||||
|
||||
if (!tripId) return;
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const token = getStoredToken();
|
||||
const data = await tripService.getById(tripId, token);
|
||||
setTrip(data);
|
||||
} catch (err: unknown) {
|
||||
setError(err instanceof Error ? err.message : "تعذّر تحميل بيانات الرحلة.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [tripId]);
|
||||
useEffect(() => {
|
||||
queueMicrotask(loadTrip);
|
||||
}, [loadTrip]);
|
||||
|
||||
// ── Edit submit ───────────────────────────────────────────────────────────
|
||||
const handleEditSubmit = useCallback(
|
||||
async (
|
||||
payload: CreateTripPayload | UpdateTripPayload,
|
||||
): Promise<boolean> => {
|
||||
if (!trip) return false;
|
||||
try {
|
||||
const token = getStoredToken();
|
||||
const res = await tripService.update(trip.id, payload as UpdateTripPayload, token);
|
||||
const updated = (res as unknown as { data: Trip }).data;
|
||||
setTrip(updated);
|
||||
notify({ type: "success", message: "تم تحديث بيانات الرحلة بنجاح." });
|
||||
return true;
|
||||
} catch (err) {
|
||||
notify({ type: "error", message: extractApiMessage(err, "تعذّر تحديث الرحلة.") });
|
||||
return false;
|
||||
}
|
||||
},
|
||||
[trip, notify],
|
||||
);
|
||||
async (
|
||||
payload: CreateTripPayload | UpdateTripPayload,
|
||||
): Promise<boolean> => {
|
||||
if (!trip) return false;
|
||||
try {
|
||||
const token = getStoredToken();
|
||||
const updated = await tripService.update(trip.id, payload as UpdateTripPayload, token);
|
||||
setTrip(updated);
|
||||
notify({ type: "success", message: "تم تحديث بيانات الرحلة بنجاح." });
|
||||
return true;
|
||||
} catch (err) {
|
||||
notify({ type: "error", message: extractApiMessage(err, "تعذّر تحديث الرحلة.") });
|
||||
return false;
|
||||
}
|
||||
},
|
||||
[trip, notify],
|
||||
);
|
||||
|
||||
// ── Delete confirm ────────────────────────────────────────────────────────
|
||||
const handleConfirmDelete = useCallback(async () => {
|
||||
@@ -558,14 +555,14 @@ export default function TripDetailPage() {
|
||||
)}
|
||||
|
||||
{/* ── Delete modal ── */}
|
||||
{deleteOpen && (
|
||||
<TripDeleteModal
|
||||
trip={trip}
|
||||
deleting={deleting}
|
||||
onCancel={() => setDeleteOpen(false)}
|
||||
onConfirm={handleConfirmDelete}
|
||||
/>
|
||||
)}
|
||||
<ConfirmDialog
|
||||
open={deleteOpen}
|
||||
loading={deleting}
|
||||
onCancel={() => setDeleteOpen(false)}
|
||||
onConfirm={handleConfirmDelete}
|
||||
title="حذف الرحلة"
|
||||
description={`هل أنت متأكد من حذف رحلة ${trip.title} (${trip.tripNumber})؟ لا يمكن التراجع عن هذا الإجراء.`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -31,10 +31,8 @@ export default function ArchivedTripDetailPage() {
|
||||
setError(null);
|
||||
try {
|
||||
const token = getStoredToken();
|
||||
// Archived trips must go through the archived endpoint —
|
||||
// the normal /trip/:id endpoint won't return soft-deleted trips.
|
||||
const res = await tripService.getArchivedById(tripId, token);
|
||||
if (!cancelled) setTrip((res as unknown as { data: Trip }).data);
|
||||
const data = await tripService.getArchivedById(tripId, token);
|
||||
if (!cancelled) setTrip(data);
|
||||
} catch {
|
||||
if (!cancelled) setError("لم يتم العثور على هذه الرحلة في الأرشيف.");
|
||||
} finally {
|
||||
@@ -54,7 +52,6 @@ export default function ArchivedTripDetailPage() {
|
||||
);
|
||||
}
|
||||
|
||||
// Edge case: invalid/missing/unreachable trip ID
|
||||
if (error || !trip) {
|
||||
return (
|
||||
<EmptyState
|
||||
|
||||
@@ -4,10 +4,8 @@ import { useCallback, useEffect, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useTrips } from "@/src/hooks/useTrip";
|
||||
import { TripFormModal } from "@/src/Components/Trip/Tripformmodal";
|
||||
import { TripDeleteModal } from "@/src/Components/Trip/Tripdeletemodal";
|
||||
import { ArchivedTripList } from "@/src/Components/Trip/archive/ArchivedTripList";
|
||||
import { Alert, Spinner, ArchiveButton } from "@/src/Components/UI";
|
||||
import { Toast } from "@/src/Components/UI/Toast";
|
||||
import { Alert, Spinner, ArchiveButton, ConfirmDialog , Toast } from "@/src/Components/UI";
|
||||
import type {
|
||||
Trip,
|
||||
TripStatus,
|
||||
@@ -748,14 +746,14 @@ export default function TripsPage() {
|
||||
)}
|
||||
|
||||
{/* ── Delete modal ── */}
|
||||
{deleteTarget && (
|
||||
<TripDeleteModal
|
||||
trip={deleteTarget}
|
||||
deleting={deleting}
|
||||
onCancel={() => setDeleteTarget(null)}
|
||||
onConfirm={handleConfirmDelete}
|
||||
/>
|
||||
)}
|
||||
<ConfirmDialog
|
||||
open={!!deleteTarget}
|
||||
loading={deleting}
|
||||
onCancel={() => setDeleteTarget(null)}
|
||||
onConfirm={handleConfirmDelete}
|
||||
title="حذف الرحلة"
|
||||
description={`هل أنت متأكد من حذف رحلة ${deleteTarget?.title ?? ""} (${deleteTarget?.tripNumber ?? ""})؟ لا يمكن التراجع عن هذا الإجراء.`}
|
||||
/>
|
||||
|
||||
{/* ── Archive browser modal ── */}
|
||||
{archiveOpen && (
|
||||
@@ -768,4 +766,4 @@ export default function TripsPage() {
|
||||
<Toast notification={notification} onDismiss={dismissNotification} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user