@nice2dev/ui-erp 1.0.11 → 1.0.14

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.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
- const react = require("react");
4
+ const React = require("react");
5
5
  const DEFAULT_VIEW_CONFIG$1 = {
6
6
  timeUnit: "day",
7
7
  showUtilization: true,
@@ -31,15 +31,15 @@ const NiceResourceAllocation = ({
31
31
  }) => {
32
32
  var _a, _b;
33
33
  const config = { ...DEFAULT_VIEW_CONFIG$1, ...externalConfig };
34
- const [selectedAllocation, setSelectedAllocation] = react.useState(null);
35
- const [hoveredCell, setHoveredCell] = react.useState(null);
36
- const [timeUnit, setTimeUnit] = react.useState(config.timeUnit);
37
- const [expandedResources, setExpandedResources] = react.useState(
34
+ const [selectedAllocation, setSelectedAllocation] = React.useState(null);
35
+ const [hoveredCell, setHoveredCell] = React.useState(null);
36
+ const [timeUnit, setTimeUnit] = React.useState(config.timeUnit);
37
+ const [expandedResources, setExpandedResources] = React.useState(
38
38
  new Set(resources.map((r) => r.id))
39
39
  );
40
- const [showAllocationModal, setShowAllocationModal] = react.useState(false);
41
- const [newAllocation, setNewAllocation] = react.useState({});
42
- const timePeriods = react.useMemo(() => {
40
+ const [showAllocationModal, setShowAllocationModal] = React.useState(false);
41
+ const [newAllocation, setNewAllocation] = React.useState({});
42
+ const timePeriods = React.useMemo(() => {
43
43
  const periods = [];
44
44
  const increment = TIME_INCREMENTS[timeUnit];
45
45
  let current = new Date(dateRange.start);
@@ -49,7 +49,7 @@ const NiceResourceAllocation = ({
49
49
  }
50
50
  return periods;
51
51
  }, [dateRange.start, dateRange.end, timeUnit]);
52
- const utilizationMap = react.useMemo(() => {
52
+ const utilizationMap = React.useMemo(() => {
53
53
  const map = /* @__PURE__ */ new Map();
54
54
  resources.forEach((resource) => {
55
55
  const resourceMap = /* @__PURE__ */ new Map();
@@ -80,7 +80,7 @@ const NiceResourceAllocation = ({
80
80
  });
81
81
  return map;
82
82
  }, [resources, allocations, timePeriods, timeUnit]);
83
- const conflicts = react.useMemo(() => {
83
+ const conflicts = React.useMemo(() => {
84
84
  const conflictList = [];
85
85
  utilizationMap.forEach((resourceMap, resourceId) => {
86
86
  const resource = resources.find((r) => r.id === resourceId);
@@ -108,7 +108,7 @@ const NiceResourceAllocation = ({
108
108
  });
109
109
  return conflictList;
110
110
  }, [utilizationMap, allocations, resources, timeUnit]);
111
- const getCellAllocations = react.useCallback(
111
+ const getCellAllocations = React.useCallback(
112
112
  (resourceId, date) => {
113
113
  const periodStart = date.getTime();
114
114
  const periodEnd = periodStart + TIME_INCREMENTS[timeUnit];
@@ -130,13 +130,13 @@ const NiceResourceAllocation = ({
130
130
  return "transparent";
131
131
  }
132
132
  if (util.overallocated) {
133
- return "rgba(239, 68, 68, 0.4)";
133
+ return "var(--nice-danger-tint-40, rgba(239, 68, 68, 0.4))";
134
134
  }
135
135
  if (util.utilizationPercent >= config.utilizationThreshold) {
136
- return "rgba(245, 158, 11, 0.3)";
136
+ return "var(--nice-warning-tint-30, rgba(245, 158, 11, 0.3))";
137
137
  }
138
138
  if (util.utilizationPercent > 0) {
139
- return "rgba(34, 197, 94, 0.2)";
139
+ return "var(--nice-success-tint-20, rgba(34, 197, 94, 0.2))";
140
140
  }
141
141
  return "transparent";
142
142
  };
@@ -237,11 +237,11 @@ const NiceResourceAllocation = ({
237
237
  ] }),
238
238
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "allocation__legend", children: [
239
239
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "legend-item", children: [
240
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "legend-color", style: { backgroundColor: "rgba(34, 197, 94, 0.2)" } }),
240
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "legend-color", style: { backgroundColor: "var(--nice-success-tint-20, rgba(34, 197, 94, 0.2))" } }),
241
241
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Allocated" })
242
242
  ] }),
243
243
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "legend-item", children: [
244
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "legend-color", style: { backgroundColor: "rgba(245, 158, 11, 0.3)" } }),
244
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "legend-color", style: { backgroundColor: "var(--nice-warning-tint-30, rgba(245, 158, 11, 0.3))" } }),
245
245
  /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
246
246
  "High Utilization (",
247
247
  ">",
@@ -251,7 +251,7 @@ const NiceResourceAllocation = ({
251
251
  ] })
252
252
  ] }),
253
253
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "legend-item", children: [
254
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "legend-color", style: { backgroundColor: "rgba(239, 68, 68, 0.4)" } }),
254
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "legend-color", style: { backgroundColor: "var(--nice-danger-tint-40, rgba(239, 68, 68, 0.4))" } }),
255
255
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Overallocated" })
256
256
  ] })
257
257
  ] }),
