Merge pull request #767 from Tria-plc/freight_feature/usermanagement

Freight feature/usermanagement
This commit is contained in:
marshal
2026-07-17 14:40:59 +03:00
committed by GitHub
37 changed files with 736 additions and 365 deletions

View File

@@ -63,8 +63,10 @@ import {
import { contractsService } from "@/services/contracts.service";
import { api } from "@/services/api";
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
import { fileViewUrl } from "@/constants/apiConfig";
import { downloadBookingFile } from "@/services/files.service";
import {
downloadBookingFile,
fetchViewableFile,
} from "@/services/files.service";
import type { CustomerDocument } from "@/types/customer";
import type { Freight } from "@edr/types";
@@ -396,10 +398,9 @@ export default function ContractRequestDetailPage() {
radius="lg"
leftSection={<FileText size={15} />}
onClick={() =>
handleViewFile({
...contractPdf,
url: fileViewUrl(contractPdf.id),
})
void fetchViewableFile(contractPdf.id, contractPdf.name).then(
view,
)
}
>
View contract

View File

@@ -54,7 +54,10 @@ import {
humanize,
} from "@/components/customers";
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
import { fileViewUrl } from "@/constants/apiConfig";
import {
downloadBookingFile,
fetchViewableFile,
} from "@/services/files.service";
import { api } from "@/services/api";
import type {
CompanyProfile,
@@ -212,13 +215,7 @@ export default function CustomerDetailPage() {
variant="subtle"
color="gray"
aria-label={`View ${f.name}`}
onClick={() =>
view({
name: f.name,
url: fileViewUrl(f.id),
mimeType: f.mimeType,
})
}
onClick={() => void fetchViewableFile(f.id, f.name).then(view)}
>
<Eye size={14} />
</ActionIcon>
@@ -227,13 +224,7 @@ export default function CustomerDetailPage() {
type="button"
size="xs"
lineClamp={1}
onClick={() =>
view({
name: f.name,
url: fileViewUrl(f.id),
mimeType: f.mimeType,
})
}
onClick={() => void fetchViewableFile(f.id, f.name).then(view)}
style={{
maxWidth: 170,
textAlign: "left",
@@ -412,18 +403,19 @@ export default function CustomerDetailPage() {
aria-label="View"
data-stop-row-click
onClick={() =>
view({
name: row.original.name,
url: fileViewUrl(row.original.id),
mimeType: row.original.mimeType,
})
void fetchViewableFile(row.original.id, row.original.name).then(
view,
)
}
>
<Eye size={16} />
</ActionIcon>
<ActionIcon
component="a"
href={fileViewUrl(row.original.id, true)}
component="button"
type="button"
onClick={() =>
void downloadBookingFile(row.original.id, row.original.name)
}
variant="subtle"
color="gray"
aria-label="Download"
@@ -839,11 +831,7 @@ export default function CustomerDetailPage() {
size="sm"
lineClamp={1}
onClick={() =>
view({
name: doc.name,
url: fileViewUrl(doc.id),
mimeType: doc.mimeType,
})
void fetchViewableFile(doc.id, doc.name).then(view)
}
>
{doc.name}
@@ -869,18 +857,17 @@ export default function CustomerDetailPage() {
color="gray"
aria-label={`Preview ${doc.name}`}
onClick={() =>
view({
name: doc.name,
url: fileViewUrl(doc.id),
mimeType: doc.mimeType,
})
void fetchViewableFile(doc.id, doc.name).then(view)
}
>
<Eye size={16} />
</ActionIcon>
<ActionIcon
component="a"
href={fileViewUrl(doc.id, true)}
component="button"
type="button"
onClick={() =>
void downloadBookingFile(doc.id, doc.name)
}
variant="subtle"
color="gray"
aria-label={`Download ${doc.name}`}
@@ -980,11 +967,7 @@ export default function CustomerDetailPage() {
component="button"
type="button"
onClick={() =>
view({
name: f.name,
url: fileViewUrl(f.id),
mimeType: f.mimeType,
})
void fetchViewableFile(f.id, f.name).then(view)
}
size="xs"
style={{

View File

@@ -38,6 +38,10 @@ 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 {
downloadBookingFile,
fetchViewableFile,
} from "@/services/files.service";
import { useToast } from "@/hooks/use-toast";
const fmtDate = (iso?: string | null) => {
@@ -155,10 +159,6 @@ const DriverDocuments = ({ driverId }: { driverId: string }) => {
onError: () => toast({ title: "Delete failed", variant: "destructive" }),
});
// /files/:id is a public inline-serving route; open directly for preview/download.
const fileUrl = (fileId: string, download = false) =>
`${import.meta.env.VITE_API_URL}/files/${fileId}${download ? "?download=1" : ""}`;
return (
<Card withBorder padding="lg" radius="md">
<Stack gap="md" mb="lg">
@@ -211,10 +211,22 @@ const DriverDocuments = ({ driverId }: { driverId: string }) => {
<Table.Td>{fmtDate(doc.createdAt)}</Table.Td>
<Table.Td>
<Group gap={4} justify="flex-end" wrap="nowrap">
<ActionIcon variant="subtle" aria-label="View" onClick={() => window.open(fileUrl(doc.id), "_blank")}>
<ActionIcon
variant="subtle"
aria-label="View"
onClick={() =>
void fetchViewableFile(doc.id, doc.name).then((f) =>
window.open(f.url, "_blank"),
)
}
>
<Eye size={16} />
</ActionIcon>
<ActionIcon variant="subtle" aria-label="Download" onClick={() => window.open(fileUrl(doc.id, true), "_blank")}>
<ActionIcon
variant="subtle"
aria-label="Download"
onClick={() => void downloadBookingFile(doc.id, doc.name)}
>
<Download size={16} />
</ActionIcon>
<ActionIcon

View File

@@ -92,7 +92,7 @@ export default function TrainSchedulingGlobalRulesPage() {
subtitle="Global limits applied when previewing and assigning bookings to trains."
/>
<Card maw={720}>
{/* <Card maw={720}>
<Stack gap="md">
<NumberInput
label="Max wagons per train"
@@ -107,7 +107,7 @@ export default function TrainSchedulingGlobalRulesPage() {
disabled={loading}
/>
</Stack>
</Card>
</Card> */}
<Card maw={720} mt="md">
<Stack gap="md">