fix file uplaod

This commit is contained in:
natib21
2026-07-06 14:18:51 +00:00
parent 7913a448a9
commit 8328543686
2 changed files with 60 additions and 15 deletions

View File

@@ -512,6 +512,32 @@ const CONTRACT_INTAKE_SETTINGS: OnboardingDocumentSetting[] = [
const CLEARANCE_DESCRIPTION =
"Operation/clearance documents collected after contract execution, by operation, freight type and customs.";
// ── Driver documents ────────────────────────────────────────────────────────
// Configurable upload area (code "driver_docs") attached to a driver profile —
// license, national ID, contracts, training certificates, etc.
const DRIVER_DOCUMENT_FIELDS: OnboardingField[] = [
{
fileKey: "driver_docs",
fileLabel: "Driver documents",
helpText: "License, national ID, contracts, training certificates, etc.",
isRequired: false,
isMultiple: true,
maxFiles: 20,
allowedExtensions: ["pdf", "jpg", "jpeg", "png", "doc", "docx"],
maxSizeMb: 10,
displayOrder: 1,
},
];
const DRIVER_DOCUMENT_SETTINGS: OnboardingDocumentSetting[] = [
{
code: "driver_docs",
label: "Driver documents",
entity: "driver",
fields: DRIVER_DOCUMENT_FIELDS,
},
];
@Injectable()
export class FileUploadSettingsSeeder {
private readonly logger = new Logger(FileUploadSettingsSeeder.name);
@@ -549,6 +575,11 @@ export class FileUploadSettingsSeeder {
description:
"Commercial/framework documents attached at contract submission.",
})),
...DRIVER_DOCUMENT_SETTINGS.map((s) => ({
...s,
description:
"Documents uploaded against a driver profile (license, ID, contracts, etc.).",
})),
];
for (const documentSetting of allSettings) {

View File

@@ -37,6 +37,7 @@ import {
import { driversService } from "@/services/drivers.service";
import { vehiclesService } from "@/services/vehicles.service";
import { fleetHistoryService, type FleetHistoryEvent } from "@/services/fleet-history.service";
import { fileUploadSettingsService } from "@/services/fileUploadSettings.service";
import { useToast } from "@/hooks/use-toast";
const fmtDate = (iso?: string | null) => {
@@ -70,11 +71,14 @@ const fmtSize = (bytes: number) => {
return kb < 1024 ? `${kb.toFixed(0)} KB` : `${(kb / 1024).toFixed(1)} MB`;
};
// Field key the synthesized driver-docs upload setting is keyed on.
/** Upload-area setting code configured on the File Settings page. */
const DRIVER_DOCS_CODE = "driver_docs";
// Field key the FALLBACK setting is keyed on (used only when the "driver_docs"
// upload area hasn't been configured in File Settings yet).
const DRIVER_DOCS_KEY = "driver_docs";
/** Single-field upload setting so driver docs reuse the shared SmartFileInput
* dropzone (same UX as customer-onboarding document uploads). */
const DRIVER_DOCS_SETTING: IFileUploadSetting = {
/** Fallback single-field setting so the dropzone still works before an admin
* configures the "driver_docs" area in File Settings. */
const DRIVER_DOCS_FALLBACK: IFileUploadSetting = {
id: "driver-docs-setting",
createdAt: "",
updatedAt: "",
@@ -107,7 +111,20 @@ const DRIVER_DOCS_SETTING: IFileUploadSetting = {
const DriverDocuments = ({ driverId }: { driverId: string }) => {
const { toast } = useToast();
const qc = useQueryClient();
const [selected, setSelected] = useState<File[]>([]);
// Files selected per configured field key (SmartFileInput is multi-field).
const [selectedMap, setSelectedMap] = useState<Record<string, File | File[] | null>>({});
const selectedFiles = Object.values(selectedMap).flatMap((v) =>
Array.isArray(v) ? v : v ? [v] : [],
);
// Upload-area configuration from the File Settings page (code "driver_docs").
// Falls back to a default field until an admin configures it there.
const { data: setting } = useQuery({
queryKey: ["file-upload-setting", DRIVER_DOCS_CODE],
queryFn: () => fileUploadSettingsService.getByCode(DRIVER_DOCS_CODE),
retry: false,
});
const activeSetting = setting ?? DRIVER_DOCS_FALLBACK;
const { data: docs = [], isLoading } = useQuery({
queryKey: ["driver", driverId, "documents"],
@@ -145,26 +162,23 @@ const DriverDocuments = ({ driverId }: { driverId: string }) => {
return (
<Card withBorder padding="lg" radius="md">
<Stack gap="md" mb="lg">
<Text fw={600} size="sm">Upload documents</Text>
<Text fw={600} size="sm">{activeSetting.label ?? "Upload documents"}</Text>
<SmartFileInput
file={DRIVER_DOCS_SETTING}
value={{ [DRIVER_DOCS_KEY]: selected }}
onChange={(v) => {
const next = v[DRIVER_DOCS_KEY];
setSelected(Array.isArray(next) ? next : next ? [next] : []);
}}
file={activeSetting}
value={selectedMap}
onChange={setSelectedMap}
/>
<Group justify="flex-end">
<Button
size="xs"
leftSection={<Upload size={14} />}
loading={uploadMutation.isPending}
disabled={selected.length === 0}
disabled={selectedFiles.length === 0}
onClick={() =>
uploadMutation.mutate(selected, { onSuccess: () => setSelected([]) })
uploadMutation.mutate(selectedFiles, { onSuccess: () => setSelectedMap({}) })
}
>
Upload {selected.length > 0 ? `(${selected.length})` : ""}
Upload {selectedFiles.length > 0 ? `(${selectedFiles.length})` : ""}
</Button>
</Group>
</Stack>