@@ -482,21 +482,21 @@ const NiceInventoryManager = ({
482
482
  }) => {
483
483
  var _a, _b;
484
484
  const config = { ...DEFAULT_VIEW_CONFIG, ...externalConfig };
485
- const [filters, setFilters] = react.useState({});
486
- const [view, setView] = react.useState(config.view);
487
- const [sortBy, setSortBy] = react.useState(config.sortBy);
488
- const [sortOrder, setSortOrder] = react.useState(config.sortOrder);
489
- const [page, setPage] = react.useState(1);
490
- const [selectedItems, setSelectedItems] = react.useState(/* @__PURE__ */ new Set());
491
- const [showItemModal, setShowItemModal] = react.useState(false);
492
- const [showTransactionModal, setShowTransactionModal] = react.useState(false);
493
- const [editingItem, setEditingItem] = react.useState(null);
494
- const [newTransaction, setNewTransaction] = react.useState({});
495
- const [activeTab, setActiveTab] = react.useState("inventory");
496
- const categories = react.useMemo(() => {
485
+ const [filters, setFilters] = React.useState({});
486
+ const [view, setView] = React.useState(config.view);
487
+ const [sortBy, setSortBy] = React.useState(config.sortBy);
488
+ const [sortOrder, setSortOrder] = React.useState(config.sortOrder);
489
+ const [page, setPage] = React.useState(1);
490
+ const [selectedItems, setSelectedItems] = React.useState(/* @__PURE__ */ new Set());
491
+ const [showItemModal, setShowItemModal] = React.useState(false);
492
+ const [showTransactionModal, setShowTransactionModal] = React.useState(false);
493
+ const [editingItem, setEditingItem] = React.useState(null);
494
+ const [newTransaction, setNewTransaction] = React.useState({});
495
+ const [activeTab, setActiveTab] = React.useState("inventory");
496
+ const categories = React.useMemo(() => {
497
497
  return Array.from(new Set(items.map((item) => item.category))).sort();
498
498
  }, [items]);
499
- const filteredItems = react.useMemo(() => {
499
+ const filteredItems = React.useMemo(() => {
500
500
  var _a2, _b2;
501
501
  let result = [...items];
502
502
  if (filters.searchQuery) {
@@ -541,18 +541,18 @@ const NiceInventoryManager = ({
541
541
  });
542
542
  return result;
543
543
  }, [items, filters, sortBy, sortOrder]);
544
- const paginatedItems = react.useMemo(() => {
544
+ const paginatedItems = React.useMemo(() => {
545
545
  const start = (page - 1) * config.pageSize;
546
546
  return filteredItems.slice(start, start + config.pageSize);
547
547
  }, [filteredItems, page, config.pageSize]);
548
548
  const totalPages = Math.ceil(filteredItems.length / config.pageSize);
549
- const reorderItems = react.useMemo(() => {
549
+ const reorderItems = React.useMemo(() => {
550
550
  return items.filter((item) => item.quantity <= item.reorderLevel);
551
551
  }, [items]);
552
- const recentTransactions = react.useMemo(() => {
552
+ const recentTransactions = React.useMemo(() => {
553
553
  return [...transactions].sort((a, b) => b.date.getTime() - a.date.getTime()).slice(0, 50);
554
554
  }, [transactions]);
555
- const kanbanGroups = react.useMemo(() => {
555
+ const kanbanGroups = React.useMemo(() => {
556
556
  if (view !== "kanban") {
557
557
  return null;
558
558
  }
@@ -574,17 +574,17 @@ const NiceInventoryManager = ({
574
574
  const getStatusColor = (status) => {
575
575
  switch (status) {
576
576
  case "in-stock":
577
- return "#22c55e";
577
+ return "var(--nice-success, #22c55e)";
578
578
  case "low-stock":
579
- return "#f59e0b";
579
+ return "var(--nice-warning, #f59e0b)";
580
580
  case "out-of-stock":
581
- return "#ef4444";
581
+ return "var(--nice-danger, #ef4444)";
582
582
  case "on-order":
583
- return "#3b82f6";
583
+ return "var(--nice-primary, #3b82f6)";
584
584
  case "discontinued":
585
- return "#6b7280";
585
+ return "var(--nice-text-secondary, #6b7280)";
586
586
  default:
587
- return "#6b7280";
587
+ return "var(--nice-text-secondary, #6b7280)";
588
588
  }
589
589
  };
590
590
  const getTransactionIcon = (type) => {
@@ -1266,6 +1266,888 @@ const NiceInventoryManager = ({
1266
1266
  ] }) })
1267
1267
  ] });
1268
1268
  };
1269
+ const STATUS_COLOR = {
1270
+ draft: "var(--nice-color-muted, #6b7280)",
1271
+ issued: "var(--nice-color-info, #2563eb)",
1272
+ sent: "var(--nice-color-info, #2563eb)",
1273
+ paid: "var(--nice-color-success, #16a34a)",
1274
+ "partially-paid": "var(--nice-color-warning, #ca8a04)",
1275
+ overdue: "var(--nice-color-danger, #dc2626)",
1276
+ cancelled: "var(--nice-color-muted, #6b7280)"
1277
+ };
1278
+ function lineNet(line) {
1279
+ const gross = line.quantity * line.unitPrice.amount;
1280
+ const discounted = line.discount ? gross * (1 - line.discount) : gross;
1281
+ return Math.round(discounted);
1282
+ }
1283
+ function lineVat(line) {
1284
+ return Math.round(lineNet(line) * line.vatRate);
1285
+ }
1286
+ function fmtMoney$1(amount, currency, locale) {
1287
+ const code = typeof currency === "string" ? currency : currency.code;
1288
+ const decimals = typeof currency === "string" ? 2 : currency.decimalPlaces ?? 2;
1289
+ return new Intl.NumberFormat(locale, { style: "currency", currency: code }).format(amount / Math.pow(10, decimals));
1290
+ }
1291
+ function fmtDate$1(d, locale) {
1292
+ const dt = d instanceof Date ? d : new Date(d);
1293
+ return new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(dt);
1294
+ }
1295
+ const NiceInvoiceView = React.forwardRef(
1296
+ function NiceInvoiceView2({ invoice, locale, currency, hideSections, labels, onAction, showActions = false, density = "comfortable", className, style, id }, ref) {
1297
+ var _a;
1298
+ const cur = currency ?? invoice.currency ?? ((_a = invoice.lines[0]) == null ? void 0 : _a.unitPrice.currency) ?? "EUR";
1299
+ const L = {
1300
+ invoiceNumber: "Invoice",
1301
+ issueDate: "Issue date",
1302
+ dueDate: "Due date",
1303
+ seller: "Seller",
1304
+ buyer: "Buyer",
1305
+ description: "Description",
1306
+ qty: "Qty",
1307
+ unitPrice: "Unit price",
1308
+ vat: "VAT",
1309
+ net: "Net",
1310
+ gross: "Gross",
1311
+ subtotal: "Subtotal",
1312
+ vatTotal: "VAT total",
1313
+ total: "Total",
1314
+ vatBreakdown: "VAT breakdown",
1315
+ timeline: "History",
1316
+ notes: "Notes",
1317
+ vatId: "VAT ID",
1318
+ ...labels
1319
+ };
1320
+ const totals = React.useMemo(() => {
1321
+ let net = 0;
1322
+ let vat = 0;
1323
+ const byRate = /* @__PURE__ */ new Map();
1324
+ for (const ln of invoice.lines) {
1325
+ const n = lineNet(ln);
1326
+ const v = lineVat(ln);
1327
+ net += n;
1328
+ vat += v;
1329
+ const cell = byRate.get(ln.vatRate) ?? { net: 0, vat: 0 };
1330
+ cell.net += n;
1331
+ cell.vat += v;
1332
+ byRate.set(ln.vatRate, cell);
1333
+ }
1334
+ return { net, vat, gross: net + vat, byRate };
1335
+ }, [invoice.lines]);
1336
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1337
+ "article",
1338
+ {
1339
+ ref,
1340
+ id,
1341
+ className: `nice-invoice-view nice-invoice-view--${density} ${className ?? ""}`,
1342
+ style,
1343
+ "aria-label": `${L.invoiceNumber} ${invoice.invoiceNumber}`,
1344
+ children: [
1345
+ !(hideSections == null ? void 0 : hideSections.header) && /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "nice-invoice-view__header", children: [
1346
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1347
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nice-invoice-view__title", children: [
1348
+ L.invoiceNumber,
1349
+ " ",
1350
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: invoice.invoiceNumber })
1351
+ ] }),
1352
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nice-invoice-view__dates", children: [
1353
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1354
+ L.issueDate,
1355
+ ": ",
1356
+ fmtDate$1(invoice.issueDate, locale)
1357
+ ] }),
1358
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1359
+ L.dueDate,
1360
+ ": ",
1361
+ fmtDate$1(invoice.dueDate, locale)
1362
+ ] })
1363
+ ] })
1364
+ ] }),
1365
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nice-invoice-view__status", style: { color: STATUS_COLOR[invoice.status] }, children: [
1366
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "●" }),
1367
+ " ",
1368
+ invoice.status
1369
+ ] }),
1370
+ showActions && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nice-invoice-view__actions", children: [
1371
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => onAction == null ? void 0 : onAction("download"), children: "↓" }),
1372
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => onAction == null ? void 0 : onAction("print"), children: "⎙" }),
1373
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => onAction == null ? void 0 : onAction("send"), children: "✉" })
1374
+ ] })
1375
+ ] }),
1376
+ !(hideSections == null ? void 0 : hideSections.header) && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "nice-invoice-view__parties", children: [
1377
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1378
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { children: L.seller }),
1379
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: invoice.seller.name }),
1380
+ invoice.seller.vatId && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1381
+ L.vatId,
1382
+ ": ",
1383
+ invoice.seller.vatId
1384
+ ] })
1385
+ ] }),
1386
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1387
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { children: L.buyer }),
1388
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: invoice.buyer.name }),
1389
+ invoice.buyer.vatId && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1390
+ L.vatId,
1391
+ ": ",
1392
+ invoice.buyer.vatId
1393
+ ] })
1394
+ ] })
1395
+ ] }),
1396
+ !(hideSections == null ? void 0 : hideSections.lines) && /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "nice-invoice-view__lines", children: [
1397
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1398
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.description }),
1399
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.qty }),
1400
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.unitPrice }),
1401
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.vat }),
1402
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.net }),
1403
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.gross })
1404
+ ] }) }),
1405
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: invoice.lines.map((ln) => {
1406
+ const n = lineNet(ln);
1407
+ const v = lineVat(ln);
1408
+ return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1409
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: ln.description }),
1410
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "nice-num", children: [
1411
+ ln.quantity,
1412
+ ln.unit ? ` ${ln.unit}` : ""
1413
+ ] }),
1414
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney$1(ln.unitPrice.amount, cur, locale) }),
1415
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "nice-num", children: [
1416
+ (ln.vatRate * 100).toFixed(0),
1417
+ "%"
1418
+ ] }),
1419
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney$1(n, cur, locale) }),
1420
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney$1(n + v, cur, locale) })
1421
+ ] }, ln.id);
1422
+ }) })
1423
+ ] }),
1424
+ !(hideSections == null ? void 0 : hideSections.vat) && totals.byRate.size > 0 && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "nice-invoice-view__vat", children: [
1425
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { children: L.vatBreakdown }),
1426
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { children: [
1427
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1428
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.vat }),
1429
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.net }),
1430
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.vat }),
1431
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.gross })
1432
+ ] }) }),
1433
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: [...totals.byRate.entries()].sort((a, b) => b[0] - a[0]).map(([rate, c]) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1434
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { children: [
1435
+ (rate * 100).toFixed(0),
1436
+ "%"
1437
+ ] }),
1438
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney$1(c.net, cur, locale) }),
1439
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney$1(c.vat, cur, locale) }),
1440
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney$1(c.net + c.vat, cur, locale) })
1441
+ ] }, rate)) })
1442
+ ] })
1443
+ ] }),
1444
+ !(hideSections == null ? void 0 : hideSections.totals) && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "nice-invoice-view__totals", "aria-label": L.total, children: [
1445
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1446
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: L.subtotal }),
1447
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: fmtMoney$1(totals.net, cur, locale) })
1448
+ ] }),
1449
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1450
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: L.vatTotal }),
1451
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: fmtMoney$1(totals.vat, cur, locale) })
1452
+ ] }),
1453
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nice-invoice-view__grand", children: [
1454
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: L.total }),
1455
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: fmtMoney$1(totals.gross, cur, locale) })
1456
+ ] })
1457
+ ] }),
1458
+ !(hideSections == null ? void 0 : hideSections.timeline) && invoice.history && invoice.history.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "nice-invoice-view__timeline", children: [
1459
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { children: L.timeline }),
1460
+ /* @__PURE__ */ jsxRuntime.jsx("ol", { children: invoice.history.map((h, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
1461
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nice-invoice-view__t-date", children: fmtDate$1(h.at, locale) }),
1462
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nice-invoice-view__t-status", style: { color: STATUS_COLOR[h.status] }, children: h.status }),
1463
+ h.note && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "nice-invoice-view__t-note", children: [
1464
+ " — ",
1465
+ h.note
1466
+ ] })
1467
+ ] }, i)) })
1468
+ ] }),
1469
+ !(hideSections == null ? void 0 : hideSections.notes) && invoice.notes && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "nice-invoice-view__notes", children: [
1470
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { children: L.notes }),
1471
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: invoice.notes })
1472
+ ] })
1473
+ ]
1474
+ }
1475
+ );
1476
+ }
1477
+ );
1478
+ function colorFor(occ, colors) {
1479
+ if (occ <= 0.01) {
1480
+ return colors.low;
1481
+ }
1482
+ if (occ < 0.5) {
1483
+ return colors.low;
1484
+ }
1485
+ if (occ < 0.85) {
1486
+ return colors.mid;
1487
+ }
1488
+ return colors.high;
1489
+ }
1490
+ const NiceWarehouseView = React.forwardRef(
1491
+ function NiceWarehouseView2({
1492
+ warehouseName,
1493
+ cells,
1494
+ colors = { low: "#dcfce7", mid: "#fde68a", high: "#fecaca" },
1495
+ onCellClick,
1496
+ showLegend = true,
1497
+ cellSize = 48,
1498
+ aisleEvery = 4,
1499
+ className,
1500
+ style,
1501
+ id
1502
+ }, ref) {
1503
+ const [hovered, setHovered] = React.useState(null);
1504
+ const grid = React.useMemo(() => {
1505
+ const rows = /* @__PURE__ */ new Map();
1506
+ for (const c of cells) {
1507
+ const rowKey = c.row !== void 0 ? `r${c.row}` : c.location.rack ?? c.location.aisle ?? "0";
1508
+ let arr = rows.get(rowKey);
1509
+ if (!arr) {
1510
+ arr = [];
1511
+ rows.set(rowKey, arr);
1512
+ }
1513
+ arr.push(c);
1514
+ }
1515
+ return [...rows.entries()].map(([rowKey, arr]) => ({ rowKey, cells: arr }));
1516
+ }, [cells]);
1517
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, id, className: `nice-warehouse-view ${className ?? ""}`, style, children: [
1518
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "nice-warehouse-view__header", children: [
1519
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: warehouseName }),
1520
+ showLegend && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nice-warehouse-view__legend", "aria-label": "Occupancy legend", children: [
1521
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { background: colors.low } }),
1522
+ " low",
1523
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { background: colors.mid } }),
1524
+ " mid",
1525
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { background: colors.high } }),
1526
+ " high"
1527
+ ] })
1528
+ ] }),
1529
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "nice-warehouse-view__grid", role: "grid", "aria-label": warehouseName, children: grid.map(({ rowKey, cells: row }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "nice-warehouse-view__row", role: "row", children: row.map((c, idx) => {
1530
+ const key = [c.location.rack, c.location.aisle, c.location.shelf, c.location.bin].filter(Boolean).join("-") || String(idx);
1531
+ const aisleBreak = aisleEvery > 0 && idx > 0 && idx % aisleEvery === 0;
1532
+ return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
1533
+ aisleBreak && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "nice-warehouse-view__aisle", "aria-hidden": true }),
1534
+ /* @__PURE__ */ jsxRuntime.jsx(
1535
+ "button",
1536
+ {
1537
+ type: "button",
1538
+ role: "gridcell",
1539
+ className: "nice-warehouse-view__cell",
1540
+ style: {
1541
+ width: cellSize,
1542
+ height: cellSize,
1543
+ background: colorFor(c.occupancy, colors)
1544
+ },
1545
+ title: `${key} — ${(c.occupancy * 100).toFixed(0)}% (${c.items.length} items)`,
1546
+ onClick: () => onCellClick == null ? void 0 : onCellClick(c),
1547
+ onMouseEnter: () => setHovered(c),
1548
+ onMouseLeave: () => setHovered(null),
1549
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nice-warehouse-view__bin", children: c.location.bin ?? c.location.shelf ?? "" })
1550
+ }
1551
+ )
1552
+ ] }, key);
1553
+ }) }, rowKey)) }),
1554
+ hovered && /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "nice-warehouse-view__details", "aria-live": "polite", children: [
1555
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
1556
+ hovered.location.rack,
1557
+ "/",
1558
+ hovered.location.shelf,
1559
+ "/",
1560
+ hovered.location.bin
1561
+ ] }),
1562
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1563
+ hovered.items.length,
1564
+ " items · ",
1565
+ (hovered.occupancy * 100).toFixed(0),
1566
+ "% full"
1567
+ ] }),
1568
+ /* @__PURE__ */ jsxRuntime.jsxs("ul", { children: [
1569
+ hovered.items.slice(0, 5).map((it) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
1570
+ it.sku,
1571
+ " — ",
1572
+ it.name
1573
+ ] }, it.id)),
1574
+ hovered.items.length > 5 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
1575
+ "…+",
1576
+ hovered.items.length - 5
1577
+ ] })
1578
+ ] })
1579
+ ] })
1580
+ ] });
1581
+ }
1582
+ );
1583
+ const STATUS_TINT = {
1584
+ draft: "#6b7280",
1585
+ "pending-approval": "#ca8a04",
1586
+ approved: "#2563eb",
1587
+ ordered: "#0891b2",
1588
+ "partially-received": "#9333ea",
1589
+ received: "#16a34a",
1590
+ cancelled: "#dc2626"
1591
+ };
1592
+ function fmtMoney(amount, currency, locale) {
1593
+ const code = typeof currency === "string" ? currency : currency.code;
1594
+ const decimals = typeof currency === "string" ? 2 : currency.decimalPlaces ?? 2;
1595
+ return new Intl.NumberFormat(locale, { style: "currency", currency: code }).format(
1596
+ amount / Math.pow(10, decimals)
1597
+ );
1598
+ }
1599
+ function fmtDate(d, locale) {
1600
+ if (!d) {
1601
+ return "—";
1602
+ }
1603
+ const dt = d instanceof Date ? d : new Date(d);
1604
+ return new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(dt);
1605
+ }
1606
+ const NicePurchaseOrder = React.forwardRef(
1607
+ function NicePurchaseOrder2({
1608
+ orders,
1609
+ selectable = true,
1610
+ initialSelectedId,
1611
+ locale,
1612
+ labels,
1613
+ readOnly,
1614
+ onOrderApprove,
1615
+ onReceiveItems,
1616
+ onOrderUpdate,
1617
+ className,
1618
+ style,
1619
+ id
1620
+ }, ref) {
1621
+ var _a;
1622
+ const [selectedId, setSelectedId] = React.useState(
1623
+ initialSelectedId ?? ((_a = orders[0]) == null ? void 0 : _a.id)
1624
+ );
1625
+ const L = {
1626
+ orderNumber: "PO #",
1627
+ supplier: "Supplier",
1628
+ status: "Status",
1629
+ orderDate: "Ordered",
1630
+ expected: "Expected",
1631
+ total: "Total",
1632
+ sku: "SKU",
1633
+ name: "Item",
1634
+ qty: "Qty",
1635
+ received: "Recv",
1636
+ unitPrice: "Unit",
1637
+ lineTotal: "Subtotal",
1638
+ notes: "Notes",
1639
+ approve: "Approve",
1640
+ receive: "Receive all",
1641
+ ...labels
1642
+ };
1643
+ const selected = React.useMemo(
1644
+ () => orders.find((o) => o.id === selectedId),
1645
+ [orders, selectedId]
1646
+ );
1647
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, id, className: `nice-purchase-order ${className ?? ""}`, style, children: [
1648
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "nice-purchase-order__list", children: [
1649
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1650
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.orderNumber }),
1651
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.supplier }),
1652
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.status }),
1653
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.orderDate }),
1654
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.expected }),
1655
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.total })
1656
+ ] }) }),
1657
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: orders.map((o) => /* @__PURE__ */ jsxRuntime.jsxs(
1658
+ "tr",
1659
+ {
1660
+ "aria-selected": o.id === selectedId,
1661
+ className: o.id === selectedId ? "is-selected" : void 0,
1662
+ onClick: () => selectable && setSelectedId(o.id),
1663
+ children: [
1664
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: o.orderNumber }),
1665
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: o.supplier.name }),
1666
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: STATUS_TINT[o.status] }, children: [
1667
+ "● ",
1668
+ o.status
1669
+ ] }) }),
1670
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: fmtDate(o.orderDate, locale) }),
1671
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: fmtDate(o.expectedDelivery, locale) }),
1672
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney(o.total.amount, o.total.currency, locale) })
1673
+ ]
1674
+ },
1675
+ o.id
1676
+ )) })
1677
+ ] }),
1678
+ selectable && selected && /* @__PURE__ */ jsxRuntime.jsxs(
1679
+ "section",
1680
+ {
1681
+ className: "nice-purchase-order__detail",
1682
+ "aria-label": `${L.orderNumber} ${selected.orderNumber}`,
1683
+ children: [
1684
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { children: [
1685
+ /* @__PURE__ */ jsxRuntime.jsxs("h3", { children: [
1686
+ selected.orderNumber,
1687
+ " — ",
1688
+ selected.supplier.name
1689
+ ] }),
1690
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nice-purchase-order__actions", children: [
1691
+ selected.status === "pending-approval" && onOrderApprove && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => onOrderApprove(selected.id), children: L.approve }),
1692
+ (selected.status === "ordered" || selected.status === "partially-received") && onReceiveItems && /* @__PURE__ */ jsxRuntime.jsx(
1693
+ "button",
1694
+ {
1695
+ type: "button",
1696
+ onClick: () => onReceiveItems(
1697
+ selected.id,
1698
+ selected.items.map((it) => ({
1699
+ itemId: it.itemId,
1700
+ quantity: it.quantity - (it.receivedQuantity ?? 0)
1701
+ }))
1702
+ ),
1703
+ children: L.receive
1704
+ }
1705
+ ),
1706
+ onOrderUpdate && selected.status === "draft" && /* @__PURE__ */ jsxRuntime.jsx(
1707
+ "button",
1708
+ {
1709
+ type: "button",
1710
+ onClick: () => onOrderUpdate({ ...selected, status: "pending-approval" }),
1711
+ children: "Submit"
1712
+ }
1713
+ )
1714
+ ] })
1715
+ ] }),
1716
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "nice-purchase-order__items", children: [
1717
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1718
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.sku }),
1719
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.name }),
1720
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.qty }),
1721
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.received }),
1722
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.unitPrice }),
1723
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.lineTotal })
1724
+ ] }) }),
1725
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: selected.items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1726
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: it.sku }),
1727
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: it.itemName }),
1728
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: it.quantity }),
1729
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: it.receivedQuantity ?? 0 }),
1730
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney(it.unitPrice.amount, it.unitPrice.currency, locale) }),
1731
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney(it.lineTotal.amount, it.lineTotal.currency, locale) })
1732
+ ] }, it.itemId)) }),
1733
+ /* @__PURE__ */ jsxRuntime.jsx("tfoot", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1734
+ /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: 5, className: "nice-num", children: L.total }),
1735
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: /* @__PURE__ */ jsxRuntime.jsx("strong", { children: fmtMoney(selected.total.amount, selected.total.currency, locale) }) })
1736
+ ] }) })
1737
+ ] }),
1738
+ selected.notes && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "nice-purchase-order__notes", children: [
1739
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
1740
+ L.notes,
1741
+ ":"
1742
+ ] }),
1743
+ " ",
1744
+ selected.notes
1745
+ ] })
1746
+ ]
1747
+ }
1748
+ )
1749
+ ] });
1750
+ }
1751
+ );
1752
+ const NiceHRDashboard = React.forwardRef(
1753
+ function NiceHRDashboard2({ employees, labels, hideWidgets, locale, density = "comfortable", onWidgetClick, className, style, id }, ref) {
1754
+ const L = {
1755
+ headcount: "Headcount",
1756
+ fte: "FTE",
1757
+ vacationBalance: "Avg vacation balance",
1758
+ sickLeave: "Avg sick days (YTD)",
1759
+ departments: "Departments",
1760
+ activeEmployees: "Active",
1761
+ ...labels
1762
+ };
1763
+ const stats = React.useMemo(() => {
1764
+ const active = employees.filter((e) => e.active !== false);
1765
+ const fte = active.reduce((s, e) => s + (e.fte ?? 1), 0);
1766
+ const vacationAvg = active.length === 0 ? 0 : active.reduce((s, e) => s + (e.vacationBalanceDays ?? 0), 0) / active.length;
1767
+ const sickAvg = active.length === 0 ? 0 : active.reduce((s, e) => s + (e.sickLeaveDaysYtd ?? 0), 0) / active.length;
1768
+ const byDepartment = /* @__PURE__ */ new Map();
1769
+ for (const e of active) {
1770
+ const k = e.department ?? "—";
1771
+ byDepartment.set(k, (byDepartment.get(k) ?? 0) + 1);
1772
+ }
1773
+ return { headcount: employees.length, active: active.length, fte, vacationAvg, sickAvg, byDepartment };
1774
+ }, [employees]);
1775
+ const fmt = (n, d = 1) => n.toLocaleString(locale, { maximumFractionDigits: d });
1776
+ const Widget = ({ kind, label, value, hint }) => /* @__PURE__ */ jsxRuntime.jsxs(
1777
+ "button",
1778
+ {
1779
+ type: "button",
1780
+ className: "nice-hr-dashboard__widget",
1781
+ onClick: () => onWidgetClick == null ? void 0 : onWidgetClick(kind),
1782
+ children: [
1783
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nice-hr-dashboard__label", children: label }),
1784
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nice-hr-dashboard__value", children: value }),
1785
+ hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nice-hr-dashboard__hint", children: hint })
1786
+ ]
1787
+ }
1788
+ );
1789
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, id, className: `nice-hr-dashboard nice-hr-dashboard--${density} ${className ?? ""}`, style, role: "group", "aria-label": "HR dashboard", children: [
1790
+ !(hideWidgets == null ? void 0 : hideWidgets.headcount) && /* @__PURE__ */ jsxRuntime.jsx(Widget, { kind: "headcount", label: L.headcount, value: fmt(stats.headcount, 0), hint: `${L.activeEmployees}: ${fmt(stats.active, 0)}` }),
1791
+ !(hideWidgets == null ? void 0 : hideWidgets.fte) && /* @__PURE__ */ jsxRuntime.jsx(Widget, { kind: "fte", label: L.fte, value: fmt(stats.fte, 2) }),
1792
+ !(hideWidgets == null ? void 0 : hideWidgets.vacation) && /* @__PURE__ */ jsxRuntime.jsx(Widget, { kind: "vacation", label: L.vacationBalance, value: `${fmt(stats.vacationAvg, 1)} d` }),
1793
+ !(hideWidgets == null ? void 0 : hideWidgets.sick) && /* @__PURE__ */ jsxRuntime.jsx(Widget, { kind: "sick", label: L.sickLeave, value: `${fmt(stats.sickAvg, 1)} d` }),
1794
+ !(hideWidgets == null ? void 0 : hideWidgets.departments) && /* @__PURE__ */ jsxRuntime.jsx(
1795
+ Widget,
1796
+ {
1797
+ kind: "departments",
1798
+ label: L.departments,
1799
+ value: fmt(stats.byDepartment.size, 0),
1800
+ hint: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "nice-hr-dashboard__dept-list", children: [...stats.byDepartment.entries()].slice(0, 5).map(([d, n]) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
1801
+ d,
1802
+ ": ",
1803
+ n
1804
+ ] }, d)) })
1805
+ }
1806
+ )
1807
+ ] });
1808
+ }
1809
+ );
1810
+ const wait = (ms) => new Promise((r) => setTimeout(r, ms));
1811
+ const NICE_VAT_PRESETS = {
1812
+ PL: [
1813
+ { code: "PL-23", rate: 0.23, label: "23%", description: "Stawka podstawowa" },
1814
+ { code: "PL-8", rate: 0.08, label: "8%", description: "Stawka obniżona" },
1815
+ { code: "PL-5", rate: 0.05, label: "5%", description: "Stawka obniżona" },
1816
+ { code: "PL-0", rate: 0, label: "0%", description: "Stawka zerowa (eksport)" },
1817
+ { code: "PL-zw", rate: 0, label: "zw.", description: "Zwolnienie" }
1818
+ ],
1819
+ EU: [
1820
+ { code: "EU-21", rate: 0.21, label: "21%" },
1821
+ { code: "EU-19", rate: 0.19, label: "19%" },
1822
+ { code: "EU-9", rate: 0.09, label: "9%" },
1823
+ { code: "EU-0", rate: 0, label: "0%" }
1824
+ ],
1825
+ UK: [
1826
+ { code: "UK-20", rate: 0.2, label: "20%", description: "Standard" },
1827
+ { code: "UK-5", rate: 0.05, label: "5%", description: "Reduced" },
1828
+ { code: "UK-0", rate: 0, label: "0%", description: "Zero" }
1829
+ ]
1830
+ };
1831
+ const DEFAULT_SEED = {
1832
+ invoices: [],
1833
+ purchaseOrders: [],
1834
+ inventory: [],
1835
+ suppliers: [],
1836
+ employees: [],
1837
+ resources: [],
1838
+ vatRates: NICE_VAT_PRESETS.PL
1839
+ };
1840
+ function useMockErpApi(options = {}) {
1841
+ const { latencyMs = 300, errorRate = 0, seed } = options;
1842
+ const [loading, setLoading] = React.useState(true);
1843
+ const [error, setError] = React.useState(null);
1844
+ const [data, setData] = React.useState(() => ({ ...DEFAULT_SEED, ...seed }));
1845
+ const settledRef = React.useRef(false);
1846
+ const refresh = React.useCallback(async () => {
1847
+ setLoading(true);
1848
+ setError(null);
1849
+ await wait(latencyMs);
1850
+ if (Math.random() < errorRate) {
1851
+ setError(new Error("Mock ERP API: simulated failure"));
1852
+ } else {
1853
+ setData((d) => ({ ...d }));
1854
+ }
1855
+ setLoading(false);
1856
+ }, [latencyMs, errorRate]);
1857
+ React.useEffect(() => {
1858
+ if (settledRef.current) {
1859
+ return;
1860
+ }
1861
+ settledRef.current = true;
1862
+ void refresh();
1863
+ }, [refresh]);
1864
+ const writeWith = React.useCallback(
1865
+ async (key, item) => {
1866
+ await wait(latencyMs);
1867
+ if (Math.random() < errorRate) {
1868
+ throw new Error("Mock ERP API: write failed");
1869
+ }
1870
+ setData((d) => {
1871
+ const arr = [...d[key]];
1872
+ const idx = arr.findIndex((i) => i.id === item.id);
1873
+ if (idx >= 0) {
1874
+ arr[idx] = item;
1875
+ } else {
1876
+ arr.push(item);
1877
+ }
1878
+ return { ...d, [key]: arr };
1879
+ });
1880
+ },
1881
+ [latencyMs, errorRate]
1882
+ );
1883
+ return React.useMemo(
1884
+ () => ({
1885
+ loading,
1886
+ error,
1887
+ invoices: data.invoices,
1888
+ purchaseOrders: data.purchaseOrders,
1889
+ inventory: data.inventory,
1890
+ suppliers: data.suppliers,
1891
+ employees: data.employees,
1892
+ resources: data.resources,
1893
+ vatRates: data.vatRates,
1894
+ refresh,
1895
+ upsertInvoice: (i) => writeWith("invoices", i),
1896
+ upsertPurchaseOrder: (p) => writeWith("purchaseOrders", p),
1897
+ upsertInventory: (i) => writeWith("inventory", i)
1898
+ }),
1899
+ [loading, error, data, refresh, writeWith]
1900
+ );
1901
+ }
1902
+ const NiceVatTable = React.forwardRef(function NiceVatTable2({
1903
+ country = "PL",
1904
+ rates,
1905
+ editable = false,
1906
+ onChange,
1907
+ onRemove,
1908
+ locale,
1909
+ labels,
1910
+ density = "comfortable",
1911
+ className,
1912
+ style,
1913
+ id
1914
+ }, ref) {
1915
+ const [internal, setInternal] = React.useState(rates ?? NICE_VAT_PRESETS[country]);
1916
+ const L = {
1917
+ code: "Code",
1918
+ rate: "Rate",
1919
+ label: "Label",
1920
+ description: "Description",
1921
+ add: "+ Add",
1922
+ remove: "Remove",
1923
+ ...labels
1924
+ };
1925
+ const update = React.useCallback(
1926
+ (next) => {
1927
+ setInternal(next);
1928
+ onChange == null ? void 0 : onChange(next);
1929
+ },
1930
+ [onChange]
1931
+ );
1932
+ const onCellEdit = (idx, key, raw) => {
1933
+ const next = [...internal];
1934
+ const r = { ...next[idx] };
1935
+ if (key === "rate") {
1936
+ const n = Number(raw.replace(",", "."));
1937
+ if (!Number.isFinite(n)) {
1938
+ return;
1939
+ }
1940
+ r.rate = n > 1 ? n / 100 : n;
1941
+ } else if (key === "code" || key === "label" || key === "description") {
1942
+ r[key] = raw;
1943
+ }
1944
+ next[idx] = r;
1945
+ update(next);
1946
+ };
1947
+ const addRow = () => {
1948
+ update([...internal, { code: `NEW-${internal.length + 1}`, rate: 0, label: "0%" }]);
1949
+ };
1950
+ const removeRow = (idx) => {
1951
+ const code = internal[idx].code;
1952
+ const next = internal.filter((_, i) => i !== idx);
1953
+ update(next);
1954
+ onRemove == null ? void 0 : onRemove(code);
1955
+ };
1956
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1957
+ "div",
1958
+ {
1959
+ ref,
1960
+ id,
1961
+ className: `nice-vat-table nice-vat-table--${density} ${className ?? ""}`,
1962
+ style,
1963
+ children: [
1964
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { children: [
1965
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1966
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.code }),
1967
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.rate }),
1968
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.label }),
1969
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.description }),
1970
+ editable && /* @__PURE__ */ jsxRuntime.jsx("th", { "aria-label": L.remove })
1971
+ ] }) }),
1972
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: internal.map((r, idx) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1973
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: editable ? /* @__PURE__ */ jsxRuntime.jsx("input", { value: r.code, onChange: (e) => onCellEdit(idx, "code", e.target.value) }) : r.code }),
1974
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: editable ? /* @__PURE__ */ jsxRuntime.jsx(
1975
+ "input",
1976
+ {
1977
+ type: "number",
1978
+ step: "0.01",
1979
+ min: 0,
1980
+ max: 1,
1981
+ value: r.rate,
1982
+ onChange: (e) => onCellEdit(idx, "rate", e.target.value)
1983
+ }
1984
+ ) : `${(r.rate * 100).toLocaleString(locale, { maximumFractionDigits: 2 })}%` }),
1985
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: editable ? /* @__PURE__ */ jsxRuntime.jsx(
1986
+ "input",
1987
+ {
1988
+ value: r.label ?? "",
1989
+ onChange: (e) => onCellEdit(idx, "label", e.target.value)
1990
+ }
1991
+ ) : r.label ?? "" }),
1992
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: editable ? /* @__PURE__ */ jsxRuntime.jsx(
1993
+ "input",
1994
+ {
1995
+ value: r.description ?? "",
1996
+ onChange: (e) => onCellEdit(idx, "description", e.target.value)
1997
+ }
1998
+ ) : r.description ?? "" }),
1999
+ editable && /* @__PURE__ */ jsxRuntime.jsx("td", { children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => removeRow(idx), "aria-label": L.remove, children: "×" }) })
2000
+ ] }, r.code)) })
2001
+ ] }),
2002
+ editable && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "nice-vat-table__add", onClick: addRow, children: L.add })
2003
+ ]
2004
+ }
2005
+ );
2006
+ });
2007
+ function pad(n) {
2008
+ return n < 10 ? `0${n}` : String(n);
2009
+ }
2010
+ function isoDate(d) {
2011
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
2012
+ }
2013
+ function escapeXml(s) {
2014
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
2015
+ }
2016
+ function defaultBuildXml(opts) {
2017
+ const { format, period, taxpayer, invoices } = opts;
2018
+ const lines = [];
2019
+ lines.push('<?xml version="1.0" encoding="UTF-8"?>');
2020
+ lines.push(`<JPK xmlns="http://jpk.mf.gov.pl/wzor/2022/01/01/${format}/" formCode="${format}">`);
2021
+ lines.push(" <Naglowek>");
2022
+ lines.push(` <KodFormularza>${format}</KodFormularza>`);
2023
+ lines.push(` <DataOd>${isoDate(period.from)}</DataOd>`);
2024
+ lines.push(` <DataDo>${isoDate(period.to)}</DataDo>`);
2025
+ lines.push(" </Naglowek>");
2026
+ lines.push(" <Podmiot1>");
2027
+ lines.push(` <NIP>${escapeXml(taxpayer.nip)}</NIP>`);
2028
+ lines.push(` <PelnaNazwa>${escapeXml(taxpayer.name)}</PelnaNazwa>`);
2029
+ if (taxpayer.regon) {
2030
+ lines.push(` <REGON>${escapeXml(taxpayer.regon)}</REGON>`);
2031
+ }
2032
+ lines.push(" </Podmiot1>");
2033
+ for (const inv of invoices) {
2034
+ lines.push(" <Faktura>");
2035
+ lines.push(` <NumerFaktury>${escapeXml(inv.invoiceNumber)}</NumerFaktury>`);
2036
+ lines.push(
2037
+ ` <DataWystawienia>${isoDate(inv.issueDate instanceof Date ? inv.issueDate : new Date(inv.issueDate))}</DataWystawienia>`
2038
+ );
2039
+ lines.push(` <NazwaNabywcy>${escapeXml(inv.buyer.name)}</NazwaNabywcy>`);
2040
+ if (inv.buyer.vatId) {
2041
+ lines.push(` <NIPNabywcy>${escapeXml(inv.buyer.vatId)}</NIPNabywcy>`);
2042
+ }
2043
+ let net = 0;
2044
+ let vat = 0;
2045
+ for (const ln of inv.lines) {
2046
+ const n = Math.round(ln.quantity * ln.unitPrice.amount * (1 - (ln.discount ?? 0)));
2047
+ const v = Math.round(n * ln.vatRate);
2048
+ net += n;
2049
+ vat += v;
2050
+ }
2051
+ lines.push(` <SumaNetto>${(net / 100).toFixed(2)}</SumaNetto>`);
2052
+ lines.push(` <SumaVAT>${(vat / 100).toFixed(2)}</SumaVAT>`);
2053
+ lines.push(` <SumaBrutto>${((net + vat) / 100).toFixed(2)}</SumaBrutto>`);
2054
+ lines.push(" </Faktura>");
2055
+ }
2056
+ lines.push("</JPK>");
2057
+ return lines.join("\n");
2058
+ }
2059
+ const NiceJpkExporter = React.forwardRef(
2060
+ function NiceJpkExporter2({
2061
+ invoices,
2062
+ taxpayer,
2063
+ defaultFormat = "JPK_V7M",
2064
+ defaultPeriod,
2065
+ buildXml = defaultBuildXml,
2066
+ onExport,
2067
+ filenameFor,
2068
+ labels,
2069
+ className,
2070
+ style,
2071
+ id
2072
+ }, ref) {
2073
+ const today = /* @__PURE__ */ new Date();
2074
+ const [format, setFormat] = React.useState(defaultFormat);
2075
+ const [from, setFrom] = React.useState(
2076
+ isoDate((defaultPeriod == null ? void 0 : defaultPeriod.from) ?? new Date(today.getFullYear(), today.getMonth(), 1))
2077
+ );
2078
+ const [to, setTo] = React.useState(
2079
+ isoDate((defaultPeriod == null ? void 0 : defaultPeriod.to) ?? new Date(today.getFullYear(), today.getMonth() + 1, 0))
2080
+ );
2081
+ const L = {
2082
+ format: "Format",
2083
+ from: "From",
2084
+ to: "To",
2085
+ export: "Export",
2086
+ ...labels
2087
+ };
2088
+ const exportNow = React.useCallback(() => {
2089
+ const opts = {
2090
+ format,
2091
+ period: { from: new Date(from), to: new Date(to) },
2092
+ taxpayer,
2093
+ invoices
2094
+ };
2095
+ const xml = buildXml(opts);
2096
+ const blob = new Blob([xml], { type: "application/xml" });
2097
+ const filename = (filenameFor == null ? void 0 : filenameFor(opts)) ?? `${format}_${from}_${to}.xml`;
2098
+ onExport == null ? void 0 : onExport(xml, blob, opts);
2099
+ if (typeof window !== "undefined" && typeof URL.createObjectURL === "function") {
2100
+ const url = URL.createObjectURL(blob);
2101
+ const a = document.createElement("a");
2102
+ a.href = url;
2103
+ a.download = filename;
2104
+ document.body.appendChild(a);
2105
+ a.click();
2106
+ a.remove();
2107
+ URL.revokeObjectURL(url);
2108
+ }
2109
+ }, [format, from, to, taxpayer, invoices, buildXml, onExport, filenameFor]);
2110
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, id, className: `nice-jpk-exporter ${className ?? ""}`, style, children: [
2111
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
2112
+ L.format,
2113
+ /* @__PURE__ */ jsxRuntime.jsxs(
2114
+ "select",
2115
+ {
2116
+ value: format,
2117
+ onChange: (e) => setFormat(e.target.value),
2118
+ children: [
2119
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "JPK_V7M", children: "JPK_V7M" }),
2120
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "JPK_V7K", children: "JPK_V7K" }),
2121
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "JPK_FA", children: "JPK_FA" })
2122
+ ]
2123
+ }
2124
+ )
2125
+ ] }),
2126
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
2127
+ L.from,
2128
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "date", value: from, onChange: (e) => setFrom(e.target.value) })
2129
+ ] }),
2130
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
2131
+ L.to,
2132
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "date", value: to, onChange: (e) => setTo(e.target.value) })
2133
+ ] }),
2134
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: exportNow, children: L.export }),
2135
+ /* @__PURE__ */ jsxRuntime.jsxs("small", { children: [
2136
+ invoices.length,
2137
+ " invoices ready"
2138
+ ] })
2139
+ ] });
2140
+ }
2141
+ );
2142
+ exports.NICE_VAT_PRESETS = NICE_VAT_PRESETS;
2143
+ exports.NiceHRDashboard = NiceHRDashboard;
1269
2144
  exports.NiceInventoryManager = NiceInventoryManager;
2145
+ exports.NiceInvoiceView = NiceInvoiceView;
2146
+ exports.NiceJpkExporter = NiceJpkExporter;
2147
+ exports.NicePurchaseOrder = NicePurchaseOrder;
1270
2148
  exports.NiceResourceAllocation = NiceResourceAllocation;
2149
+ exports.NiceVatTable = NiceVatTable;
2150
+ exports.NiceWarehouseView = NiceWarehouseView;
2151
+ exports.buildJpkXml = defaultBuildXml;
2152
+ exports.useMockErpApi = useMockErpApi;
1271
2153
  //# sourceMappingURL=index.cjs.map