@burdenoff/microfe-assethandler 2026.703.6 → 2026.703.7
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/assethandler/ops/NewWorkOrderDialog.js +164 -0
- package/dist/assethandler/ops/NewWorkOrderDialog.js.map +1 -0
- package/dist/assethandler/ops/ScheduleMaintenanceDialog.js +197 -0
- package/dist/assethandler/ops/ScheduleMaintenanceDialog.js.map +1 -0
- package/dist/assethandler/pages/AiPredictionsPage.js +112 -54
- package/dist/assethandler/pages/AiPredictionsPage.js.map +1 -1
- package/dist/assethandler/pages/CmdbBrowserPage.js +195 -36
- package/dist/assethandler/pages/CmdbBrowserPage.js.map +1 -1
- package/dist/assethandler/pages/DigitalTwinPage.js +162 -31
- package/dist/assethandler/pages/DigitalTwinPage.js.map +1 -1
- package/dist/assethandler/pages/DiscoveryJobsPage.js +85 -55
- package/dist/assethandler/pages/DiscoveryJobsPage.js.map +1 -1
- package/dist/assethandler/pages/EsgDashboardPage.js +189 -60
- package/dist/assethandler/pages/EsgDashboardPage.js.map +1 -1
- package/dist/assethandler/pages/IotDevicesPage.js +206 -38
- package/dist/assethandler/pages/IotDevicesPage.js.map +1 -1
- package/dist/assethandler/pages/ItilChangeDetailPage.js +221 -114
- package/dist/assethandler/pages/ItilChangeDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilChangeManagementPage.js +86 -61
- package/dist/assethandler/pages/ItilChangeManagementPage.js.map +1 -1
- package/dist/assethandler/pages/ItilDialogs.js +361 -0
- package/dist/assethandler/pages/ItilDialogs.js.map +1 -0
- package/dist/assethandler/pages/ItilIncidentDetailPage.js +370 -105
- package/dist/assethandler/pages/ItilIncidentDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilIncidentManagementPage.js +130 -103
- package/dist/assethandler/pages/ItilIncidentManagementPage.js.map +1 -1
- package/dist/assethandler/pages/ItilItilhubPage.js +186 -132
- package/dist/assethandler/pages/ItilItilhubPage.js.map +1 -1
- package/dist/assethandler/pages/ItilProblemDetailPage.js +195 -96
- package/dist/assethandler/pages/ItilProblemDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilProblemManagementPage.js +83 -58
- package/dist/assethandler/pages/ItilProblemManagementPage.js.map +1 -1
- package/dist/assethandler/pages/KnowledgeBasePage.js +205 -75
- package/dist/assethandler/pages/KnowledgeBasePage.js.map +1 -1
- package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js +212 -96
- package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js.map +1 -1
- package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js +70 -38
- package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js +470 -116
- package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsOperationsHubPage.js +154 -102
- package/dist/assethandler/pages/OperationsOperationsHubPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js +386 -79
- package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ProvenancePage.js +102 -56
- package/dist/assethandler/pages/ProvenancePage.js.map +1 -1
- package/dist/assethandler/pages/SamLicensesPage.js +186 -36
- package/dist/assethandler/pages/SamLicensesPage.js.map +1 -1
- package/dist/assethandler/pages/SecurityComplianceDetailPage.js +147 -65
- package/dist/assethandler/pages/SecurityComplianceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecurityPolicyDetailPage.js +349 -124
- package/dist/assethandler/pages/SecurityPolicyDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js +191 -116
- package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecuritySecurityHubPage.js +421 -184
- package/dist/assethandler/pages/SecuritySecurityHubPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { useAssetHandlerStore as e } from "../store/assethandlerStore.js";
|
|
2
|
+
import { notify as t } from "../utils/toast.js";
|
|
3
|
+
import { useState as n } from "react";
|
|
4
|
+
import { Loader2 as r } from "lucide-react";
|
|
5
|
+
import { gql as i } from "@apollo/client";
|
|
6
|
+
import { useMutation as a } from "@apollo/client/react";
|
|
7
|
+
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
8
|
+
import { Button as c, Input as l, Label as u, ResponsiveDialog as d, ResponsiveDialogContent as f, ResponsiveDialogDescription as p, ResponsiveDialogFooter as m, ResponsiveDialogHeader as h, ResponsiveDialogTitle as g, Select as _, SelectContent as v, SelectItem as y, SelectTrigger as b, SelectValue as x, Textarea as S } from "@burdenoff/fe-libs/ui";
|
|
9
|
+
//#region src/assethandler/ops/NewWorkOrderDialog.tsx
|
|
10
|
+
var C = i`
|
|
11
|
+
mutation AssetHandlerCreateWorkOrder($input: CreateWorkOrderInput!) {
|
|
12
|
+
createWorkOrder(input: $input) {
|
|
13
|
+
id
|
|
14
|
+
title
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
`, w = [
|
|
18
|
+
"CORRECTIVE",
|
|
19
|
+
"PREVENTIVE",
|
|
20
|
+
"PREDICTIVE",
|
|
21
|
+
"EMERGENCY"
|
|
22
|
+
], T = [
|
|
23
|
+
"DRAFT",
|
|
24
|
+
"SCHEDULED",
|
|
25
|
+
"APPROVED",
|
|
26
|
+
"IN_PROGRESS",
|
|
27
|
+
"COMPLETED",
|
|
28
|
+
"CANCELLED"
|
|
29
|
+
], E = [
|
|
30
|
+
"CRITICAL",
|
|
31
|
+
"HIGH",
|
|
32
|
+
"MEDIUM",
|
|
33
|
+
"LOW"
|
|
34
|
+
], D = (e) => e.toLowerCase().replace(/_/g, " ").replace(/^\w/, (e) => e.toUpperCase());
|
|
35
|
+
function O({ open: i, onOpenChange: O }) {
|
|
36
|
+
let { assets: k } = e(), [A, j] = n(""), [M, N] = n(""), [P, F] = n(""), [I, L] = n(""), [R, z] = n("CORRECTIVE"), [B, V] = n("MEDIUM"), [H, U] = n("DRAFT"), W = () => {
|
|
37
|
+
j(""), N(""), F(""), L(""), z("CORRECTIVE"), V("MEDIUM"), U("DRAFT");
|
|
38
|
+
}, [G, { loading: K }] = a(C, {
|
|
39
|
+
refetchQueries: ["AssetHandlerBootstrap"],
|
|
40
|
+
onCompleted: (e) => {
|
|
41
|
+
t.success("Work order created", `${e.createWorkOrder.title} was raised.`), W(), O(!1);
|
|
42
|
+
},
|
|
43
|
+
onError: (e) => t.error("Could not create work order", e.message)
|
|
44
|
+
});
|
|
45
|
+
return /* @__PURE__ */ o(d, {
|
|
46
|
+
open: i,
|
|
47
|
+
onOpenChange: O,
|
|
48
|
+
children: /* @__PURE__ */ s(f, {
|
|
49
|
+
className: "max-h-[85vh] overflow-y-auto sm:max-w-xl",
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ s(h, { children: [/* @__PURE__ */ o(g, { children: "New Work Order" }), /* @__PURE__ */ o(p, { children: "Raise a work order when an asset needs repair, inspection or attention." })] }),
|
|
52
|
+
/* @__PURE__ */ s("div", {
|
|
53
|
+
className: "space-y-4",
|
|
54
|
+
children: [
|
|
55
|
+
/* @__PURE__ */ s("div", {
|
|
56
|
+
className: "space-y-2",
|
|
57
|
+
children: [/* @__PURE__ */ o(u, { children: "Title *" }), /* @__PURE__ */ o(l, {
|
|
58
|
+
placeholder: "e.g., Replace worn drive belt",
|
|
59
|
+
value: A,
|
|
60
|
+
onChange: (e) => j(e.target.value)
|
|
61
|
+
})]
|
|
62
|
+
}),
|
|
63
|
+
/* @__PURE__ */ s("div", {
|
|
64
|
+
className: "space-y-2",
|
|
65
|
+
children: [/* @__PURE__ */ o(u, { children: "Description" }), /* @__PURE__ */ o(S, {
|
|
66
|
+
placeholder: "Describe the work required",
|
|
67
|
+
value: M,
|
|
68
|
+
onChange: (e) => N(e.target.value),
|
|
69
|
+
rows: 2
|
|
70
|
+
})]
|
|
71
|
+
}),
|
|
72
|
+
/* @__PURE__ */ s("div", {
|
|
73
|
+
className: "grid gap-4 md:grid-cols-2",
|
|
74
|
+
children: [/* @__PURE__ */ s("div", {
|
|
75
|
+
className: "space-y-2",
|
|
76
|
+
children: [/* @__PURE__ */ o(u, { children: "Asset" }), /* @__PURE__ */ s(_, {
|
|
77
|
+
value: P,
|
|
78
|
+
onValueChange: F,
|
|
79
|
+
children: [/* @__PURE__ */ o(b, { children: /* @__PURE__ */ o(x, { placeholder: "Unassigned" }) }), /* @__PURE__ */ o(v, { children: k.map((e) => /* @__PURE__ */ s(y, {
|
|
80
|
+
value: e.id,
|
|
81
|
+
children: [e.name, e.assetTag ? ` · ${e.assetTag}` : ""]
|
|
82
|
+
}, e.id)) })]
|
|
83
|
+
})]
|
|
84
|
+
}), /* @__PURE__ */ s("div", {
|
|
85
|
+
className: "space-y-2",
|
|
86
|
+
children: [/* @__PURE__ */ o(u, { children: "Assigned To" }), /* @__PURE__ */ o(l, {
|
|
87
|
+
placeholder: "e.g., Facilities team",
|
|
88
|
+
value: I,
|
|
89
|
+
onChange: (e) => L(e.target.value)
|
|
90
|
+
})]
|
|
91
|
+
})]
|
|
92
|
+
}),
|
|
93
|
+
/* @__PURE__ */ s("div", {
|
|
94
|
+
className: "grid gap-4 md:grid-cols-3",
|
|
95
|
+
children: [
|
|
96
|
+
/* @__PURE__ */ s("div", {
|
|
97
|
+
className: "space-y-2",
|
|
98
|
+
children: [/* @__PURE__ */ o(u, { children: "Type" }), /* @__PURE__ */ s(_, {
|
|
99
|
+
value: R,
|
|
100
|
+
onValueChange: (e) => z(e),
|
|
101
|
+
children: [/* @__PURE__ */ o(b, { children: /* @__PURE__ */ o(x, {}) }), /* @__PURE__ */ o(v, { children: w.map((e) => /* @__PURE__ */ o(y, {
|
|
102
|
+
value: e,
|
|
103
|
+
children: D(e)
|
|
104
|
+
}, e)) })]
|
|
105
|
+
})]
|
|
106
|
+
}),
|
|
107
|
+
/* @__PURE__ */ s("div", {
|
|
108
|
+
className: "space-y-2",
|
|
109
|
+
children: [/* @__PURE__ */ o(u, { children: "Priority" }), /* @__PURE__ */ s(_, {
|
|
110
|
+
value: B,
|
|
111
|
+
onValueChange: (e) => V(e),
|
|
112
|
+
children: [/* @__PURE__ */ o(b, { children: /* @__PURE__ */ o(x, {}) }), /* @__PURE__ */ o(v, { children: E.map((e) => /* @__PURE__ */ o(y, {
|
|
113
|
+
value: e,
|
|
114
|
+
children: D(e)
|
|
115
|
+
}, e)) })]
|
|
116
|
+
})]
|
|
117
|
+
}),
|
|
118
|
+
/* @__PURE__ */ s("div", {
|
|
119
|
+
className: "space-y-2",
|
|
120
|
+
children: [/* @__PURE__ */ o(u, { children: "Status" }), /* @__PURE__ */ s(_, {
|
|
121
|
+
value: H,
|
|
122
|
+
onValueChange: (e) => U(e),
|
|
123
|
+
children: [/* @__PURE__ */ o(b, { children: /* @__PURE__ */ o(x, {}) }), /* @__PURE__ */ o(v, { children: T.map((e) => /* @__PURE__ */ o(y, {
|
|
124
|
+
value: e,
|
|
125
|
+
children: D(e)
|
|
126
|
+
}, e)) })]
|
|
127
|
+
})]
|
|
128
|
+
})
|
|
129
|
+
]
|
|
130
|
+
})
|
|
131
|
+
]
|
|
132
|
+
}),
|
|
133
|
+
/* @__PURE__ */ s(m, { children: [/* @__PURE__ */ o(c, {
|
|
134
|
+
variant: "outline",
|
|
135
|
+
onClick: () => O(!1),
|
|
136
|
+
disabled: K,
|
|
137
|
+
children: "Cancel"
|
|
138
|
+
}), /* @__PURE__ */ s(c, {
|
|
139
|
+
onClick: () => {
|
|
140
|
+
if (!A.trim()) {
|
|
141
|
+
t.warning("Title required", "Give the work order a title.");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
G({ variables: { input: {
|
|
145
|
+
title: A.trim(),
|
|
146
|
+
description: M.trim() || null,
|
|
147
|
+
assetId: P || null,
|
|
148
|
+
assignedTo: I.trim() || null,
|
|
149
|
+
type: R,
|
|
150
|
+
priority: B,
|
|
151
|
+
status: H
|
|
152
|
+
} } });
|
|
153
|
+
},
|
|
154
|
+
disabled: K,
|
|
155
|
+
children: [K ? /* @__PURE__ */ o(r, { className: "mr-2 h-4 w-4 animate-spin" }) : null, K ? "Creating…" : "Create Work Order"]
|
|
156
|
+
})] })
|
|
157
|
+
]
|
|
158
|
+
})
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
//#endregion
|
|
162
|
+
export { O as NewWorkOrderDialog };
|
|
163
|
+
|
|
164
|
+
//# sourceMappingURL=NewWorkOrderDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NewWorkOrderDialog.js","names":[],"sources":["../../../src/assethandler/ops/NewWorkOrderDialog.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { Loader2 } from 'lucide-react';\nimport { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport { notify } from '../utils/toast';\n\n/**\n * Reusable \"New Work Order\" create dialog, wired to the real createWorkOrder\n * mutation (wspace-assethandler-svc). Used by the Operations Hub.\n */\nconst CREATE_WORK_ORDER_MUTATION = gql`\n mutation AssetHandlerCreateWorkOrder($input: CreateWorkOrderInput!) {\n createWorkOrder(input: $input) {\n id\n title\n }\n }\n`;\n\ninterface CreateWorkOrderResult {\n createWorkOrder: { id: string; title: string };\n}\n\nconst WORK_ORDER_TYPES = ['CORRECTIVE', 'PREVENTIVE', 'PREDICTIVE', 'EMERGENCY'] as const;\nconst WORK_ORDER_STATUSES = [\n 'DRAFT',\n 'SCHEDULED',\n 'APPROVED',\n 'IN_PROGRESS',\n 'COMPLETED',\n 'CANCELLED',\n] as const;\nconst PRIORITIES = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'] as const;\n\nconst humanize = (value: string) =>\n value\n .toLowerCase()\n .replace(/_/g, ' ')\n .replace(/^\\w/, (c) => c.toUpperCase());\n\nexport function NewWorkOrderDialog({\n open,\n onOpenChange,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const { assets } = useAssetHandlerStore();\n\n const [title, setTitle] = useState('');\n const [description, setDescription] = useState('');\n const [assetId, setAssetId] = useState('');\n const [assignedTo, setAssignedTo] = useState('');\n const [type, setType] = useState<(typeof WORK_ORDER_TYPES)[number]>('CORRECTIVE');\n const [priority, setPriority] = useState<(typeof PRIORITIES)[number]>('MEDIUM');\n const [status, setStatus] = useState<(typeof WORK_ORDER_STATUSES)[number]>('DRAFT');\n\n const reset = () => {\n setTitle('');\n setDescription('');\n setAssetId('');\n setAssignedTo('');\n setType('CORRECTIVE');\n setPriority('MEDIUM');\n setStatus('DRAFT');\n };\n\n const [createWorkOrder, { loading }] = useMutation<CreateWorkOrderResult>(\n CREATE_WORK_ORDER_MUTATION,\n {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: (data) => {\n notify.success('Work order created', `${data.createWorkOrder.title} was raised.`);\n reset();\n onOpenChange(false);\n },\n onError: (error) => notify.error('Could not create work order', error.message),\n }\n );\n\n const handleSubmit = () => {\n if (!title.trim()) {\n notify.warning('Title required', 'Give the work order a title.');\n return;\n }\n void createWorkOrder({\n variables: {\n input: {\n title: title.trim(),\n description: description.trim() || null,\n assetId: assetId || null,\n assignedTo: assignedTo.trim() || null,\n type,\n priority,\n status,\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-h-[85vh] overflow-y-auto sm:max-w-xl\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New Work Order</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Raise a work order when an asset needs repair, inspection or attention.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label>Title *</Label>\n <Input\n placeholder=\"e.g., Replace worn drive belt\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Description</Label>\n <Textarea\n placeholder=\"Describe the work required\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n />\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Asset</Label>\n <Select value={assetId} onValueChange={setAssetId}>\n <SelectTrigger>\n <SelectValue placeholder=\"Unassigned\" />\n </SelectTrigger>\n <SelectContent>\n {assets.map((asset) => (\n <SelectItem key={asset.id} value={asset.id}>\n {asset.name}\n {asset.assetTag ? ` · ${asset.assetTag}` : ''}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Assigned To</Label>\n <Input\n placeholder=\"e.g., Facilities team\"\n value={assignedTo}\n onChange={(e) => setAssignedTo(e.target.value)}\n />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-3\">\n <div className=\"space-y-2\">\n <Label>Type</Label>\n <Select value={type} onValueChange={(v) => setType(v as typeof type)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {WORK_ORDER_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {humanize(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Priority</Label>\n <Select value={priority} onValueChange={(v) => setPriority(v as typeof priority)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {PRIORITIES.map((p) => (\n <SelectItem key={p} value={p}>\n {humanize(p)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Status</Label>\n <Select value={status} onValueChange={(v) => setStatus(v as typeof status)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {WORK_ORDER_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {loading ? 'Creating…' : 'Create Work Order'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { useAssetHandlerStore as e } from "../store/assethandlerStore.js";
|
|
2
|
+
import { notify as t } from "../utils/toast.js";
|
|
3
|
+
import { useState as n } from "react";
|
|
4
|
+
import { Loader2 as r, Plus as i, X as a } from "lucide-react";
|
|
5
|
+
import { gql as o } from "@apollo/client";
|
|
6
|
+
import { useMutation as s } from "@apollo/client/react";
|
|
7
|
+
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
8
|
+
import { Button as u, Input as d, Label as f, ResponsiveDialog as p, ResponsiveDialogContent as m, ResponsiveDialogDescription as h, ResponsiveDialogFooter as g, ResponsiveDialogHeader as _, ResponsiveDialogTitle as v, Select as y, SelectContent as b, SelectItem as x, SelectTrigger as S, SelectValue as C, Textarea as w } from "@burdenoff/fe-libs/ui";
|
|
9
|
+
//#region src/assethandler/ops/ScheduleMaintenanceDialog.tsx
|
|
10
|
+
var T = o`
|
|
11
|
+
mutation AssetHandlerCreateMaintenanceRecord($input: CreateMaintenanceRecordInput!) {
|
|
12
|
+
createMaintenanceRecord(input: $input) {
|
|
13
|
+
id
|
|
14
|
+
title
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
`, E = [
|
|
18
|
+
"PREVENTIVE",
|
|
19
|
+
"CORRECTIVE",
|
|
20
|
+
"INSPECTION",
|
|
21
|
+
"CALIBRATION",
|
|
22
|
+
"EMERGENCY"
|
|
23
|
+
], D = [
|
|
24
|
+
"CRITICAL",
|
|
25
|
+
"HIGH",
|
|
26
|
+
"MEDIUM",
|
|
27
|
+
"LOW"
|
|
28
|
+
], O = (e) => e.toLowerCase().replace(/_/g, " ").replace(/^\w/, (e) => e.toUpperCase());
|
|
29
|
+
function k({ open: o, onOpenChange: k }) {
|
|
30
|
+
let { assets: A } = e(), [j, M] = n(""), [N, P] = n(""), [F, I] = n(""), [L, R] = n("PREVENTIVE"), [z, B] = n("MEDIUM"), [V, H] = n(""), [U, W] = n(""), [G, K] = n([""]), q = () => {
|
|
31
|
+
M(""), P(""), I(""), R("PREVENTIVE"), B("MEDIUM"), H(""), W(""), K([""]);
|
|
32
|
+
}, [J, { loading: Y }] = s(T, {
|
|
33
|
+
refetchQueries: ["AssetHandlerBootstrap"],
|
|
34
|
+
onCompleted: (e) => {
|
|
35
|
+
t.success("Maintenance scheduled", `${e.createMaintenanceRecord.title} was added.`), q(), k(!1);
|
|
36
|
+
},
|
|
37
|
+
onError: (e) => t.error("Could not schedule maintenance", e.message)
|
|
38
|
+
}), X = (e, t) => K((n) => n.map((n, r) => r === e ? t : n)), Z = () => K((e) => [...e, ""]), Q = (e) => K((t) => t.length === 1 ? t : t.filter((t, n) => n !== e));
|
|
39
|
+
return /* @__PURE__ */ c(p, {
|
|
40
|
+
open: o,
|
|
41
|
+
onOpenChange: k,
|
|
42
|
+
children: /* @__PURE__ */ l(m, {
|
|
43
|
+
className: "max-h-[85vh] overflow-y-auto sm:max-w-2xl",
|
|
44
|
+
children: [
|
|
45
|
+
/* @__PURE__ */ l(_, { children: [/* @__PURE__ */ c(v, { children: "Schedule Maintenance" }), /* @__PURE__ */ c(h, { children: "Plan a maintenance job against an asset, with its own checklist and cost estimate." })] }),
|
|
46
|
+
/* @__PURE__ */ l("div", {
|
|
47
|
+
className: "space-y-4",
|
|
48
|
+
children: [
|
|
49
|
+
/* @__PURE__ */ l("div", {
|
|
50
|
+
className: "space-y-2",
|
|
51
|
+
children: [/* @__PURE__ */ c(f, { children: "Asset *" }), /* @__PURE__ */ l(y, {
|
|
52
|
+
value: j,
|
|
53
|
+
onValueChange: M,
|
|
54
|
+
children: [/* @__PURE__ */ c(S, { children: /* @__PURE__ */ c(C, { placeholder: "Select an asset" }) }), /* @__PURE__ */ c(b, { children: A.map((e) => /* @__PURE__ */ l(x, {
|
|
55
|
+
value: e.id,
|
|
56
|
+
children: [e.name, e.assetTag ? ` · ${e.assetTag}` : ""]
|
|
57
|
+
}, e.id)) })]
|
|
58
|
+
})]
|
|
59
|
+
}),
|
|
60
|
+
/* @__PURE__ */ l("div", {
|
|
61
|
+
className: "space-y-2",
|
|
62
|
+
children: [/* @__PURE__ */ c(f, { children: "Title *" }), /* @__PURE__ */ c(d, {
|
|
63
|
+
placeholder: "e.g., Quarterly HVAC service",
|
|
64
|
+
value: N,
|
|
65
|
+
onChange: (e) => P(e.target.value)
|
|
66
|
+
})]
|
|
67
|
+
}),
|
|
68
|
+
/* @__PURE__ */ l("div", {
|
|
69
|
+
className: "space-y-2",
|
|
70
|
+
children: [/* @__PURE__ */ c(f, { children: "Description" }), /* @__PURE__ */ c(w, {
|
|
71
|
+
placeholder: "What does this job involve?",
|
|
72
|
+
value: F,
|
|
73
|
+
onChange: (e) => I(e.target.value),
|
|
74
|
+
rows: 2
|
|
75
|
+
})]
|
|
76
|
+
}),
|
|
77
|
+
/* @__PURE__ */ l("div", {
|
|
78
|
+
className: "grid gap-4 md:grid-cols-3",
|
|
79
|
+
children: [
|
|
80
|
+
/* @__PURE__ */ l("div", {
|
|
81
|
+
className: "space-y-2",
|
|
82
|
+
children: [/* @__PURE__ */ c(f, { children: "Type" }), /* @__PURE__ */ l(y, {
|
|
83
|
+
value: L,
|
|
84
|
+
onValueChange: (e) => R(e),
|
|
85
|
+
children: [/* @__PURE__ */ c(S, { children: /* @__PURE__ */ c(C, {}) }), /* @__PURE__ */ c(b, { children: E.map((e) => /* @__PURE__ */ c(x, {
|
|
86
|
+
value: e,
|
|
87
|
+
children: O(e)
|
|
88
|
+
}, e)) })]
|
|
89
|
+
})]
|
|
90
|
+
}),
|
|
91
|
+
/* @__PURE__ */ l("div", {
|
|
92
|
+
className: "space-y-2",
|
|
93
|
+
children: [/* @__PURE__ */ c(f, { children: "Priority" }), /* @__PURE__ */ l(y, {
|
|
94
|
+
value: z,
|
|
95
|
+
onValueChange: (e) => B(e),
|
|
96
|
+
children: [/* @__PURE__ */ c(S, { children: /* @__PURE__ */ c(C, {}) }), /* @__PURE__ */ c(b, { children: D.map((e) => /* @__PURE__ */ c(x, {
|
|
97
|
+
value: e,
|
|
98
|
+
children: O(e)
|
|
99
|
+
}, e)) })]
|
|
100
|
+
})]
|
|
101
|
+
}),
|
|
102
|
+
/* @__PURE__ */ l("div", {
|
|
103
|
+
className: "space-y-2",
|
|
104
|
+
children: [/* @__PURE__ */ c(f, { children: "Estimated Cost" }), /* @__PURE__ */ c(d, {
|
|
105
|
+
type: "number",
|
|
106
|
+
min: "0",
|
|
107
|
+
step: "0.01",
|
|
108
|
+
placeholder: "e.g., 500",
|
|
109
|
+
value: U,
|
|
110
|
+
onChange: (e) => W(e.target.value)
|
|
111
|
+
})]
|
|
112
|
+
})
|
|
113
|
+
]
|
|
114
|
+
}),
|
|
115
|
+
/* @__PURE__ */ l("div", {
|
|
116
|
+
className: "space-y-2",
|
|
117
|
+
children: [/* @__PURE__ */ c(f, { children: "Scheduled Date" }), /* @__PURE__ */ c(d, {
|
|
118
|
+
type: "date",
|
|
119
|
+
value: V,
|
|
120
|
+
onChange: (e) => H(e.target.value)
|
|
121
|
+
})]
|
|
122
|
+
}),
|
|
123
|
+
/* @__PURE__ */ l("div", {
|
|
124
|
+
className: "space-y-2",
|
|
125
|
+
children: [/* @__PURE__ */ l("div", {
|
|
126
|
+
className: "flex items-center justify-between",
|
|
127
|
+
children: [/* @__PURE__ */ c(f, { children: "Checklist" }), /* @__PURE__ */ l(u, {
|
|
128
|
+
type: "button",
|
|
129
|
+
size: "sm",
|
|
130
|
+
variant: "ghost",
|
|
131
|
+
onClick: Z,
|
|
132
|
+
children: [/* @__PURE__ */ c(i, { className: "mr-1 h-3.5 w-3.5" }), "Add task"]
|
|
133
|
+
})]
|
|
134
|
+
}), /* @__PURE__ */ c("div", {
|
|
135
|
+
className: "space-y-2",
|
|
136
|
+
children: G.map((e, t) => /* @__PURE__ */ l("div", {
|
|
137
|
+
className: "flex items-center gap-2",
|
|
138
|
+
children: [/* @__PURE__ */ c(d, {
|
|
139
|
+
placeholder: `Task ${t + 1}`,
|
|
140
|
+
value: e,
|
|
141
|
+
onChange: (e) => X(t, e.target.value)
|
|
142
|
+
}), /* @__PURE__ */ c(u, {
|
|
143
|
+
type: "button",
|
|
144
|
+
size: "icon",
|
|
145
|
+
variant: "ghost",
|
|
146
|
+
onClick: () => Q(t),
|
|
147
|
+
disabled: G.length === 1,
|
|
148
|
+
"aria-label": "Remove task",
|
|
149
|
+
children: /* @__PURE__ */ c(a, { className: "h-4 w-4" })
|
|
150
|
+
})]
|
|
151
|
+
}, t))
|
|
152
|
+
})]
|
|
153
|
+
})
|
|
154
|
+
]
|
|
155
|
+
}),
|
|
156
|
+
/* @__PURE__ */ l(g, { children: [/* @__PURE__ */ c(u, {
|
|
157
|
+
variant: "outline",
|
|
158
|
+
onClick: () => k(!1),
|
|
159
|
+
disabled: Y,
|
|
160
|
+
children: "Cancel"
|
|
161
|
+
}), /* @__PURE__ */ l(u, {
|
|
162
|
+
onClick: () => {
|
|
163
|
+
if (!j) {
|
|
164
|
+
t.warning("Asset required", "Pick the asset this maintenance is for.");
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (!N.trim()) {
|
|
168
|
+
t.warning("Title required", "Give the maintenance job a title.");
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
let e = Number(U), n = G.map((e) => e.trim()).filter((e) => e !== "").map((e) => ({
|
|
172
|
+
task: e,
|
|
173
|
+
completed: !1
|
|
174
|
+
}));
|
|
175
|
+
J({ variables: { input: {
|
|
176
|
+
assetId: j,
|
|
177
|
+
title: N.trim(),
|
|
178
|
+
description: F.trim() || null,
|
|
179
|
+
type: L,
|
|
180
|
+
status: "SCHEDULED",
|
|
181
|
+
priority: z,
|
|
182
|
+
scheduledAt: V ? new Date(V).toISOString() : null,
|
|
183
|
+
estimatedCost: U.trim() !== "" && Number.isFinite(e) ? e : null,
|
|
184
|
+
checklist: n
|
|
185
|
+
} } });
|
|
186
|
+
},
|
|
187
|
+
disabled: Y,
|
|
188
|
+
children: [Y ? /* @__PURE__ */ c(r, { className: "mr-2 h-4 w-4 animate-spin" }) : null, Y ? "Scheduling…" : "Schedule Maintenance"]
|
|
189
|
+
})] })
|
|
190
|
+
]
|
|
191
|
+
})
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
//#endregion
|
|
195
|
+
export { k as ScheduleMaintenanceDialog };
|
|
196
|
+
|
|
197
|
+
//# sourceMappingURL=ScheduleMaintenanceDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScheduleMaintenanceDialog.js","names":[],"sources":["../../../src/assethandler/ops/ScheduleMaintenanceDialog.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { Loader2, Plus, X } from 'lucide-react';\nimport { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport { notify } from '../utils/toast';\n\n/**\n * Reusable \"Schedule Maintenance\" create dialog. Wired to the real\n * createMaintenanceRecord mutation (wspace-assethandler-svc). Shared by the\n * Maintenance Scheduler and Maintenance Calendar pages so both entry points\n * write through one contract.\n *\n * Reuse note: a wspace-calendar-svc CalendarEvent projection is deliberately\n * deferred — createEvent requires a calendarId that the AssetHandler MFE has no\n * handle on. The Maintenance Calendar therefore renders the real\n * maintenanceRecords (scheduledAt) rather than shared-platform CalendarEvents.\n */\nconst CREATE_MAINTENANCE_RECORD_MUTATION = gql`\n mutation AssetHandlerCreateMaintenanceRecord($input: CreateMaintenanceRecordInput!) {\n createMaintenanceRecord(input: $input) {\n id\n title\n }\n }\n`;\n\ninterface CreateMaintenanceRecordResult {\n createMaintenanceRecord: { id: string; title: string };\n}\n\n// Maintenance `type` is a free-form String on the backend; these are the\n// canonical categories the product exposes in the UI.\nconst MAINTENANCE_TYPES = [\n 'PREVENTIVE',\n 'CORRECTIVE',\n 'INSPECTION',\n 'CALIBRATION',\n 'EMERGENCY',\n] as const;\nconst PRIORITIES = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'] as const;\n\nconst humanize = (value: string) =>\n value\n .toLowerCase()\n .replace(/_/g, ' ')\n .replace(/^\\w/, (c) => c.toUpperCase());\n\nexport function ScheduleMaintenanceDialog({\n open,\n onOpenChange,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const { assets } = useAssetHandlerStore();\n\n const [assetId, setAssetId] = useState('');\n const [title, setTitle] = useState('');\n const [description, setDescription] = useState('');\n const [type, setType] = useState<(typeof MAINTENANCE_TYPES)[number]>('PREVENTIVE');\n const [priority, setPriority] = useState<(typeof PRIORITIES)[number]>('MEDIUM');\n const [scheduledAt, setScheduledAt] = useState('');\n const [estimatedCost, setEstimatedCost] = useState('');\n const [checklist, setChecklist] = useState<string[]>(['']);\n\n const reset = () => {\n setAssetId('');\n setTitle('');\n setDescription('');\n setType('PREVENTIVE');\n setPriority('MEDIUM');\n setScheduledAt('');\n setEstimatedCost('');\n setChecklist(['']);\n };\n\n const [createMaintenanceRecord, { loading }] = useMutation<CreateMaintenanceRecordResult>(\n CREATE_MAINTENANCE_RECORD_MUTATION,\n {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: (data) => {\n notify.success('Maintenance scheduled', `${data.createMaintenanceRecord.title} was added.`);\n reset();\n onOpenChange(false);\n },\n onError: (error) => notify.error('Could not schedule maintenance', error.message),\n }\n );\n\n const setChecklistItem = (index: number, value: string) =>\n setChecklist((prev) => prev.map((task, i) => (i === index ? value : task)));\n const addChecklistItem = () => setChecklist((prev) => [...prev, '']);\n const removeChecklistItem = (index: number) =>\n setChecklist((prev) => (prev.length === 1 ? prev : prev.filter((_, i) => i !== index)));\n\n const handleSubmit = () => {\n if (!assetId) {\n notify.warning('Asset required', 'Pick the asset this maintenance is for.');\n return;\n }\n if (!title.trim()) {\n notify.warning('Title required', 'Give the maintenance job a title.');\n return;\n }\n const parsedCost = Number(estimatedCost);\n const cleanedChecklist = checklist\n .map((task) => task.trim())\n .filter((task) => task !== '')\n .map((task) => ({ task, completed: false }));\n void createMaintenanceRecord({\n variables: {\n input: {\n assetId,\n title: title.trim(),\n description: description.trim() || null,\n type,\n status: 'SCHEDULED',\n priority,\n scheduledAt: scheduledAt ? new Date(scheduledAt).toISOString() : null,\n estimatedCost:\n estimatedCost.trim() !== '' && Number.isFinite(parsedCost) ? parsedCost : null,\n checklist: cleanedChecklist,\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-h-[85vh] overflow-y-auto sm:max-w-2xl\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Schedule Maintenance</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Plan a maintenance job against an asset, with its own checklist and cost estimate.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label>Asset *</Label>\n <Select value={assetId} onValueChange={setAssetId}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select an asset\" />\n </SelectTrigger>\n <SelectContent>\n {assets.map((asset) => (\n <SelectItem key={asset.id} value={asset.id}>\n {asset.name}\n {asset.assetTag ? ` · ${asset.assetTag}` : ''}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Title *</Label>\n <Input\n placeholder=\"e.g., Quarterly HVAC service\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Description</Label>\n <Textarea\n placeholder=\"What does this job involve?\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n />\n </div>\n <div className=\"grid gap-4 md:grid-cols-3\">\n <div className=\"space-y-2\">\n <Label>Type</Label>\n <Select value={type} onValueChange={(v) => setType(v as typeof type)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {MAINTENANCE_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {humanize(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Priority</Label>\n <Select value={priority} onValueChange={(v) => setPriority(v as typeof priority)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {PRIORITIES.map((p) => (\n <SelectItem key={p} value={p}>\n {humanize(p)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Estimated Cost</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n placeholder=\"e.g., 500\"\n value={estimatedCost}\n onChange={(e) => setEstimatedCost(e.target.value)}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label>Scheduled Date</Label>\n <Input\n type=\"date\"\n value={scheduledAt}\n onChange={(e) => setScheduledAt(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <Label>Checklist</Label>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={addChecklistItem}>\n <Plus className=\"mr-1 h-3.5 w-3.5\" />\n Add task\n </Button>\n </div>\n <div className=\"space-y-2\">\n {checklist.map((task, i) => (\n <div key={i} className=\"flex items-center gap-2\">\n <Input\n placeholder={`Task ${i + 1}`}\n value={task}\n onChange={(e) => setChecklistItem(i, e.target.value)}\n />\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"ghost\"\n onClick={() => removeChecklistItem(i)}\n disabled={checklist.length === 1}\n aria-label=\"Remove task\"\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {loading ? 'Scheduling…' : 'Schedule Maintenance'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|