@nice2dev/ui-erp 1.0.10

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/index.mjs ADDED
@@ -0,0 +1,1271 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { useState, useMemo, useCallback } from "react";
3
+ const DEFAULT_VIEW_CONFIG$1 = {
4
+ timeUnit: "day",
5
+ showUtilization: true,
6
+ showConflicts: true,
7
+ groupBy: "resource",
8
+ utilizationThreshold: 80
9
+ };
10
+ const TIME_INCREMENTS = {
11
+ hour: 60 * 60 * 1e3,
12
+ day: 24 * 60 * 60 * 1e3,
13
+ week: 7 * 24 * 60 * 60 * 1e3,
14
+ month: 30 * 24 * 60 * 60 * 1e3,
15
+ quarter: 90 * 24 * 60 * 60 * 1e3,
16
+ year: 365 * 24 * 60 * 60 * 1e3
17
+ };
18
+ const NiceResourceAllocation = ({
19
+ resources,
20
+ allocations,
21
+ dateRange,
22
+ viewConfig: externalConfig,
23
+ onAllocationCreate,
24
+ onAllocationUpdate,
25
+ onAllocationDelete,
26
+ onResourceClick,
27
+ readOnly = false,
28
+ className = ""
29
+ }) => {
30
+ var _a, _b;
31
+ const config = { ...DEFAULT_VIEW_CONFIG$1, ...externalConfig };
32
+ const [selectedAllocation, setSelectedAllocation] = useState(null);
33
+ const [hoveredCell, setHoveredCell] = useState(null);
34
+ const [timeUnit, setTimeUnit] = useState(config.timeUnit);
35
+ const [expandedResources, setExpandedResources] = useState(
36
+ new Set(resources.map((r) => r.id))
37
+ );
38
+ const [showAllocationModal, setShowAllocationModal] = useState(false);
39
+ const [newAllocation, setNewAllocation] = useState({});
40
+ const timePeriods = useMemo(() => {
41
+ const periods = [];
42
+ const increment = TIME_INCREMENTS[timeUnit];
43
+ let current = new Date(dateRange.start);
44
+ while (current <= dateRange.end) {
45
+ periods.push(new Date(current));
46
+ current = new Date(current.getTime() + increment);
47
+ }
48
+ return periods;
49
+ }, [dateRange.start, dateRange.end, timeUnit]);
50
+ const utilizationMap = useMemo(() => {
51
+ const map = /* @__PURE__ */ new Map();
52
+ resources.forEach((resource) => {
53
+ const resourceMap = /* @__PURE__ */ new Map();
54
+ timePeriods.forEach((period) => {
55
+ const periodStart = period.getTime();
56
+ const periodEnd = periodStart + TIME_INCREMENTS[timeUnit];
57
+ const periodAllocations = allocations.filter((a) => {
58
+ if (a.resourceId !== resource.id) {
59
+ return false;
60
+ }
61
+ const allocStart = a.start.getTime();
62
+ const allocEnd = a.end.getTime();
63
+ return allocStart < periodEnd && allocEnd > periodStart;
64
+ });
65
+ const allocatedHours = periodAllocations.reduce((sum, a) => sum + a.hoursPerDay, 0);
66
+ const availableHours = resource.maxCapacity;
67
+ const utilizationPercent = availableHours > 0 ? allocatedHours / availableHours * 100 : 0;
68
+ resourceMap.set(periodStart, {
69
+ resourceId: resource.id,
70
+ period: { start: period, end: new Date(periodEnd) },
71
+ allocatedHours,
72
+ availableHours,
73
+ utilizationPercent,
74
+ overallocated: utilizationPercent > 100
75
+ });
76
+ });
77
+ map.set(resource.id, resourceMap);
78
+ });
79
+ return map;
80
+ }, [resources, allocations, timePeriods, timeUnit]);
81
+ const conflicts = useMemo(() => {
82
+ const conflictList = [];
83
+ utilizationMap.forEach((resourceMap, resourceId) => {
84
+ const resource = resources.find((r) => r.id === resourceId);
85
+ resourceMap.forEach((util, periodStart) => {
86
+ if (util.overallocated) {
87
+ const period = new Date(periodStart);
88
+ const periodEnd = periodStart + TIME_INCREMENTS[timeUnit];
89
+ const conflictAllocations = allocations.filter((a) => {
90
+ if (a.resourceId !== resourceId) {
91
+ return false;
92
+ }
93
+ const allocStart = a.start.getTime();
94
+ const allocEnd = a.end.getTime();
95
+ return allocStart < periodEnd && allocEnd > periodStart;
96
+ });
97
+ conflictList.push({
98
+ resourceId,
99
+ date: period,
100
+ allocatedHours: util.allocatedHours,
101
+ maxCapacity: resource.maxCapacity,
102
+ allocations: conflictAllocations
103
+ });
104
+ }
105
+ });
106
+ });
107
+ return conflictList;
108
+ }, [utilizationMap, allocations, resources, timeUnit]);
109
+ const getCellAllocations = useCallback(
110
+ (resourceId, date) => {
111
+ const periodStart = date.getTime();
112
+ const periodEnd = periodStart + TIME_INCREMENTS[timeUnit];
113
+ return allocations.filter((a) => {
114
+ if (a.resourceId !== resourceId) {
115
+ return false;
116
+ }
117
+ const allocStart = a.start.getTime();
118
+ const allocEnd = a.end.getTime();
119
+ return allocStart < periodEnd && allocEnd > periodStart;
120
+ });
121
+ },
122
+ [allocations, timeUnit]
123
+ );
124
+ const getCellColor = (resourceId, date) => {
125
+ var _a2;
126
+ const util = (_a2 = utilizationMap.get(resourceId)) == null ? void 0 : _a2.get(date.getTime());
127
+ if (!util) {
128
+ return "transparent";
129
+ }
130
+ if (util.overallocated) {
131
+ return "rgba(239, 68, 68, 0.4)";
132
+ }
133
+ if (util.utilizationPercent >= config.utilizationThreshold) {
134
+ return "rgba(245, 158, 11, 0.3)";
135
+ }
136
+ if (util.utilizationPercent > 0) {
137
+ return "rgba(34, 197, 94, 0.2)";
138
+ }
139
+ return "transparent";
140
+ };
141
+ const formatDate = (date) => {
142
+ switch (timeUnit) {
143
+ case "hour":
144
+ return date.toLocaleTimeString([], { hour: "2-digit" });
145
+ case "day":
146
+ return date.toLocaleDateString([], { weekday: "short", day: "numeric" });
147
+ case "week":
148
+ return `W${Math.ceil(date.getDate() / 7)}`;
149
+ case "month":
150
+ return date.toLocaleDateString([], { month: "short" });
151
+ default:
152
+ return date.toLocaleDateString();
153
+ }
154
+ };
155
+ const handleCellClick = (resourceId, date) => {
156
+ var _a2;
157
+ if (readOnly) {
158
+ return;
159
+ }
160
+ setNewAllocation({
161
+ resourceId,
162
+ start: date,
163
+ end: new Date(date.getTime() + TIME_INCREMENTS[timeUnit]),
164
+ hoursPerDay: ((_a2 = resources.find((r) => r.id === resourceId)) == null ? void 0 : _a2.maxCapacity) || 8,
165
+ status: "tentative"
166
+ });
167
+ setShowAllocationModal(true);
168
+ };
169
+ const handleCreateAllocation = () => {
170
+ if (newAllocation.resourceId && newAllocation.start && newAllocation.end) {
171
+ onAllocationCreate == null ? void 0 : onAllocationCreate({
172
+ resourceId: newAllocation.resourceId,
173
+ start: newAllocation.start,
174
+ end: newAllocation.end,
175
+ hoursPerDay: newAllocation.hoursPerDay || 8,
176
+ status: newAllocation.status || "tentative",
177
+ notes: newAllocation.notes
178
+ });
179
+ setShowAllocationModal(false);
180
+ setNewAllocation({});
181
+ }
182
+ };
183
+ const toggleResource = (resourceId) => {
184
+ setExpandedResources((prev) => {
185
+ const next = new Set(prev);
186
+ if (next.has(resourceId)) {
187
+ next.delete(resourceId);
188
+ } else {
189
+ next.add(resourceId);
190
+ }
191
+ return next;
192
+ });
193
+ };
194
+ const getResourceTypeIcon = (type) => {
195
+ switch (type) {
196
+ case "human":
197
+ return "👤";
198
+ case "equipment":
199
+ return "🔧";
200
+ case "room":
201
+ return "🏢";
202
+ case "vehicle":
203
+ return "🚗";
204
+ case "material":
205
+ return "📦";
206
+ default:
207
+ return "📋";
208
+ }
209
+ };
210
+ return /* @__PURE__ */ jsxs("div", { className: `nice-resource-allocation ${className}`, children: [
211
+ /* @__PURE__ */ jsxs("header", { className: "allocation__toolbar", children: [
212
+ /* @__PURE__ */ jsxs("div", { className: "toolbar__left", children: [
213
+ /* @__PURE__ */ jsx("h2", { children: "Resource Allocation" }),
214
+ /* @__PURE__ */ jsxs("span", { className: "date-range", children: [
215
+ dateRange.start.toLocaleDateString(),
216
+ " - ",
217
+ dateRange.end.toLocaleDateString()
218
+ ] })
219
+ ] }),
220
+ /* @__PURE__ */ jsx("div", { className: "toolbar__center", children: /* @__PURE__ */ jsx("div", { className: "time-unit-selector", children: ["day", "week", "month"].map((unit) => /* @__PURE__ */ jsx(
221
+ "button",
222
+ {
223
+ className: `unit-button ${timeUnit === unit ? "unit-button--active" : ""}`,
224
+ onClick: () => setTimeUnit(unit),
225
+ children: unit.charAt(0).toUpperCase() + unit.slice(1)
226
+ },
227
+ unit
228
+ )) }) }),
229
+ /* @__PURE__ */ jsx("div", { className: "toolbar__right", children: config.showConflicts && conflicts.length > 0 && /* @__PURE__ */ jsxs("div", { className: "conflicts-badge", children: [
230
+ /* @__PURE__ */ jsx("span", { className: "badge-icon", children: "⚠️" }),
231
+ conflicts.length,
232
+ " Conflict",
233
+ conflicts.length !== 1 ? "s" : ""
234
+ ] }) })
235
+ ] }),
236
+ /* @__PURE__ */ jsxs("div", { className: "allocation__legend", children: [
237
+ /* @__PURE__ */ jsxs("div", { className: "legend-item", children: [
238
+ /* @__PURE__ */ jsx("span", { className: "legend-color", style: { backgroundColor: "rgba(34, 197, 94, 0.2)" } }),
239
+ /* @__PURE__ */ jsx("span", { children: "Allocated" })
240
+ ] }),
241
+ /* @__PURE__ */ jsxs("div", { className: "legend-item", children: [
242
+ /* @__PURE__ */ jsx("span", { className: "legend-color", style: { backgroundColor: "rgba(245, 158, 11, 0.3)" } }),
243
+ /* @__PURE__ */ jsxs("span", { children: [
244
+ "High Utilization (",
245
+ ">",
246
+ "=",
247
+ config.utilizationThreshold,
248
+ "%)"
249
+ ] })
250
+ ] }),
251
+ /* @__PURE__ */ jsxs("div", { className: "legend-item", children: [
252
+ /* @__PURE__ */ jsx("span", { className: "legend-color", style: { backgroundColor: "rgba(239, 68, 68, 0.4)" } }),
253
+ /* @__PURE__ */ jsx("span", { children: "Overallocated" })
254
+ ] })
255
+ ] }),
256
+ /* @__PURE__ */ jsxs("div", { className: "allocation__grid", children: [
257
+ /* @__PURE__ */ jsxs("div", { className: "grid__header", children: [
258
+ /* @__PURE__ */ jsx("div", { className: "resource-header", children: "Resource" }),
259
+ /* @__PURE__ */ jsx("div", { className: "time-headers", children: timePeriods.map((period, idx) => /* @__PURE__ */ jsx("div", { className: "time-header", children: formatDate(period) }, idx)) })
260
+ ] }),
261
+ /* @__PURE__ */ jsx("div", { className: "grid__body", children: resources.map((resource) => /* @__PURE__ */ jsxs("div", { className: "resource-row", children: [
262
+ /* @__PURE__ */ jsxs("div", { className: "resource-cell", onClick: () => onResourceClick == null ? void 0 : onResourceClick(resource), children: [
263
+ /* @__PURE__ */ jsx(
264
+ "button",
265
+ {
266
+ className: "expand-button",
267
+ onClick: (e) => {
268
+ e.stopPropagation();
269
+ toggleResource(resource.id);
270
+ },
271
+ children: expandedResources.has(resource.id) ? "▾" : "▸"
272
+ }
273
+ ),
274
+ /* @__PURE__ */ jsx("span", { className: "resource-icon", children: getResourceTypeIcon(resource.type) }),
275
+ /* @__PURE__ */ jsxs("div", { className: "resource-info", children: [
276
+ /* @__PURE__ */ jsx("span", { className: "resource-name", children: resource.name }),
277
+ resource.department && /* @__PURE__ */ jsx("span", { className: "resource-dept", children: resource.department })
278
+ ] }),
279
+ /* @__PURE__ */ jsxs("span", { className: "resource-capacity", children: [
280
+ resource.maxCapacity,
281
+ "h/day"
282
+ ] })
283
+ ] }),
284
+ /* @__PURE__ */ jsx("div", { className: "time-cells", children: timePeriods.map((period, idx) => {
285
+ var _a2;
286
+ const cellAllocations = getCellAllocations(resource.id, period);
287
+ const util = (_a2 = utilizationMap.get(resource.id)) == null ? void 0 : _a2.get(period.getTime());
288
+ const isHovered = (hoveredCell == null ? void 0 : hoveredCell.resourceId) === resource.id && (hoveredCell == null ? void 0 : hoveredCell.date.getTime()) === period.getTime();
289
+ return /* @__PURE__ */ jsxs(
290
+ "div",
291
+ {
292
+ className: `time-cell ${isHovered ? "time-cell--hovered" : ""}`,
293
+ style: { backgroundColor: getCellColor(resource.id, period) },
294
+ onClick: () => handleCellClick(resource.id, period),
295
+ onMouseEnter: () => setHoveredCell({ resourceId: resource.id, date: period }),
296
+ onMouseLeave: () => setHoveredCell(null),
297
+ children: [
298
+ cellAllocations.length > 0 && /* @__PURE__ */ jsxs("div", { className: "allocation-indicators", children: [
299
+ cellAllocations.slice(0, 2).map((alloc) => /* @__PURE__ */ jsx(
300
+ "div",
301
+ {
302
+ className: `allocation-dot ${alloc.status}`,
303
+ onClick: (e) => {
304
+ e.stopPropagation();
305
+ setSelectedAllocation(alloc.id);
306
+ }
307
+ },
308
+ alloc.id
309
+ )),
310
+ cellAllocations.length > 2 && /* @__PURE__ */ jsxs("span", { className: "more-indicator", children: [
311
+ "+",
312
+ cellAllocations.length - 2
313
+ ] })
314
+ ] }),
315
+ config.showUtilization && util && util.allocatedHours > 0 && /* @__PURE__ */ jsxs("span", { className: "utilization-label", children: [
316
+ util.allocatedHours.toFixed(1),
317
+ "h"
318
+ ] })
319
+ ]
320
+ },
321
+ idx
322
+ );
323
+ }) }),
324
+ expandedResources.has(resource.id) && /* @__PURE__ */ jsx("div", { className: "expanded-allocations", children: allocations.filter((a) => a.resourceId === resource.id).map((allocation) => {
325
+ const startIdx = timePeriods.findIndex(
326
+ (p) => p.getTime() <= allocation.start.getTime()
327
+ );
328
+ const endIdx = timePeriods.findIndex(
329
+ (p) => p.getTime() >= allocation.end.getTime()
330
+ );
331
+ if (startIdx === -1) {
332
+ return null;
333
+ }
334
+ const span = Math.max(1, endIdx - startIdx);
335
+ const leftPercent = startIdx / timePeriods.length * 100;
336
+ const widthPercent = span / timePeriods.length * 100;
337
+ return /* @__PURE__ */ jsxs(
338
+ "div",
339
+ {
340
+ className: `allocation-bar ${allocation.status} ${selectedAllocation === allocation.id ? "selected" : ""}`,
341
+ style: {
342
+ left: `${leftPercent}%`,
343
+ width: `${widthPercent}%`
344
+ },
345
+ onClick: () => setSelectedAllocation(allocation.id),
346
+ children: [
347
+ /* @__PURE__ */ jsxs("span", { className: "allocation-label", children: [
348
+ allocation.hoursPerDay,
349
+ "h/day"
350
+ ] }),
351
+ !readOnly && /* @__PURE__ */ jsx(
352
+ "button",
353
+ {
354
+ className: "delete-allocation",
355
+ onClick: (e) => {
356
+ e.stopPropagation();
357
+ onAllocationDelete == null ? void 0 : onAllocationDelete(allocation.id);
358
+ },
359
+ children: "×"
360
+ }
361
+ )
362
+ ]
363
+ },
364
+ allocation.id
365
+ );
366
+ }) })
367
+ ] }, resource.id)) })
368
+ ] }),
369
+ showAllocationModal && /* @__PURE__ */ jsx("div", { className: "modal-overlay", onClick: () => setShowAllocationModal(false), children: /* @__PURE__ */ jsxs("div", { className: "allocation-modal", onClick: (e) => e.stopPropagation(), children: [
370
+ /* @__PURE__ */ jsx("h3", { children: "Create Allocation" }),
371
+ /* @__PURE__ */ jsxs("div", { className: "modal-form", children: [
372
+ /* @__PURE__ */ jsxs("label", { children: [
373
+ "Resource",
374
+ /* @__PURE__ */ jsxs(
375
+ "select",
376
+ {
377
+ value: newAllocation.resourceId || "",
378
+ onChange: (e) => setNewAllocation((prev) => ({ ...prev, resourceId: e.target.value })),
379
+ children: [
380
+ /* @__PURE__ */ jsx("option", { value: "", children: "Select resource..." }),
381
+ resources.map((r) => /* @__PURE__ */ jsx("option", { value: r.id, children: r.name }, r.id))
382
+ ]
383
+ }
384
+ )
385
+ ] }),
386
+ /* @__PURE__ */ jsxs("label", { children: [
387
+ "Start Date",
388
+ /* @__PURE__ */ jsx(
389
+ "input",
390
+ {
391
+ type: "date",
392
+ value: ((_a = newAllocation.start) == null ? void 0 : _a.toISOString().split("T")[0]) || "",
393
+ onChange: (e) => setNewAllocation((prev) => ({ ...prev, start: new Date(e.target.value) }))
394
+ }
395
+ )
396
+ ] }),
397
+ /* @__PURE__ */ jsxs("label", { children: [
398
+ "End Date",
399
+ /* @__PURE__ */ jsx(
400
+ "input",
401
+ {
402
+ type: "date",
403
+ value: ((_b = newAllocation.end) == null ? void 0 : _b.toISOString().split("T")[0]) || "",
404
+ onChange: (e) => setNewAllocation((prev) => ({ ...prev, end: new Date(e.target.value) }))
405
+ }
406
+ )
407
+ ] }),
408
+ /* @__PURE__ */ jsxs("label", { children: [
409
+ "Hours per Day",
410
+ /* @__PURE__ */ jsx(
411
+ "input",
412
+ {
413
+ type: "number",
414
+ min: "0.5",
415
+ max: "24",
416
+ step: "0.5",
417
+ value: newAllocation.hoursPerDay || 8,
418
+ onChange: (e) => setNewAllocation((prev) => ({
419
+ ...prev,
420
+ hoursPerDay: parseFloat(e.target.value)
421
+ }))
422
+ }
423
+ )
424
+ ] }),
425
+ /* @__PURE__ */ jsxs("label", { children: [
426
+ "Status",
427
+ /* @__PURE__ */ jsxs(
428
+ "select",
429
+ {
430
+ value: newAllocation.status || "tentative",
431
+ onChange: (e) => setNewAllocation((prev) => ({
432
+ ...prev,
433
+ status: e.target.value
434
+ })),
435
+ children: [
436
+ /* @__PURE__ */ jsx("option", { value: "tentative", children: "Tentative" }),
437
+ /* @__PURE__ */ jsx("option", { value: "confirmed", children: "Confirmed" })
438
+ ]
439
+ }
440
+ )
441
+ ] }),
442
+ /* @__PURE__ */ jsxs("label", { children: [
443
+ "Notes",
444
+ /* @__PURE__ */ jsx(
445
+ "textarea",
446
+ {
447
+ value: newAllocation.notes || "",
448
+ onChange: (e) => setNewAllocation((prev) => ({ ...prev, notes: e.target.value })),
449
+ placeholder: "Optional notes..."
450
+ }
451
+ )
452
+ ] })
453
+ ] }),
454
+ /* @__PURE__ */ jsxs("div", { className: "modal-actions", children: [
455
+ /* @__PURE__ */ jsx("button", { className: "cancel-button", onClick: () => setShowAllocationModal(false), children: "Cancel" }),
456
+ /* @__PURE__ */ jsx("button", { className: "create-button", onClick: handleCreateAllocation, children: "Create Allocation" })
457
+ ] })
458
+ ] }) })
459
+ ] });
460
+ };
461
+ const DEFAULT_VIEW_CONFIG = {
462
+ view: "grid",
463
+ sortBy: "name",
464
+ sortOrder: "asc",
465
+ showImages: true,
466
+ pageSize: 24
467
+ };
468
+ const NiceInventoryManager = ({
469
+ items,
470
+ transactions = [],
471
+ viewConfig: externalConfig,
472
+ onItemCreate,
473
+ onItemUpdate,
474
+ onItemDelete,
475
+ onTransactionCreate,
476
+ onStockCount,
477
+ onItemClick,
478
+ readOnly = false,
479
+ className = ""
480
+ }) => {
481
+ var _a, _b;
482
+ const config = { ...DEFAULT_VIEW_CONFIG, ...externalConfig };
483
+ const [filters, setFilters] = useState({});
484
+ const [view, setView] = useState(config.view);
485
+ const [sortBy, setSortBy] = useState(config.sortBy);
486
+ const [sortOrder, setSortOrder] = useState(config.sortOrder);
487
+ const [page, setPage] = useState(1);
488
+ const [selectedItems, setSelectedItems] = useState(/* @__PURE__ */ new Set());
489
+ const [showItemModal, setShowItemModal] = useState(false);
490
+ const [showTransactionModal, setShowTransactionModal] = useState(false);
491
+ const [editingItem, setEditingItem] = useState(null);
492
+ const [newTransaction, setNewTransaction] = useState({});
493
+ const [activeTab, setActiveTab] = useState("inventory");
494
+ const categories = useMemo(() => {
495
+ return Array.from(new Set(items.map((item) => item.category))).sort();
496
+ }, [items]);
497
+ const filteredItems = useMemo(() => {
498
+ var _a2, _b2;
499
+ let result = [...items];
500
+ if (filters.searchQuery) {
501
+ const query = filters.searchQuery.toLowerCase();
502
+ result = result.filter(
503
+ (item) => {
504
+ var _a3;
505
+ return item.name.toLowerCase().includes(query) || item.sku.toLowerCase().includes(query) || ((_a3 = item.description) == null ? void 0 : _a3.toLowerCase().includes(query));
506
+ }
507
+ );
508
+ }
509
+ if ((_a2 = filters.categories) == null ? void 0 : _a2.length) {
510
+ result = result.filter((item) => filters.categories.includes(item.category));
511
+ }
512
+ if ((_b2 = filters.statuses) == null ? void 0 : _b2.length) {
513
+ result = result.filter((item) => filters.statuses.includes(item.status));
514
+ }
515
+ if (filters.lowStockOnly) {
516
+ result = result.filter((item) => item.quantity <= item.reorderLevel);
517
+ }
518
+ result.sort((a, b) => {
519
+ var _a3, _b3;
520
+ let comparison = 0;
521
+ switch (sortBy) {
522
+ case "name":
523
+ comparison = a.name.localeCompare(b.name);
524
+ break;
525
+ case "sku":
526
+ comparison = a.sku.localeCompare(b.sku);
527
+ break;
528
+ case "quantity":
529
+ comparison = a.quantity - b.quantity;
530
+ break;
531
+ case "value":
532
+ comparison = a.quantity * a.cost.amount - b.quantity * b.cost.amount;
533
+ break;
534
+ case "lastUpdated":
535
+ comparison = (((_a3 = a.lastCountDate) == null ? void 0 : _a3.getTime()) || 0) - (((_b3 = b.lastCountDate) == null ? void 0 : _b3.getTime()) || 0);
536
+ break;
537
+ }
538
+ return sortOrder === "asc" ? comparison : -comparison;
539
+ });
540
+ return result;
541
+ }, [items, filters, sortBy, sortOrder]);
542
+ const paginatedItems = useMemo(() => {
543
+ const start = (page - 1) * config.pageSize;
544
+ return filteredItems.slice(start, start + config.pageSize);
545
+ }, [filteredItems, page, config.pageSize]);
546
+ const totalPages = Math.ceil(filteredItems.length / config.pageSize);
547
+ const reorderItems = useMemo(() => {
548
+ return items.filter((item) => item.quantity <= item.reorderLevel);
549
+ }, [items]);
550
+ const recentTransactions = useMemo(() => {
551
+ return [...transactions].sort((a, b) => b.date.getTime() - a.date.getTime()).slice(0, 50);
552
+ }, [transactions]);
553
+ const kanbanGroups = useMemo(() => {
554
+ if (view !== "kanban") {
555
+ return null;
556
+ }
557
+ const groups = /* @__PURE__ */ new Map();
558
+ const statuses = [
559
+ "in-stock",
560
+ "low-stock",
561
+ "out-of-stock",
562
+ "on-order",
563
+ "discontinued"
564
+ ];
565
+ statuses.forEach((status) => groups.set(status, []));
566
+ filteredItems.forEach((item) => {
567
+ var _a2;
568
+ (_a2 = groups.get(item.status)) == null ? void 0 : _a2.push(item);
569
+ });
570
+ return groups;
571
+ }, [filteredItems, view]);
572
+ const getStatusColor = (status) => {
573
+ switch (status) {
574
+ case "in-stock":
575
+ return "#22c55e";
576
+ case "low-stock":
577
+ return "#f59e0b";
578
+ case "out-of-stock":
579
+ return "#ef4444";
580
+ case "on-order":
581
+ return "#3b82f6";
582
+ case "discontinued":
583
+ return "#6b7280";
584
+ default:
585
+ return "#6b7280";
586
+ }
587
+ };
588
+ const getTransactionIcon = (type) => {
589
+ switch (type) {
590
+ case "receipt":
591
+ return "📥";
592
+ case "issue":
593
+ return "📤";
594
+ case "transfer":
595
+ return "🔄";
596
+ case "adjustment":
597
+ return "✏️";
598
+ case "return":
599
+ return "↩️";
600
+ case "count":
601
+ return "📊";
602
+ case "write-off":
603
+ return "❌";
604
+ default:
605
+ return "📋";
606
+ }
607
+ };
608
+ const formatCurrency = (amount, symbol = "$") => {
609
+ return `${symbol}${amount.toFixed(2)}`;
610
+ };
611
+ const handleItemSubmit = () => {
612
+ if (!editingItem) {
613
+ return;
614
+ }
615
+ if (editingItem.id) {
616
+ onItemUpdate == null ? void 0 : onItemUpdate(editingItem);
617
+ } else {
618
+ onItemCreate == null ? void 0 : onItemCreate(editingItem);
619
+ }
620
+ setShowItemModal(false);
621
+ setEditingItem(null);
622
+ };
623
+ const handleTransactionSubmit = () => {
624
+ if (newTransaction.itemId && newTransaction.type && newTransaction.quantity) {
625
+ onTransactionCreate == null ? void 0 : onTransactionCreate({
626
+ itemId: newTransaction.itemId,
627
+ type: newTransaction.type,
628
+ quantity: newTransaction.quantity,
629
+ date: /* @__PURE__ */ new Date(),
630
+ reference: newTransaction.reference,
631
+ notes: newTransaction.notes
632
+ });
633
+ setShowTransactionModal(false);
634
+ setNewTransaction({});
635
+ }
636
+ };
637
+ const toggleItemSelection = (itemId) => {
638
+ setSelectedItems((prev) => {
639
+ const next = new Set(prev);
640
+ if (next.has(itemId)) {
641
+ next.delete(itemId);
642
+ } else {
643
+ next.add(itemId);
644
+ }
645
+ return next;
646
+ });
647
+ };
648
+ return /* @__PURE__ */ jsxs("div", { className: `nice-inventory-manager ${className}`, children: [
649
+ /* @__PURE__ */ jsxs("header", { className: "inventory__toolbar", children: [
650
+ /* @__PURE__ */ jsxs("div", { className: "toolbar__left", children: [
651
+ /* @__PURE__ */ jsxs("div", { className: "search-box", children: [
652
+ /* @__PURE__ */ jsx(
653
+ "input",
654
+ {
655
+ type: "text",
656
+ placeholder: "Search items...",
657
+ value: filters.searchQuery || "",
658
+ onChange: (e) => setFilters((prev) => ({ ...prev, searchQuery: e.target.value }))
659
+ }
660
+ ),
661
+ /* @__PURE__ */ jsx("span", { className: "search-icon", children: "🔍" })
662
+ ] }),
663
+ /* @__PURE__ */ jsxs(
664
+ "select",
665
+ {
666
+ value: ((_a = filters.categories) == null ? void 0 : _a[0]) || "",
667
+ onChange: (e) => setFilters((prev) => ({
668
+ ...prev,
669
+ categories: e.target.value ? [e.target.value] : void 0
670
+ })),
671
+ children: [
672
+ /* @__PURE__ */ jsx("option", { value: "", children: "All Categories" }),
673
+ categories.map((cat) => /* @__PURE__ */ jsx("option", { value: cat, children: cat }, cat))
674
+ ]
675
+ }
676
+ ),
677
+ /* @__PURE__ */ jsxs("label", { className: "filter-checkbox", children: [
678
+ /* @__PURE__ */ jsx(
679
+ "input",
680
+ {
681
+ type: "checkbox",
682
+ checked: filters.lowStockOnly || false,
683
+ onChange: (e) => setFilters((prev) => ({ ...prev, lowStockOnly: e.target.checked }))
684
+ }
685
+ ),
686
+ "Low Stock Only"
687
+ ] })
688
+ ] }),
689
+ /* @__PURE__ */ jsxs("div", { className: "toolbar__right", children: [
690
+ /* @__PURE__ */ jsx("div", { className: "view-selector", children: ["grid", "list", "kanban"].map((v) => /* @__PURE__ */ jsx(
691
+ "button",
692
+ {
693
+ className: `view-button ${view === v ? "view-button--active" : ""}`,
694
+ onClick: () => setView(v),
695
+ children: v === "grid" ? "⊞" : v === "list" ? "☰" : "▦"
696
+ },
697
+ v
698
+ )) }),
699
+ !readOnly && /* @__PURE__ */ jsx(
700
+ "button",
701
+ {
702
+ className: "add-button",
703
+ onClick: () => {
704
+ setEditingItem({
705
+ category: categories[0],
706
+ unit: "pcs",
707
+ quantity: 0,
708
+ reorderLevel: 10,
709
+ reorderQuantity: 100,
710
+ cost: { amount: 0, currency: { code: "USD", symbol: "$", decimalPlaces: 2 } },
711
+ status: "in-stock"
712
+ });
713
+ setShowItemModal(true);
714
+ },
715
+ children: "+ Add Item"
716
+ }
717
+ )
718
+ ] })
719
+ ] }),
720
+ /* @__PURE__ */ jsxs("div", { className: "inventory__tabs", children: [
721
+ /* @__PURE__ */ jsxs(
722
+ "button",
723
+ {
724
+ className: `tab ${activeTab === "inventory" ? "tab--active" : ""}`,
725
+ onClick: () => setActiveTab("inventory"),
726
+ children: [
727
+ "Inventory (",
728
+ items.length,
729
+ ")"
730
+ ]
731
+ }
732
+ ),
733
+ /* @__PURE__ */ jsxs(
734
+ "button",
735
+ {
736
+ className: `tab ${activeTab === "transactions" ? "tab--active" : ""}`,
737
+ onClick: () => setActiveTab("transactions"),
738
+ children: [
739
+ "Transactions (",
740
+ transactions.length,
741
+ ")"
742
+ ]
743
+ }
744
+ ),
745
+ /* @__PURE__ */ jsxs(
746
+ "button",
747
+ {
748
+ className: `tab ${activeTab === "reorder" ? "tab--active" : ""}`,
749
+ onClick: () => setActiveTab("reorder"),
750
+ children: [
751
+ "Reorder Alerts",
752
+ reorderItems.length > 0 && /* @__PURE__ */ jsx("span", { className: "alert-badge", children: reorderItems.length })
753
+ ]
754
+ }
755
+ )
756
+ ] }),
757
+ /* @__PURE__ */ jsxs("div", { className: "inventory__content", children: [
758
+ activeTab === "inventory" && /* @__PURE__ */ jsxs(Fragment, { children: [
759
+ view === "grid" && /* @__PURE__ */ jsx("div", { className: "items-grid", children: paginatedItems.map((item) => {
760
+ var _a2;
761
+ return /* @__PURE__ */ jsxs(
762
+ "div",
763
+ {
764
+ className: `item-card ${selectedItems.has(item.id) ? "item-card--selected" : ""}`,
765
+ onClick: () => onItemClick == null ? void 0 : onItemClick(item),
766
+ children: [
767
+ !readOnly && /* @__PURE__ */ jsx(
768
+ "input",
769
+ {
770
+ type: "checkbox",
771
+ className: "item-checkbox",
772
+ checked: selectedItems.has(item.id),
773
+ onChange: () => toggleItemSelection(item.id),
774
+ onClick: (e) => e.stopPropagation()
775
+ }
776
+ ),
777
+ config.showImages && /* @__PURE__ */ jsx("div", { className: "item-image", children: ((_a2 = item.images) == null ? void 0 : _a2[0]) ? /* @__PURE__ */ jsx("img", { src: item.images[0], alt: item.name }) : /* @__PURE__ */ jsx("span", { className: "placeholder-image", children: "📦" }) }),
778
+ /* @__PURE__ */ jsxs("div", { className: "item-info", children: [
779
+ /* @__PURE__ */ jsx("span", { className: "item-sku", children: item.sku }),
780
+ /* @__PURE__ */ jsx("h4", { className: "item-name", children: item.name }),
781
+ /* @__PURE__ */ jsx("span", { className: "item-category", children: item.category })
782
+ ] }),
783
+ /* @__PURE__ */ jsxs("div", { className: "item-stock", children: [
784
+ /* @__PURE__ */ jsx(
785
+ "span",
786
+ {
787
+ className: "status-badge",
788
+ style: { backgroundColor: getStatusColor(item.status) },
789
+ children: item.status.replace("-", " ")
790
+ }
791
+ ),
792
+ /* @__PURE__ */ jsxs("span", { className: "quantity", children: [
793
+ item.quantity,
794
+ " ",
795
+ item.unit
796
+ ] }),
797
+ item.quantity <= item.reorderLevel && /* @__PURE__ */ jsx("span", { className: "reorder-alert", children: "⚠️ Low Stock" })
798
+ ] }),
799
+ /* @__PURE__ */ jsx("div", { className: "item-value", children: formatCurrency(item.quantity * item.cost.amount, item.cost.currency.symbol) })
800
+ ]
801
+ },
802
+ item.id
803
+ );
804
+ }) }),
805
+ view === "list" && /* @__PURE__ */ jsx("div", { className: "items-table", children: /* @__PURE__ */ jsxs("table", { children: [
806
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
807
+ !readOnly && /* @__PURE__ */ jsx("th", {}),
808
+ /* @__PURE__ */ jsxs(
809
+ "th",
810
+ {
811
+ onClick: () => {
812
+ setSortBy("sku");
813
+ setSortOrder((prev) => prev === "asc" ? "desc" : "asc");
814
+ },
815
+ children: [
816
+ "SKU ",
817
+ sortBy === "sku" && (sortOrder === "asc" ? "↑" : "↓")
818
+ ]
819
+ }
820
+ ),
821
+ /* @__PURE__ */ jsxs(
822
+ "th",
823
+ {
824
+ onClick: () => {
825
+ setSortBy("name");
826
+ setSortOrder((prev) => prev === "asc" ? "desc" : "asc");
827
+ },
828
+ children: [
829
+ "Name ",
830
+ sortBy === "name" && (sortOrder === "asc" ? "↑" : "↓")
831
+ ]
832
+ }
833
+ ),
834
+ /* @__PURE__ */ jsx("th", { children: "Category" }),
835
+ /* @__PURE__ */ jsxs(
836
+ "th",
837
+ {
838
+ onClick: () => {
839
+ setSortBy("quantity");
840
+ setSortOrder((prev) => prev === "asc" ? "desc" : "asc");
841
+ },
842
+ children: [
843
+ "Qty ",
844
+ sortBy === "quantity" && (sortOrder === "asc" ? "↑" : "↓")
845
+ ]
846
+ }
847
+ ),
848
+ /* @__PURE__ */ jsx("th", { children: "Status" }),
849
+ /* @__PURE__ */ jsx("th", { children: "Location" }),
850
+ /* @__PURE__ */ jsxs(
851
+ "th",
852
+ {
853
+ onClick: () => {
854
+ setSortBy("value");
855
+ setSortOrder((prev) => prev === "asc" ? "desc" : "asc");
856
+ },
857
+ children: [
858
+ "Value ",
859
+ sortBy === "value" && (sortOrder === "asc" ? "↑" : "↓")
860
+ ]
861
+ }
862
+ ),
863
+ !readOnly && /* @__PURE__ */ jsx("th", { children: "Actions" })
864
+ ] }) }),
865
+ /* @__PURE__ */ jsx("tbody", { children: paginatedItems.map((item) => /* @__PURE__ */ jsxs(
866
+ "tr",
867
+ {
868
+ className: selectedItems.has(item.id) ? "row--selected" : "",
869
+ onClick: () => onItemClick == null ? void 0 : onItemClick(item),
870
+ children: [
871
+ !readOnly && /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(
872
+ "input",
873
+ {
874
+ type: "checkbox",
875
+ checked: selectedItems.has(item.id),
876
+ onChange: () => toggleItemSelection(item.id),
877
+ onClick: (e) => e.stopPropagation()
878
+ }
879
+ ) }),
880
+ /* @__PURE__ */ jsx("td", { className: "sku-cell", children: item.sku }),
881
+ /* @__PURE__ */ jsx("td", { children: item.name }),
882
+ /* @__PURE__ */ jsx("td", { children: item.category }),
883
+ /* @__PURE__ */ jsxs("td", { className: item.quantity <= item.reorderLevel ? "low-stock" : "", children: [
884
+ item.quantity,
885
+ " ",
886
+ item.unit
887
+ ] }),
888
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(
889
+ "span",
890
+ {
891
+ className: "status-badge",
892
+ style: { backgroundColor: getStatusColor(item.status) },
893
+ children: item.status.replace("-", " ")
894
+ }
895
+ ) }),
896
+ /* @__PURE__ */ jsx("td", { children: item.location ? `${item.location.warehouseName}${item.location.aisle ? ` / ${item.location.aisle}` : ""}` : "-" }),
897
+ /* @__PURE__ */ jsx("td", { children: formatCurrency(
898
+ item.quantity * item.cost.amount,
899
+ item.cost.currency.symbol
900
+ ) }),
901
+ !readOnly && /* @__PURE__ */ jsxs("td", { className: "actions-cell", children: [
902
+ /* @__PURE__ */ jsx(
903
+ "button",
904
+ {
905
+ className: "action-btn",
906
+ onClick: (e) => {
907
+ e.stopPropagation();
908
+ setEditingItem(item);
909
+ setShowItemModal(true);
910
+ },
911
+ children: "✏️"
912
+ }
913
+ ),
914
+ /* @__PURE__ */ jsx(
915
+ "button",
916
+ {
917
+ className: "action-btn",
918
+ onClick: (e) => {
919
+ e.stopPropagation();
920
+ setNewTransaction({ itemId: item.id });
921
+ setShowTransactionModal(true);
922
+ },
923
+ children: "📝"
924
+ }
925
+ ),
926
+ /* @__PURE__ */ jsx(
927
+ "button",
928
+ {
929
+ className: "action-btn action-btn--danger",
930
+ onClick: (e) => {
931
+ e.stopPropagation();
932
+ onItemDelete == null ? void 0 : onItemDelete(item.id);
933
+ },
934
+ children: "🗑️"
935
+ }
936
+ )
937
+ ] })
938
+ ]
939
+ },
940
+ item.id
941
+ )) })
942
+ ] }) }),
943
+ view === "kanban" && kanbanGroups && /* @__PURE__ */ jsx("div", { className: "items-kanban", children: Array.from(kanbanGroups.entries()).map(([status, statusItems]) => /* @__PURE__ */ jsxs("div", { className: "kanban-column", children: [
944
+ /* @__PURE__ */ jsxs("div", { className: "column-header", style: { borderColor: getStatusColor(status) }, children: [
945
+ /* @__PURE__ */ jsx(
946
+ "span",
947
+ {
948
+ className: "status-dot",
949
+ style: { backgroundColor: getStatusColor(status) }
950
+ }
951
+ ),
952
+ /* @__PURE__ */ jsx("span", { className: "column-title", children: status.replace("-", " ") }),
953
+ /* @__PURE__ */ jsx("span", { className: "column-count", children: statusItems.length })
954
+ ] }),
955
+ /* @__PURE__ */ jsx("div", { className: "column-items", children: statusItems.map((item) => /* @__PURE__ */ jsxs(
956
+ "div",
957
+ {
958
+ className: "kanban-card",
959
+ onClick: () => onItemClick == null ? void 0 : onItemClick(item),
960
+ children: [
961
+ /* @__PURE__ */ jsx("span", { className: "card-sku", children: item.sku }),
962
+ /* @__PURE__ */ jsx("span", { className: "card-name", children: item.name }),
963
+ /* @__PURE__ */ jsxs("span", { className: "card-qty", children: [
964
+ item.quantity,
965
+ " ",
966
+ item.unit
967
+ ] })
968
+ ]
969
+ },
970
+ item.id
971
+ )) })
972
+ ] }, status)) }),
973
+ totalPages > 1 && /* @__PURE__ */ jsxs("div", { className: "pagination", children: [
974
+ /* @__PURE__ */ jsx("button", { disabled: page === 1, onClick: () => setPage((p) => p - 1), children: "Previous" }),
975
+ /* @__PURE__ */ jsxs("span", { children: [
976
+ "Page ",
977
+ page,
978
+ " of ",
979
+ totalPages
980
+ ] }),
981
+ /* @__PURE__ */ jsx("button", { disabled: page === totalPages, onClick: () => setPage((p) => p + 1), children: "Next" })
982
+ ] })
983
+ ] }),
984
+ activeTab === "transactions" && /* @__PURE__ */ jsxs("div", { className: "transactions-tab", children: [
985
+ !readOnly && /* @__PURE__ */ jsx(
986
+ "button",
987
+ {
988
+ className: "add-transaction-button",
989
+ onClick: () => setShowTransactionModal(true),
990
+ children: "+ New Transaction"
991
+ }
992
+ ),
993
+ /* @__PURE__ */ jsx("div", { className: "transactions-list", children: recentTransactions.map((tx) => {
994
+ const item = items.find((i) => i.id === tx.itemId);
995
+ return /* @__PURE__ */ jsxs("div", { className: "transaction-item", children: [
996
+ /* @__PURE__ */ jsx("span", { className: "tx-icon", children: getTransactionIcon(tx.type) }),
997
+ /* @__PURE__ */ jsxs("div", { className: "tx-info", children: [
998
+ /* @__PURE__ */ jsx("span", { className: "tx-type", children: tx.type }),
999
+ /* @__PURE__ */ jsx("span", { className: "tx-item", children: (item == null ? void 0 : item.name) || tx.itemId })
1000
+ ] }),
1001
+ /* @__PURE__ */ jsxs(
1002
+ "span",
1003
+ {
1004
+ className: `tx-qty ${tx.type === "receipt" || tx.type === "return" ? "positive" : "negative"}`,
1005
+ children: [
1006
+ tx.type === "receipt" || tx.type === "return" ? "+" : "-",
1007
+ tx.quantity
1008
+ ]
1009
+ }
1010
+ ),
1011
+ /* @__PURE__ */ jsx("span", { className: "tx-date", children: tx.date.toLocaleString() }),
1012
+ tx.reference && /* @__PURE__ */ jsxs("span", { className: "tx-ref", children: [
1013
+ "Ref: ",
1014
+ tx.reference
1015
+ ] })
1016
+ ] }, tx.id);
1017
+ }) })
1018
+ ] }),
1019
+ activeTab === "reorder" && /* @__PURE__ */ jsx("div", { className: "reorder-tab", children: reorderItems.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "empty-state", children: [
1020
+ /* @__PURE__ */ jsx("span", { className: "empty-icon", children: "✅" }),
1021
+ /* @__PURE__ */ jsx("p", { children: "All items are sufficiently stocked" })
1022
+ ] }) : /* @__PURE__ */ jsx("div", { className: "reorder-list", children: reorderItems.map((item) => /* @__PURE__ */ jsxs("div", { className: "reorder-item", children: [
1023
+ /* @__PURE__ */ jsxs("div", { className: "reorder-info", children: [
1024
+ /* @__PURE__ */ jsx("span", { className: "reorder-sku", children: item.sku }),
1025
+ /* @__PURE__ */ jsx("span", { className: "reorder-name", children: item.name })
1026
+ ] }),
1027
+ /* @__PURE__ */ jsxs("div", { className: "reorder-stock", children: [
1028
+ /* @__PURE__ */ jsxs("span", { className: "current-qty", children: [
1029
+ "Current: ",
1030
+ item.quantity,
1031
+ " ",
1032
+ item.unit
1033
+ ] }),
1034
+ /* @__PURE__ */ jsxs("span", { className: "reorder-level", children: [
1035
+ "Reorder at: ",
1036
+ item.reorderLevel
1037
+ ] }),
1038
+ /* @__PURE__ */ jsxs("span", { className: "reorder-qty", children: [
1039
+ "Order qty: ",
1040
+ item.reorderQuantity
1041
+ ] })
1042
+ ] }),
1043
+ item.supplier && /* @__PURE__ */ jsx("span", { className: "supplier-name", children: item.supplier.name }),
1044
+ !readOnly && /* @__PURE__ */ jsx(
1045
+ "button",
1046
+ {
1047
+ className: "create-po-button",
1048
+ onClick: () => console.log("Create PO for", item.id),
1049
+ children: "Create PO"
1050
+ }
1051
+ )
1052
+ ] }, item.id)) }) })
1053
+ ] }),
1054
+ showItemModal && editingItem && /* @__PURE__ */ jsx("div", { className: "modal-overlay", onClick: () => setShowItemModal(false), children: /* @__PURE__ */ jsxs("div", { className: "item-modal", onClick: (e) => e.stopPropagation(), children: [
1055
+ /* @__PURE__ */ jsx("h3", { children: editingItem.id ? "Edit Item" : "Add New Item" }),
1056
+ /* @__PURE__ */ jsxs("div", { className: "modal-form", children: [
1057
+ /* @__PURE__ */ jsxs("div", { className: "form-row", children: [
1058
+ /* @__PURE__ */ jsxs("label", { children: [
1059
+ "SKU",
1060
+ /* @__PURE__ */ jsx(
1061
+ "input",
1062
+ {
1063
+ type: "text",
1064
+ value: editingItem.sku || "",
1065
+ onChange: (e) => setEditingItem((prev) => ({ ...prev, sku: e.target.value }))
1066
+ }
1067
+ )
1068
+ ] }),
1069
+ /* @__PURE__ */ jsxs("label", { children: [
1070
+ "Name",
1071
+ /* @__PURE__ */ jsx(
1072
+ "input",
1073
+ {
1074
+ type: "text",
1075
+ value: editingItem.name || "",
1076
+ onChange: (e) => setEditingItem((prev) => ({ ...prev, name: e.target.value }))
1077
+ }
1078
+ )
1079
+ ] })
1080
+ ] }),
1081
+ /* @__PURE__ */ jsxs("label", { children: [
1082
+ "Description",
1083
+ /* @__PURE__ */ jsx(
1084
+ "textarea",
1085
+ {
1086
+ value: editingItem.description || "",
1087
+ onChange: (e) => setEditingItem((prev) => ({ ...prev, description: e.target.value }))
1088
+ }
1089
+ )
1090
+ ] }),
1091
+ /* @__PURE__ */ jsxs("div", { className: "form-row", children: [
1092
+ /* @__PURE__ */ jsxs("label", { children: [
1093
+ "Category",
1094
+ /* @__PURE__ */ jsx(
1095
+ "input",
1096
+ {
1097
+ type: "text",
1098
+ value: editingItem.category || "",
1099
+ onChange: (e) => setEditingItem((prev) => ({ ...prev, category: e.target.value })),
1100
+ list: "categories"
1101
+ }
1102
+ ),
1103
+ /* @__PURE__ */ jsx("datalist", { id: "categories", children: categories.map((c) => /* @__PURE__ */ jsx("option", { value: c }, c)) })
1104
+ ] }),
1105
+ /* @__PURE__ */ jsxs("label", { children: [
1106
+ "Unit",
1107
+ /* @__PURE__ */ jsx(
1108
+ "input",
1109
+ {
1110
+ type: "text",
1111
+ value: editingItem.unit || "",
1112
+ onChange: (e) => setEditingItem((prev) => ({ ...prev, unit: e.target.value }))
1113
+ }
1114
+ )
1115
+ ] })
1116
+ ] }),
1117
+ /* @__PURE__ */ jsxs("div", { className: "form-row", children: [
1118
+ /* @__PURE__ */ jsxs("label", { children: [
1119
+ "Quantity",
1120
+ /* @__PURE__ */ jsx(
1121
+ "input",
1122
+ {
1123
+ type: "number",
1124
+ value: editingItem.quantity || 0,
1125
+ onChange: (e) => setEditingItem((prev) => ({ ...prev, quantity: parseInt(e.target.value) }))
1126
+ }
1127
+ )
1128
+ ] }),
1129
+ /* @__PURE__ */ jsxs("label", { children: [
1130
+ "Reorder Level",
1131
+ /* @__PURE__ */ jsx(
1132
+ "input",
1133
+ {
1134
+ type: "number",
1135
+ value: editingItem.reorderLevel || 0,
1136
+ onChange: (e) => setEditingItem((prev) => ({
1137
+ ...prev,
1138
+ reorderLevel: parseInt(e.target.value)
1139
+ }))
1140
+ }
1141
+ )
1142
+ ] }),
1143
+ /* @__PURE__ */ jsxs("label", { children: [
1144
+ "Reorder Qty",
1145
+ /* @__PURE__ */ jsx(
1146
+ "input",
1147
+ {
1148
+ type: "number",
1149
+ value: editingItem.reorderQuantity || 0,
1150
+ onChange: (e) => setEditingItem((prev) => ({
1151
+ ...prev,
1152
+ reorderQuantity: parseInt(e.target.value)
1153
+ }))
1154
+ }
1155
+ )
1156
+ ] })
1157
+ ] }),
1158
+ /* @__PURE__ */ jsxs("label", { children: [
1159
+ "Unit Cost",
1160
+ /* @__PURE__ */ jsx(
1161
+ "input",
1162
+ {
1163
+ type: "number",
1164
+ step: "0.01",
1165
+ value: ((_b = editingItem.cost) == null ? void 0 : _b.amount) || 0,
1166
+ onChange: (e) => setEditingItem((prev) => ({
1167
+ ...prev,
1168
+ cost: {
1169
+ ...prev.cost,
1170
+ amount: parseFloat(e.target.value)
1171
+ }
1172
+ }))
1173
+ }
1174
+ )
1175
+ ] })
1176
+ ] }),
1177
+ /* @__PURE__ */ jsxs("div", { className: "modal-actions", children: [
1178
+ /* @__PURE__ */ jsx("button", { className: "cancel-button", onClick: () => setShowItemModal(false), children: "Cancel" }),
1179
+ /* @__PURE__ */ jsx("button", { className: "save-button", onClick: handleItemSubmit, children: editingItem.id ? "Save Changes" : "Create Item" })
1180
+ ] })
1181
+ ] }) }),
1182
+ showTransactionModal && /* @__PURE__ */ jsx("div", { className: "modal-overlay", onClick: () => setShowTransactionModal(false), children: /* @__PURE__ */ jsxs("div", { className: "transaction-modal", onClick: (e) => e.stopPropagation(), children: [
1183
+ /* @__PURE__ */ jsx("h3", { children: "Create Transaction" }),
1184
+ /* @__PURE__ */ jsxs("div", { className: "modal-form", children: [
1185
+ /* @__PURE__ */ jsxs("label", { children: [
1186
+ "Item",
1187
+ /* @__PURE__ */ jsxs(
1188
+ "select",
1189
+ {
1190
+ value: newTransaction.itemId || "",
1191
+ onChange: (e) => setNewTransaction((prev) => ({ ...prev, itemId: e.target.value })),
1192
+ children: [
1193
+ /* @__PURE__ */ jsx("option", { value: "", children: "Select item..." }),
1194
+ items.map((item) => /* @__PURE__ */ jsxs("option", { value: item.id, children: [
1195
+ item.sku,
1196
+ " - ",
1197
+ item.name
1198
+ ] }, item.id))
1199
+ ]
1200
+ }
1201
+ )
1202
+ ] }),
1203
+ /* @__PURE__ */ jsxs("label", { children: [
1204
+ "Type",
1205
+ /* @__PURE__ */ jsxs(
1206
+ "select",
1207
+ {
1208
+ value: newTransaction.type || "",
1209
+ onChange: (e) => setNewTransaction((prev) => ({
1210
+ ...prev,
1211
+ type: e.target.value
1212
+ })),
1213
+ children: [
1214
+ /* @__PURE__ */ jsx("option", { value: "", children: "Select type..." }),
1215
+ /* @__PURE__ */ jsx("option", { value: "receipt", children: "Receipt" }),
1216
+ /* @__PURE__ */ jsx("option", { value: "issue", children: "Issue" }),
1217
+ /* @__PURE__ */ jsx("option", { value: "transfer", children: "Transfer" }),
1218
+ /* @__PURE__ */ jsx("option", { value: "adjustment", children: "Adjustment" }),
1219
+ /* @__PURE__ */ jsx("option", { value: "return", children: "Return" }),
1220
+ /* @__PURE__ */ jsx("option", { value: "write-off", children: "Write-off" })
1221
+ ]
1222
+ }
1223
+ )
1224
+ ] }),
1225
+ /* @__PURE__ */ jsxs("label", { children: [
1226
+ "Quantity",
1227
+ /* @__PURE__ */ jsx(
1228
+ "input",
1229
+ {
1230
+ type: "number",
1231
+ min: "1",
1232
+ value: newTransaction.quantity || "",
1233
+ onChange: (e) => setNewTransaction((prev) => ({ ...prev, quantity: parseInt(e.target.value) }))
1234
+ }
1235
+ )
1236
+ ] }),
1237
+ /* @__PURE__ */ jsxs("label", { children: [
1238
+ "Reference",
1239
+ /* @__PURE__ */ jsx(
1240
+ "input",
1241
+ {
1242
+ type: "text",
1243
+ value: newTransaction.reference || "",
1244
+ onChange: (e) => setNewTransaction((prev) => ({ ...prev, reference: e.target.value })),
1245
+ placeholder: "PO number, invoice, etc."
1246
+ }
1247
+ )
1248
+ ] }),
1249
+ /* @__PURE__ */ jsxs("label", { children: [
1250
+ "Notes",
1251
+ /* @__PURE__ */ jsx(
1252
+ "textarea",
1253
+ {
1254
+ value: newTransaction.notes || "",
1255
+ onChange: (e) => setNewTransaction((prev) => ({ ...prev, notes: e.target.value }))
1256
+ }
1257
+ )
1258
+ ] })
1259
+ ] }),
1260
+ /* @__PURE__ */ jsxs("div", { className: "modal-actions", children: [
1261
+ /* @__PURE__ */ jsx("button", { className: "cancel-button", onClick: () => setShowTransactionModal(false), children: "Cancel" }),
1262
+ /* @__PURE__ */ jsx("button", { className: "save-button", onClick: handleTransactionSubmit, children: "Create Transaction" })
1263
+ ] })
1264
+ ] }) })
1265
+ ] });
1266
+ };
1267
+ export {
1268
+ NiceInventoryManager,
1269
+ NiceResourceAllocation
1270
+ };
1271
+ //# sourceMappingURL=index.mjs.map