expose per-side facility flags

This commit is contained in:
Marshal
2026-08-03 08:20:18 +00:00
parent f4fd469643
commit dfd27efb6b
7 changed files with 225 additions and 25 deletions

View File

@@ -2,8 +2,10 @@ import { useMemo, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import toast from "react-hot-toast";
import { useAuth } from "@/auth/useAuth";
import { useEmployees } from "@/user-management/hooks/useEmployees";
import {
useAllExternalUsers,
userTypeEnum,
} from "@/super-admin/hooks/useExternalUsers";
import {
ALL_TRADE_DIRECTIONS,
TRADE_DIRECTION_LABELS,
@@ -34,17 +36,12 @@ type EmployeeRow = {
* and overview to the checked directions. Admins always bypass the scope.
*/
export default function TradeAccessPage() {
const { user } = useAuth();
const queryClient = useQueryClient();
const [search, setSearch] = useState("");
const organizationId =
user?.employee && user.employee.length > 0
? user.employee[0].organizationId
: undefined;
const { employeesResponseByOrg, isLoadingEmployeesByOrg } = useEmployees({
organizationId,
const { data: usersResponse, isLoading: usersLoading } = useAllExternalUsers({
userType: userTypeEnum.employee,
take: 3000,
});
const { data: configs, isLoading: configsLoading } = useQuery({
@@ -76,12 +73,12 @@ export default function TradeAccessPage() {
}, [configs]);
const rows: EmployeeRow[] = useMemo(() => {
const items = employeesResponseByOrg?.items ?? [];
const items = usersResponse?.items ?? [];
const mapped = items
.map((item: { user?: { id?: string; name?: { en?: string }; email?: string; username?: string } }) => ({
userId: item.user?.id ?? "",
name: item.user?.name?.en ?? item.user?.username ?? "—",
email: item.user?.email ?? "",
.map((u) => ({
userId: u.id ?? "",
name: u.name?.en ?? u.username ?? "—",
email: u.email ?? "",
}))
.filter((r: EmployeeRow) => r.userId);
const term = search.trim().toLowerCase();
@@ -91,7 +88,7 @@ export default function TradeAccessPage() {
r.name.toLowerCase().includes(term) ||
r.email.toLowerCase().includes(term),
);
}, [employeesResponseByOrg, search]);
}, [usersResponse, search]);
// No row yet = unrestricted, so render as all three checked.
const directionsFor = (userId: string): TradeDirection[] =>
@@ -105,7 +102,7 @@ export default function TradeAccessPage() {
saveMutation.mutate({ userId, directions: next });
};
const loading = isLoadingEmployeesByOrg || configsLoading;
const loading = usersLoading || configsLoading;
return (
<div className="space-y-4 p-4">

View File

@@ -691,6 +691,30 @@ export const RULE_ENGINE_RESOURCES: RuleEngineResourceConfig[] = [
accessorKey: "hasFacility",
format: "boolean",
},
{
id: "hasContainerFacilityOrigin",
header: "Container origin",
accessorKey: "hasContainerFacilityOrigin",
format: "boolean",
},
{
id: "hasContainerFacilityDestination",
header: "Container dest.",
accessorKey: "hasContainerFacilityDestination",
format: "boolean",
},
{
id: "hasBulkFacilityOrigin",
header: "Bulk origin",
accessorKey: "hasBulkFacilityOrigin",
format: "boolean",
},
{
id: "hasBulkFacilityDestination",
header: "Bulk dest.",
accessorKey: "hasBulkFacilityDestination",
format: "boolean",
},
{ id: "displayOrder", header: "Order", accessorKey: "displayOrder", format: "number" },
activeColumn,
],
@@ -710,6 +734,34 @@ export const RULE_ENGINE_RESOURCES: RuleEngineResourceConfig[] = [
description:
"This yard can load and unload cargo. Intercity bookings can only be loaded at their origin and unloaded at their destination when it is a facility.",
},
{
name: "hasContainerFacilityOrigin",
label: "Container facility — origin",
type: "boolean",
description: "Can load containers onto a train. Offered as a contract origin for container freight.",
showIf: (values) => Boolean(values.hasFacility),
},
{
name: "hasContainerFacilityDestination",
label: "Container facility — destination",
type: "boolean",
description: "Can receive containers off a train. Offered as a contract destination for container freight.",
showIf: (values) => Boolean(values.hasFacility),
},
{
name: "hasBulkFacilityOrigin",
label: "Bulk facility — origin",
type: "boolean",
description: "Can load bulk cargo onto a train. Offered as a contract origin for bulk freight.",
showIf: (values) => Boolean(values.hasFacility),
},
{
name: "hasBulkFacilityDestination",
label: "Bulk facility — destination",
type: "boolean",
description: "Can receive bulk cargo off a train. Offered as a contract destination for bulk freight.",
showIf: (values) => Boolean(values.hasFacility),
},
{ name: "isActive", label: "Active", type: "boolean" },
],
},

View File

@@ -19,6 +19,7 @@ export enum userTypeEnum {
external = "external_organization",
individual = "individual",
externalUsers = "external_organization,individual",
employee = "employee",
}
export interface ExternalQueryParams {