Files
edr-platform/apps/edr-freight-web/backoffice/src/components/warehouses/options.ts
Hagernesh c86118cd8d feat(warehouse): add warehouse management module (batch 1)
Backend (edr-freight-api):
- Warehouse, WarehouseYard, WarehouseZone, WarehouseInventory entities
- CRUD for warehouses/yards/zones with scoped code uniqueness
- Inventory receive with location-hierarchy + capacity validation and
  transactional capacity-counter updates
- inspect / ready-for-loading status transitions
- inventory inquiry (booking/customer/container/cargo-type joins)
- migration creating freight.warehouse* tables

Frontend (freight backoffice):
- types, service, react-query hooks, URL constants
- reusable components: badges, filters, table/card views, inventory and
  inquiry tables, create/receive modals
- pages: Warehouse list, detail (overview/yards/zones/inventory tabs),
  inventory, inventory inquiry
- Warehouse Information card + Receive At Warehouse on booking detail
- routes + sidebar nav; app-wide ErrorBoundary

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 15:54:56 +00:00

57 lines
2.0 KiB
TypeScript

import {
WAREHOUSE_TYPES,
WAREHOUSE_YARD_TYPES,
WAREHOUSE_ZONE_TYPES,
WAREHOUSE_STATUSES,
INVENTORY_STATUSES,
} from '@/types/warehouse';
export const humanizeEnum = (value: string) =>
value
.toLowerCase()
.split('_')
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
.join(' ');
const toOptions = (values: readonly string[]) =>
values.map((value) => ({ value, label: humanizeEnum(value) }));
export const warehouseTypeOptions = toOptions(WAREHOUSE_TYPES);
export const yardTypeOptions = toOptions(WAREHOUSE_YARD_TYPES);
export const zoneTypeOptions = toOptions(WAREHOUSE_ZONE_TYPES);
export const statusOptions = toOptions(WAREHOUSE_STATUSES);
export const inventoryStatusOptions = toOptions(INVENTORY_STATUSES);
export const formatNumber = (value: number | null | undefined) => {
if (value === null || value === undefined) return '—';
const num = Number(value);
if (Number.isNaN(num)) return '—';
return num.toLocaleString(undefined, { maximumFractionDigits: 3 });
};
export const formatCapacity = (current: number, capacity: number | null | undefined) => {
const cur = formatNumber(current);
if (capacity === null || capacity === undefined) return cur;
return `${cur} / ${formatNumber(capacity)}`;
};
export const formatDate = (value: string | null | undefined) => {
if (!value) return '—';
const date = new Date(value);
if (Number.isNaN(date.getTime())) return '—';
return date.toLocaleString(undefined, {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
});
};
export const extractErrorMessage = (error: unknown, fallback = 'Something went wrong') => {
const responseData = (error as { response?: { data?: unknown } })?.response?.data;
const data = responseData && typeof responseData === 'object' ? (responseData as Record<string, unknown>) : undefined;
const rawMessage = data?.message ?? data?.error ?? (error as Error)?.message;
return Array.isArray(rawMessage) ? rawMessage.join(', ') : rawMessage ? String(rawMessage) : fallback;
};