@burdenoff/microfe-movethewheels 2026.1031.1 → 2026.1031.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MoveTheWheelsRoot.js +144 -136
- package/dist/MoveTheWheelsRoutes.js +61 -57
- package/dist/components/ShipmentRiskDialog.js +228 -0
- package/dist/components/TrackingAlertList.js +149 -0
- package/dist/generated/tracking-quality-operations.d.ts +1154 -2
- package/dist/generated/wspace-types.d.ts +2895 -50
- package/dist/hooks/useEntityImport.js +68 -0
- package/dist/hooks/useShipmentRisk.js +72 -0
- package/dist/hooks/useTracking.js +96 -82
- package/dist/movethewheels/components/ShipmentRiskDialog.d.ts +20 -0
- package/dist/movethewheels/components/TrackingAlertList.d.ts +14 -0
- package/dist/movethewheels/hooks/useEntityImport.d.ts +19 -0
- package/dist/movethewheels/hooks/useShipmentRisk.d.ts +41 -0
- package/dist/movethewheels/pages/ImportExportPage.d.ts +9 -0
- package/dist/movethewheels/types/index.d.ts +15 -1
- package/dist/movethewheels/utils/entityImport.d.ts +109 -0
- package/dist/movethewheels/utils/trackingAlerts.d.ts +36 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/arrow-down-up.js +22 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/file-spreadsheet.js +30 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/file-up.js +22 -0
- package/dist/pages/CustomersPage.js +88 -79
- package/dist/pages/DashboardPage.js +147 -151
- package/dist/pages/DriversPage.js +115 -106
- package/dist/pages/ImportExportPage.js +435 -0
- package/dist/pages/LiveTrackingPage.js +169 -169
- package/dist/pages/ProductsPage.js +85 -76
- package/dist/pages/VehiclesPage.js +99 -90
- package/dist/pages/WarehousesPage.js +97 -88
- package/dist/utils/entityImport.js +73 -0
- package/dist/utils/trackingAlerts.js +86 -0
- package/package.json +4 -2
- package/src/generated/tracking-quality-operations.ts +1519 -1
- package/src/generated/wspace-types.ts +3248 -51
- package/src/movethewheels/MoveTheWheelsRoot.tsx +8 -0
- package/src/movethewheels/MoveTheWheelsRoutes.tsx +4 -0
- package/src/movethewheels/components/ShipmentRiskDialog.tsx +315 -0
- package/src/movethewheels/components/TrackingAlertList.tsx +188 -0
- package/src/movethewheels/hooks/useEntityImport.ts +108 -0
- package/src/movethewheels/hooks/useShipmentRisk.ts +195 -0
- package/src/movethewheels/hooks/useTracking.ts +66 -22
- package/src/movethewheels/pages/CustomersPage.tsx +6 -1
- package/src/movethewheels/pages/DashboardPage.tsx +10 -20
- package/src/movethewheels/pages/DriversPage.tsx +6 -0
- package/src/movethewheels/pages/ImportExportPage.tsx +483 -0
- package/src/movethewheels/pages/LiveTrackingPage.tsx +20 -22
- package/src/movethewheels/pages/ProductsPage.tsx +14 -1
- package/src/movethewheels/pages/VehiclesPage.tsx +6 -0
- package/src/movethewheels/pages/WarehousesPage.tsx +6 -1
- package/src/movethewheels/types/index.ts +16 -1
- package/src/movethewheels/utils/entityImport.ts +239 -0
- package/src/movethewheels/utils/trackingAlerts.ts +151 -0
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
import { ArrowDownUp as e } from "../node_modules/lucide-react/dist/esm/icons/arrow-down-up.js";
|
|
2
|
+
import { CircleAlert as t } from "../node_modules/lucide-react/dist/esm/icons/circle-alert.js";
|
|
3
|
+
import { CircleCheckBig as n } from "../node_modules/lucide-react/dist/esm/icons/circle-check-big.js";
|
|
4
|
+
import { Download as r } from "../node_modules/lucide-react/dist/esm/icons/download.js";
|
|
5
|
+
import { FileSpreadsheet as i } from "../node_modules/lucide-react/dist/esm/icons/file-spreadsheet.js";
|
|
6
|
+
import { FileUp as a } from "../node_modules/lucide-react/dist/esm/icons/file-up.js";
|
|
7
|
+
import { Info as o } from "../node_modules/lucide-react/dist/esm/icons/info.js";
|
|
8
|
+
import { LoaderCircle as s } from "../node_modules/lucide-react/dist/esm/icons/loader-circle.js";
|
|
9
|
+
import { ShieldCheck as c } from "../node_modules/lucide-react/dist/esm/icons/shield-check.js";
|
|
10
|
+
import { Upload as l } from "../node_modules/lucide-react/dist/esm/icons/upload.js";
|
|
11
|
+
import { joinPath as u } from "../utils/navigation.js";
|
|
12
|
+
import { useMoveTheWheels as d } from "../providers/MoveTheWheelsProvider.js";
|
|
13
|
+
import { Badge as f, Button as p, Card as m, CardContent as h, CardDescription as g, CardHeader as _, CardTitle as v, Checkbox as ee, Label as y, Select as b, SelectContent as te, SelectItem as ne, SelectTrigger as re, SelectValue as ie, Skeleton as x, Table as S, TableBody as C, TableCell as w, TableHead as T, TableHeader as E, TableRow as D } from "../components/ui.js";
|
|
14
|
+
import { PageLayout as ae } from "../components/PageLayout.js";
|
|
15
|
+
import { useEntityExport as O } from "../hooks/useEntityExport.js";
|
|
16
|
+
import { ExportStatusBanner as k } from "../components/ExportStatusBanner.js";
|
|
17
|
+
import { MTW_IMPORT_ENTITIES as A, MTW_IMPORT_MAX_ROWS as oe, buildCsvTemplate as se, detectImportFormat as ce, importEntity as le, isImportEntityType as j, summariseImport as M } from "../utils/entityImport.js";
|
|
18
|
+
import { useEntityImport as ue, useImportSpec as de } from "../hooks/useEntityImport.js";
|
|
19
|
+
import { useMemo as fe, useRef as pe, useState as N } from "react";
|
|
20
|
+
import { useSearchParams as P } from "react-router";
|
|
21
|
+
import { jsx as F, jsxs as I } from "react/jsx-runtime";
|
|
22
|
+
import { EmphasisPanel as L, PagePurpose as R } from "@burdenoff/fe-libs/ui";
|
|
23
|
+
//#region src/movethewheels/pages/ImportExportPage.tsx
|
|
24
|
+
var z = {
|
|
25
|
+
CUSTOMER: "customers",
|
|
26
|
+
VEHICLE: "fleet/vehicles",
|
|
27
|
+
DRIVER: "fleet/drivers",
|
|
28
|
+
WAREHOUSE: "inventory/warehouses",
|
|
29
|
+
CARGO_ITEM: "inventory/products"
|
|
30
|
+
}, me = [
|
|
31
|
+
{
|
|
32
|
+
entity: "orders",
|
|
33
|
+
label: "Orders",
|
|
34
|
+
noun: "order"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
entity: "customers",
|
|
38
|
+
label: "Customers",
|
|
39
|
+
noun: "customer"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
entity: "vehicles",
|
|
43
|
+
label: "Vehicles",
|
|
44
|
+
noun: "vehicle"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
entity: "drivers",
|
|
48
|
+
label: "Drivers",
|
|
49
|
+
noun: "driver"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
entity: "products",
|
|
53
|
+
label: "Products",
|
|
54
|
+
noun: "product"
|
|
55
|
+
}
|
|
56
|
+
];
|
|
57
|
+
function he(e, t, n) {
|
|
58
|
+
let r = URL.createObjectURL(new Blob([t], { type: n })), i = document.createElement("a");
|
|
59
|
+
i.href = r, i.download = e, document.body.appendChild(i), i.click(), i.remove(), URL.revokeObjectURL(r);
|
|
60
|
+
}
|
|
61
|
+
function ge(e) {
|
|
62
|
+
if (e.allowedValues?.length) return e.allowedValues.join(", ");
|
|
63
|
+
let t = [e.type.toLowerCase()];
|
|
64
|
+
return e.maxLength !== null && t.push(`max ${e.maxLength} chars`), e.min !== null && e.max !== null ? t.push(`${e.min} to ${e.max}`) : e.min !== null && t.push(`at least ${e.min}`), t.join(", ");
|
|
65
|
+
}
|
|
66
|
+
function _e({ result: e, noun: r, onOpenList: i }) {
|
|
67
|
+
let a = e.status === "REJECTED" || e.dryRun && e.failedRows > 0, o = a ? "border-status-error-border bg-status-error-bg-subtle text-status-error-text" : e.status === "PARTIAL" ? "border-status-warning-border bg-status-warning-bg-subtle text-status-warning-text" : "border-status-success-border bg-status-success-bg-subtle text-status-success-text", s = a ? t : n;
|
|
68
|
+
return /* @__PURE__ */ I("div", {
|
|
69
|
+
className: "space-y-3",
|
|
70
|
+
"data-testid": "mtw-import-result",
|
|
71
|
+
"data-status": e.status,
|
|
72
|
+
children: [
|
|
73
|
+
/* @__PURE__ */ I("div", {
|
|
74
|
+
role: a ? "alert" : "status",
|
|
75
|
+
className: `flex items-start gap-2 rounded-lg border px-4 py-3 text-sm ${o}`,
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ F(s, {
|
|
78
|
+
size: 18,
|
|
79
|
+
className: "mt-0.5 shrink-0"
|
|
80
|
+
}),
|
|
81
|
+
/* @__PURE__ */ F("span", {
|
|
82
|
+
className: "flex-1",
|
|
83
|
+
children: M(e, r)
|
|
84
|
+
}),
|
|
85
|
+
e.importedRows > 0 ? /* @__PURE__ */ I("button", {
|
|
86
|
+
type: "button",
|
|
87
|
+
className: "font-medium underline underline-offset-2",
|
|
88
|
+
onClick: i,
|
|
89
|
+
children: [
|
|
90
|
+
"View ",
|
|
91
|
+
r,
|
|
92
|
+
"s"
|
|
93
|
+
]
|
|
94
|
+
}) : null
|
|
95
|
+
]
|
|
96
|
+
}),
|
|
97
|
+
/* @__PURE__ */ I("div", {
|
|
98
|
+
className: "flex flex-wrap gap-2 text-sm",
|
|
99
|
+
children: [
|
|
100
|
+
/* @__PURE__ */ I(f, {
|
|
101
|
+
variant: "outline",
|
|
102
|
+
children: ["Rows: ", e.totalRows]
|
|
103
|
+
}),
|
|
104
|
+
/* @__PURE__ */ I(f, {
|
|
105
|
+
variant: "outline",
|
|
106
|
+
children: ["Valid: ", e.validRows]
|
|
107
|
+
}),
|
|
108
|
+
/* @__PURE__ */ I(f, {
|
|
109
|
+
variant: "outline",
|
|
110
|
+
children: ["Imported: ", e.importedRows]
|
|
111
|
+
}),
|
|
112
|
+
/* @__PURE__ */ I(f, {
|
|
113
|
+
variant: e.failedRows > 0 ? "destructive" : "outline",
|
|
114
|
+
children: ["Problems: ", e.failedRows]
|
|
115
|
+
})
|
|
116
|
+
]
|
|
117
|
+
}),
|
|
118
|
+
e.errors.length > 0 ? /* @__PURE__ */ F("div", {
|
|
119
|
+
className: "max-h-80 overflow-auto rounded-lg border border-border-default",
|
|
120
|
+
children: /* @__PURE__ */ I(S, { children: [/* @__PURE__ */ F(E, { children: /* @__PURE__ */ I(D, { children: [
|
|
121
|
+
/* @__PURE__ */ F(T, {
|
|
122
|
+
className: "w-20",
|
|
123
|
+
children: "Row"
|
|
124
|
+
}),
|
|
125
|
+
/* @__PURE__ */ F(T, {
|
|
126
|
+
className: "w-40",
|
|
127
|
+
children: "Column"
|
|
128
|
+
}),
|
|
129
|
+
/* @__PURE__ */ F(T, { children: "Problem" })
|
|
130
|
+
] }) }), /* @__PURE__ */ F(C, { children: e.errors.map((e, t) => /* @__PURE__ */ I(D, { children: [
|
|
131
|
+
/* @__PURE__ */ F(w, { children: e.row }),
|
|
132
|
+
/* @__PURE__ */ F(w, {
|
|
133
|
+
className: "font-mono text-xs",
|
|
134
|
+
children: e.field ?? "—"
|
|
135
|
+
}),
|
|
136
|
+
/* @__PURE__ */ F(w, { children: e.message })
|
|
137
|
+
] }, `${e.row}-${e.field ?? ""}-${t}`)) })] })
|
|
138
|
+
}) : null,
|
|
139
|
+
e.errorsTruncated ? /* @__PURE__ */ I("p", {
|
|
140
|
+
className: "text-sm text-text-secondary",
|
|
141
|
+
children: [
|
|
142
|
+
"Only the first ",
|
|
143
|
+
e.errors.length,
|
|
144
|
+
" problems are listed. Fix these and validate again to see the rest."
|
|
145
|
+
]
|
|
146
|
+
}) : null
|
|
147
|
+
]
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function ve({ entity: e, label: t, noun: n }) {
|
|
151
|
+
let { state: i, isExporting: a, startExport: o, dismiss: c } = O(e, n);
|
|
152
|
+
return /* @__PURE__ */ I("div", {
|
|
153
|
+
className: "space-y-2 rounded-lg border border-border-default p-4",
|
|
154
|
+
children: [/* @__PURE__ */ I("div", {
|
|
155
|
+
className: "flex items-center justify-between gap-3",
|
|
156
|
+
children: [/* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("p", {
|
|
157
|
+
className: "font-medium text-text-primary",
|
|
158
|
+
children: t
|
|
159
|
+
}), /* @__PURE__ */ I("p", {
|
|
160
|
+
className: "text-sm text-text-secondary",
|
|
161
|
+
children: [
|
|
162
|
+
"Every ",
|
|
163
|
+
n,
|
|
164
|
+
" in this workspace, as CSV"
|
|
165
|
+
]
|
|
166
|
+
})] }), /* @__PURE__ */ I(p, {
|
|
167
|
+
variant: "outline",
|
|
168
|
+
size: "sm",
|
|
169
|
+
disabled: a,
|
|
170
|
+
"aria-label": `Export ${t}`,
|
|
171
|
+
onClick: o,
|
|
172
|
+
children: [a ? /* @__PURE__ */ F(s, {
|
|
173
|
+
size: 14,
|
|
174
|
+
className: "animate-spin"
|
|
175
|
+
}) : /* @__PURE__ */ F(r, { size: 14 }), /* @__PURE__ */ F("span", {
|
|
176
|
+
className: "ml-1",
|
|
177
|
+
children: a ? "Exporting…" : "Export"
|
|
178
|
+
})]
|
|
179
|
+
})]
|
|
180
|
+
}), /* @__PURE__ */ F(k, {
|
|
181
|
+
state: i,
|
|
182
|
+
onDismiss: c
|
|
183
|
+
})]
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
function B() {
|
|
187
|
+
let { basePath: n, navigate: S } = d(), { specs: C, isLoading: w, error: T } = de(), { run: E, isRunning: D } = ue(), [O] = P(), [k, M] = N(() => {
|
|
188
|
+
let e = O.get("entity");
|
|
189
|
+
return j(e) ? e : "CUSTOMER";
|
|
190
|
+
}), [B, V] = N(null), [H, ye] = N(!1), [U, W] = N(null), [G, K] = N(null), [q, J] = N(null), Y = pe(null), X = le(k), Z = fe(() => C.find((e) => e.entityType === k) ?? null, [C, k]), Q = () => {
|
|
191
|
+
W(null), K(null), J(null);
|
|
192
|
+
}, be = (e) => {
|
|
193
|
+
j(e) && (M(e), V(null), Q());
|
|
194
|
+
}, xe = async (e) => {
|
|
195
|
+
let t = e.target.files?.[0];
|
|
196
|
+
if (e.target.value = "", Q(), !t) return;
|
|
197
|
+
let n = ce(t.name, t.type);
|
|
198
|
+
if (!n) {
|
|
199
|
+
V(null), K("Choose a .csv or .json file.");
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
V({
|
|
203
|
+
name: t.name,
|
|
204
|
+
format: n,
|
|
205
|
+
content: await t.text()
|
|
206
|
+
});
|
|
207
|
+
}, $ = async (e) => {
|
|
208
|
+
if (B) {
|
|
209
|
+
K(null), J(e ? "validate" : "import");
|
|
210
|
+
try {
|
|
211
|
+
W(await E({
|
|
212
|
+
entityType: k,
|
|
213
|
+
format: B.format,
|
|
214
|
+
content: B.content,
|
|
215
|
+
dryRun: e,
|
|
216
|
+
allowPartial: H
|
|
217
|
+
}));
|
|
218
|
+
} catch (e) {
|
|
219
|
+
W(null), K(e instanceof Error ? e.message : "The import could not be completed.");
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}, Se = () => {
|
|
223
|
+
Z && he(`${X.label.toLowerCase()}-import-template.csv`, se(Z), "text/csv");
|
|
224
|
+
}, Ce = B !== null && !D && U?.status !== "COMPLETED";
|
|
225
|
+
return /* @__PURE__ */ I(ae, {
|
|
226
|
+
title: "Import / Export",
|
|
227
|
+
subtitle: "Bring master data in from a file, or take a full copy out",
|
|
228
|
+
icon: /* @__PURE__ */ F(e, { size: 24 }),
|
|
229
|
+
children: [
|
|
230
|
+
/* @__PURE__ */ F(R, {
|
|
231
|
+
icon: /* @__PURE__ */ F(e, { size: 18 }),
|
|
232
|
+
children: "Onboard or migrate without re-keying: import customers, vehicles, drivers, warehouses or products from CSV or JSON. Every row is checked before anything is saved, so you can fix a file and try again. Export any dataset for accounting, BI tools or backups."
|
|
233
|
+
}),
|
|
234
|
+
/* @__PURE__ */ F("input", {
|
|
235
|
+
ref: Y,
|
|
236
|
+
type: "file",
|
|
237
|
+
accept: ".csv,.json,text/csv,application/json",
|
|
238
|
+
className: "hidden",
|
|
239
|
+
"data-testid": "mtw-import-file",
|
|
240
|
+
onChange: (e) => void xe(e)
|
|
241
|
+
}),
|
|
242
|
+
/* @__PURE__ */ I("div", {
|
|
243
|
+
className: "grid grid-cols-1 gap-6 xl:grid-cols-3",
|
|
244
|
+
children: [/* @__PURE__ */ I(L, {
|
|
245
|
+
className: "space-y-5 xl:col-span-2",
|
|
246
|
+
children: [
|
|
247
|
+
/* @__PURE__ */ I("div", {
|
|
248
|
+
className: "flex flex-wrap items-center justify-between gap-3",
|
|
249
|
+
children: [/* @__PURE__ */ I("h2", {
|
|
250
|
+
className: "flex items-center gap-2 text-base font-semibold text-text-primary",
|
|
251
|
+
children: [/* @__PURE__ */ F(l, { size: 18 }), " Import data"]
|
|
252
|
+
}), /* @__PURE__ */ I(f, {
|
|
253
|
+
variant: "outline",
|
|
254
|
+
children: [
|
|
255
|
+
"CSV or JSON · up to ",
|
|
256
|
+
oe,
|
|
257
|
+
" rows · 2 MB"
|
|
258
|
+
]
|
|
259
|
+
})]
|
|
260
|
+
}),
|
|
261
|
+
/* @__PURE__ */ I("div", {
|
|
262
|
+
className: "grid grid-cols-1 gap-4 md:grid-cols-2",
|
|
263
|
+
children: [/* @__PURE__ */ I("div", {
|
|
264
|
+
className: "space-y-2",
|
|
265
|
+
children: [/* @__PURE__ */ F(y, {
|
|
266
|
+
htmlFor: "mtw-import-entity",
|
|
267
|
+
children: "What are you importing?"
|
|
268
|
+
}), /* @__PURE__ */ I(b, {
|
|
269
|
+
value: k,
|
|
270
|
+
onValueChange: be,
|
|
271
|
+
children: [/* @__PURE__ */ F(re, {
|
|
272
|
+
id: "mtw-import-entity",
|
|
273
|
+
"aria-label": "Import type",
|
|
274
|
+
children: /* @__PURE__ */ F(ie, {})
|
|
275
|
+
}), /* @__PURE__ */ F(te, { children: A.map((e) => /* @__PURE__ */ F(ne, {
|
|
276
|
+
value: e.entityType,
|
|
277
|
+
children: e.label
|
|
278
|
+
}, e.entityType)) })]
|
|
279
|
+
})]
|
|
280
|
+
}), /* @__PURE__ */ I("div", {
|
|
281
|
+
className: "space-y-2",
|
|
282
|
+
children: [
|
|
283
|
+
/* @__PURE__ */ F(y, { children: "File" }),
|
|
284
|
+
/* @__PURE__ */ I("div", {
|
|
285
|
+
className: "flex flex-wrap items-center gap-2",
|
|
286
|
+
children: [/* @__PURE__ */ I(p, {
|
|
287
|
+
variant: "outline",
|
|
288
|
+
onClick: () => Y.current?.click(),
|
|
289
|
+
children: [/* @__PURE__ */ F(a, { size: 16 }), /* @__PURE__ */ F("span", {
|
|
290
|
+
className: "ml-1",
|
|
291
|
+
children: B ? "Choose another file" : "Choose file"
|
|
292
|
+
})]
|
|
293
|
+
}), /* @__PURE__ */ I(p, {
|
|
294
|
+
variant: "ghost",
|
|
295
|
+
disabled: !Z,
|
|
296
|
+
onClick: Se,
|
|
297
|
+
"aria-label": `Download ${X.label} CSV template`,
|
|
298
|
+
children: [/* @__PURE__ */ F(i, { size: 16 }), /* @__PURE__ */ F("span", {
|
|
299
|
+
className: "ml-1",
|
|
300
|
+
children: "Template"
|
|
301
|
+
})]
|
|
302
|
+
})]
|
|
303
|
+
}),
|
|
304
|
+
B ? /* @__PURE__ */ I("p", {
|
|
305
|
+
className: "text-sm text-text-secondary",
|
|
306
|
+
"data-testid": "mtw-import-file-name",
|
|
307
|
+
children: [
|
|
308
|
+
B.name,
|
|
309
|
+
" (",
|
|
310
|
+
B.format,
|
|
311
|
+
")"
|
|
312
|
+
]
|
|
313
|
+
}) : null
|
|
314
|
+
]
|
|
315
|
+
})]
|
|
316
|
+
}),
|
|
317
|
+
/* @__PURE__ */ I("div", {
|
|
318
|
+
className: "flex items-start gap-2",
|
|
319
|
+
children: [/* @__PURE__ */ F(ee, {
|
|
320
|
+
id: "mtw-import-partial",
|
|
321
|
+
checked: H,
|
|
322
|
+
onCheckedChange: (e) => {
|
|
323
|
+
ye(e === !0), U && !U.dryRun && Q();
|
|
324
|
+
}
|
|
325
|
+
}), /* @__PURE__ */ F(y, {
|
|
326
|
+
htmlFor: "mtw-import-partial",
|
|
327
|
+
className: "text-sm font-normal leading-snug",
|
|
328
|
+
children: "Import the valid rows even if some rows have problems. When this is off, a file with any problem imports nothing."
|
|
329
|
+
})]
|
|
330
|
+
}),
|
|
331
|
+
/* @__PURE__ */ I("div", {
|
|
332
|
+
className: "flex flex-wrap gap-2",
|
|
333
|
+
children: [/* @__PURE__ */ I(p, {
|
|
334
|
+
variant: "outline",
|
|
335
|
+
disabled: !B || D,
|
|
336
|
+
onClick: () => void $(!0),
|
|
337
|
+
children: [D && q === "validate" ? /* @__PURE__ */ F(s, {
|
|
338
|
+
size: 16,
|
|
339
|
+
className: "animate-spin"
|
|
340
|
+
}) : /* @__PURE__ */ F(c, { size: 16 }), /* @__PURE__ */ F("span", {
|
|
341
|
+
className: "ml-1",
|
|
342
|
+
children: "Validate"
|
|
343
|
+
})]
|
|
344
|
+
}), /* @__PURE__ */ I(p, {
|
|
345
|
+
disabled: !Ce,
|
|
346
|
+
onClick: () => void $(!1),
|
|
347
|
+
children: [D && q === "import" ? /* @__PURE__ */ F(s, {
|
|
348
|
+
size: 16,
|
|
349
|
+
className: "animate-spin"
|
|
350
|
+
}) : /* @__PURE__ */ F(l, { size: 16 }), /* @__PURE__ */ I("span", {
|
|
351
|
+
className: "ml-1",
|
|
352
|
+
children: ["Import ", X.label.toLowerCase()]
|
|
353
|
+
})]
|
|
354
|
+
})]
|
|
355
|
+
}),
|
|
356
|
+
G ? /* @__PURE__ */ I("div", {
|
|
357
|
+
role: "alert",
|
|
358
|
+
"data-testid": "mtw-import-error",
|
|
359
|
+
className: "flex items-start gap-2 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-4 py-3 text-sm text-status-error-text",
|
|
360
|
+
children: [/* @__PURE__ */ F(t, {
|
|
361
|
+
size: 18,
|
|
362
|
+
className: "mt-0.5 shrink-0"
|
|
363
|
+
}), /* @__PURE__ */ F("span", { children: G })]
|
|
364
|
+
}) : null,
|
|
365
|
+
U ? /* @__PURE__ */ F(_e, {
|
|
366
|
+
result: U,
|
|
367
|
+
noun: X.noun,
|
|
368
|
+
onOpenList: () => S?.(u(n, z[k]))
|
|
369
|
+
}) : null
|
|
370
|
+
]
|
|
371
|
+
}), /* @__PURE__ */ I(m, { children: [/* @__PURE__ */ I(_, { children: [/* @__PURE__ */ I(v, {
|
|
372
|
+
className: "flex items-center gap-2 text-base",
|
|
373
|
+
children: [
|
|
374
|
+
/* @__PURE__ */ F(o, { size: 18 }),
|
|
375
|
+
" ",
|
|
376
|
+
X.label,
|
|
377
|
+
" columns"
|
|
378
|
+
]
|
|
379
|
+
}), /* @__PURE__ */ F(g, { children: "Use these column names as the CSV header or JSON keys. Values are not case-sensitive for lists." })] }), /* @__PURE__ */ F(h, { children: w ? /* @__PURE__ */ I("div", {
|
|
380
|
+
className: "space-y-2",
|
|
381
|
+
children: [
|
|
382
|
+
/* @__PURE__ */ F(x, { className: "h-6 w-full" }),
|
|
383
|
+
/* @__PURE__ */ F(x, { className: "h-6 w-full" }),
|
|
384
|
+
/* @__PURE__ */ F(x, { className: "h-6 w-2/3" })
|
|
385
|
+
]
|
|
386
|
+
}) : T ? /* @__PURE__ */ F("p", {
|
|
387
|
+
className: "text-sm text-status-error-text",
|
|
388
|
+
children: "The column guide could not be loaded. Imports still work."
|
|
389
|
+
}) : Z ? /* @__PURE__ */ F("ul", {
|
|
390
|
+
className: "space-y-3",
|
|
391
|
+
"data-testid": "mtw-import-columns",
|
|
392
|
+
children: Z.columns.map((e) => /* @__PURE__ */ I("li", {
|
|
393
|
+
className: "text-sm",
|
|
394
|
+
children: [
|
|
395
|
+
/* @__PURE__ */ I("div", {
|
|
396
|
+
className: "flex flex-wrap items-center gap-2",
|
|
397
|
+
children: [
|
|
398
|
+
/* @__PURE__ */ F("code", {
|
|
399
|
+
className: "font-mono text-text-primary",
|
|
400
|
+
children: e.name
|
|
401
|
+
}),
|
|
402
|
+
e.required ? /* @__PURE__ */ F(f, {
|
|
403
|
+
variant: "default",
|
|
404
|
+
children: "required"
|
|
405
|
+
}) : null,
|
|
406
|
+
Z.keyColumn === e.name ? /* @__PURE__ */ F(f, {
|
|
407
|
+
variant: "outline",
|
|
408
|
+
children: "unique"
|
|
409
|
+
}) : null
|
|
410
|
+
]
|
|
411
|
+
}),
|
|
412
|
+
/* @__PURE__ */ F("p", {
|
|
413
|
+
className: "text-text-secondary",
|
|
414
|
+
children: e.description
|
|
415
|
+
}),
|
|
416
|
+
/* @__PURE__ */ F("p", {
|
|
417
|
+
className: "text-xs text-text-tertiary",
|
|
418
|
+
children: ge(e)
|
|
419
|
+
})
|
|
420
|
+
]
|
|
421
|
+
}, e.name))
|
|
422
|
+
}) : null })] })]
|
|
423
|
+
}),
|
|
424
|
+
/* @__PURE__ */ I(m, { children: [/* @__PURE__ */ I(_, { children: [/* @__PURE__ */ I(v, {
|
|
425
|
+
className: "flex items-center gap-2 text-base",
|
|
426
|
+
children: [/* @__PURE__ */ F(r, { size: 18 }), " Export data"]
|
|
427
|
+
}), /* @__PURE__ */ F(g, { children: "Exports run in the background and download as a ZIP. Large exports stay available on the Exports page." })] }), /* @__PURE__ */ F(h, {
|
|
428
|
+
className: "grid grid-cols-1 gap-3 md:grid-cols-2",
|
|
429
|
+
children: me.map((e) => /* @__PURE__ */ F(ve, { ...e }, e.entity))
|
|
430
|
+
})] })
|
|
431
|
+
]
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
//#endregion
|
|
435
|
+
export { B as default };
|