mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 02:58:11 +00:00
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>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import { Component, type ErrorInfo, type ReactNode } from "react";
|
||||
|
||||
interface ErrorBoundaryProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
interface ErrorBoundaryState {
|
||||
error: Error | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* App-wide error boundary. Without this, any render-time exception unmounts the
|
||||
* React tree and the user sees a blank white screen. This surfaces the actual
|
||||
* error message + stack so failures are diagnosable in place.
|
||||
*/
|
||||
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
state: ErrorBoundaryState = { error: null };
|
||||
|
||||
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
|
||||
return { error };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, info: ErrorInfo) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("[ErrorBoundary] Uncaught render error:", error, info.componentStack);
|
||||
}
|
||||
|
||||
handleReset = () => this.setState({ error: null });
|
||||
|
||||
render() {
|
||||
const { error } = this.state;
|
||||
|
||||
if (!error) return this.props.children;
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
minHeight: "100vh",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: 24,
|
||||
background: "#f8fafc",
|
||||
fontFamily: "system-ui, sans-serif",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
maxWidth: 720,
|
||||
width: "100%",
|
||||
background: "#fff",
|
||||
border: "1px solid #fecaca",
|
||||
borderRadius: 12,
|
||||
padding: 24,
|
||||
boxShadow: "0 1px 3px rgba(0,0,0,0.08)",
|
||||
}}
|
||||
>
|
||||
<h2 style={{ margin: 0, color: "#b91c1c", fontSize: 18 }}>Something went wrong</h2>
|
||||
<p style={{ color: "#64748b", fontSize: 14 }}>
|
||||
A render error was caught. Details below — share this with the developer.
|
||||
</p>
|
||||
<pre
|
||||
style={{
|
||||
whiteSpace: "pre-wrap",
|
||||
wordBreak: "break-word",
|
||||
background: "#0f172a",
|
||||
color: "#fca5a5",
|
||||
padding: 16,
|
||||
borderRadius: 8,
|
||||
fontSize: 12,
|
||||
maxHeight: 320,
|
||||
overflow: "auto",
|
||||
}}
|
||||
>
|
||||
{error.message}
|
||||
{"\n\n"}
|
||||
{error.stack}
|
||||
</pre>
|
||||
<button
|
||||
type="button"
|
||||
onClick={this.handleReset}
|
||||
style={{
|
||||
marginTop: 12,
|
||||
padding: "8px 16px",
|
||||
border: "none",
|
||||
borderRadius: 8,
|
||||
background: "#0f766e",
|
||||
color: "#fff",
|
||||
cursor: "pointer",
|
||||
fontSize: 14,
|
||||
}}
|
||||
>
|
||||
Dismiss
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user