@nice2dev/ui-erp 1.0.11 → 1.0.12

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,739 @@ 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) return colors.low;
1480
+ if (occ < 0.5) return colors.low;
1481
+ if (occ < 0.85) return colors.mid;
1482
+ return colors.high;
1483
+ }
1484
+ const NiceWarehouseView = React.forwardRef(
1485
+ function NiceWarehouseView2({ warehouseName, cells, colors = { low: "#dcfce7", mid: "#fde68a", high: "#fecaca" }, onCellClick, showLegend = true, cellSize = 48, aisleEvery = 4, className, style, id }, ref) {
1486
+ const [hovered, setHovered] = React.useState(null);
1487
+ const grid = React.useMemo(() => {
1488
+ const rows = /* @__PURE__ */ new Map();
1489
+ for (const c of cells) {
1490
+ const rowKey = c.row !== void 0 ? `r${c.row}` : c.location.rack ?? c.location.aisle ?? "0";
1491
+ let arr = rows.get(rowKey);
1492
+ if (!arr) {
1493
+ arr = [];
1494
+ rows.set(rowKey, arr);
1495
+ }
1496
+ arr.push(c);
1497
+ }
1498
+ return [...rows.entries()].map(([rowKey, arr]) => ({ rowKey, cells: arr }));
1499
+ }, [cells]);
1500
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, id, className: `nice-warehouse-view ${className ?? ""}`, style, children: [
1501
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "nice-warehouse-view__header", children: [
1502
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: warehouseName }),
1503
+ showLegend && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nice-warehouse-view__legend", "aria-label": "Occupancy legend", children: [
1504
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { background: colors.low } }),
1505
+ " low",
1506
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { background: colors.mid } }),
1507
+ " mid",
1508
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { background: colors.high } }),
1509
+ " high"
1510
+ ] })
1511
+ ] }),
1512
+ /* @__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) => {
1513
+ const key = [c.location.rack, c.location.aisle, c.location.shelf, c.location.bin].filter(Boolean).join("-") || String(idx);
1514
+ const aisleBreak = aisleEvery > 0 && idx > 0 && idx % aisleEvery === 0;
1515
+ return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
1516
+ aisleBreak && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "nice-warehouse-view__aisle", "aria-hidden": true }),
1517
+ /* @__PURE__ */ jsxRuntime.jsx(
1518
+ "button",
1519
+ {
1520
+ type: "button",
1521
+ role: "gridcell",
1522
+ className: "nice-warehouse-view__cell",
1523
+ style: {
1524
+ width: cellSize,
1525
+ height: cellSize,
1526
+ background: colorFor(c.occupancy, colors)
1527
+ },
1528
+ title: `${key} — ${(c.occupancy * 100).toFixed(0)}% (${c.items.length} items)`,
1529
+ onClick: () => onCellClick == null ? void 0 : onCellClick(c),
1530
+ onMouseEnter: () => setHovered(c),
1531
+ onMouseLeave: () => setHovered(null),
1532
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nice-warehouse-view__bin", children: c.location.bin ?? c.location.shelf ?? "" })
1533
+ }
1534
+ )
1535
+ ] }, key);
1536
+ }) }, rowKey)) }),
1537
+ hovered && /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "nice-warehouse-view__details", "aria-live": "polite", children: [
1538
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
1539
+ hovered.location.rack,
1540
+ "/",
1541
+ hovered.location.shelf,
1542
+ "/",
1543
+ hovered.location.bin
1544
+ ] }),
1545
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1546
+ hovered.items.length,
1547
+ " items · ",
1548
+ (hovered.occupancy * 100).toFixed(0),
1549
+ "% full"
1550
+ ] }),
1551
+ /* @__PURE__ */ jsxRuntime.jsxs("ul", { children: [
1552
+ hovered.items.slice(0, 5).map((it) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
1553
+ it.sku,
1554
+ " — ",
1555
+ it.name
1556
+ ] }, it.id)),
1557
+ hovered.items.length > 5 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
1558
+ "…+",
1559
+ hovered.items.length - 5
1560
+ ] })
1561
+ ] })
1562
+ ] })
1563
+ ] });
1564
+ }
1565
+ );
1566
+ const STATUS_TINT = {
1567
+ draft: "#6b7280",
1568
+ "pending-approval": "#ca8a04",
1569
+ approved: "#2563eb",
1570
+ ordered: "#0891b2",
1571
+ "partially-received": "#9333ea",
1572
+ received: "#16a34a",
1573
+ cancelled: "#dc2626"
1574
+ };
1575
+ function fmtMoney(amount, currency, locale) {
1576
+ const code = typeof currency === "string" ? currency : currency.code;
1577
+ const decimals = typeof currency === "string" ? 2 : currency.decimalPlaces ?? 2;
1578
+ return new Intl.NumberFormat(locale, { style: "currency", currency: code }).format(amount / Math.pow(10, decimals));
1579
+ }
1580
+ function fmtDate(d, locale) {
1581
+ if (!d) return "—";
1582
+ const dt = d instanceof Date ? d : new Date(d);
1583
+ return new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(dt);
1584
+ }
1585
+ const NicePurchaseOrder = React.forwardRef(
1586
+ function NicePurchaseOrder2({ orders, selectable = true, initialSelectedId, locale, labels, readOnly, onOrderApprove, onReceiveItems, onOrderUpdate, className, style, id }, ref) {
1587
+ var _a;
1588
+ const [selectedId, setSelectedId] = React.useState(initialSelectedId ?? ((_a = orders[0]) == null ? void 0 : _a.id));
1589
+ const L = {
1590
+ orderNumber: "PO #",
1591
+ supplier: "Supplier",
1592
+ status: "Status",
1593
+ orderDate: "Ordered",
1594
+ expected: "Expected",
1595
+ total: "Total",
1596
+ sku: "SKU",
1597
+ name: "Item",
1598
+ qty: "Qty",
1599
+ received: "Recv",
1600
+ unitPrice: "Unit",
1601
+ lineTotal: "Subtotal",
1602
+ notes: "Notes",
1603
+ approve: "Approve",
1604
+ receive: "Receive all",
1605
+ ...labels
1606
+ };
1607
+ const selected = React.useMemo(
1608
+ () => orders.find((o) => o.id === selectedId),
1609
+ [orders, selectedId]
1610
+ );
1611
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, id, className: `nice-purchase-order ${className ?? ""}`, style, children: [
1612
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "nice-purchase-order__list", children: [
1613
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1614
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.orderNumber }),
1615
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.supplier }),
1616
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.status }),
1617
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.orderDate }),
1618
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.expected }),
1619
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.total })
1620
+ ] }) }),
1621
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: orders.map((o) => /* @__PURE__ */ jsxRuntime.jsxs(
1622
+ "tr",
1623
+ {
1624
+ "aria-selected": o.id === selectedId,
1625
+ className: o.id === selectedId ? "is-selected" : void 0,
1626
+ onClick: () => selectable && setSelectedId(o.id),
1627
+ children: [
1628
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: o.orderNumber }),
1629
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: o.supplier.name }),
1630
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: STATUS_TINT[o.status] }, children: [
1631
+ "● ",
1632
+ o.status
1633
+ ] }) }),
1634
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: fmtDate(o.orderDate, locale) }),
1635
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: fmtDate(o.expectedDelivery, locale) }),
1636
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney(o.total.amount, o.total.currency, locale) })
1637
+ ]
1638
+ },
1639
+ o.id
1640
+ )) })
1641
+ ] }),
1642
+ selectable && selected && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "nice-purchase-order__detail", "aria-label": `${L.orderNumber} ${selected.orderNumber}`, children: [
1643
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { children: [
1644
+ /* @__PURE__ */ jsxRuntime.jsxs("h3", { children: [
1645
+ selected.orderNumber,
1646
+ " — ",
1647
+ selected.supplier.name
1648
+ ] }),
1649
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nice-purchase-order__actions", children: [
1650
+ selected.status === "pending-approval" && onOrderApprove && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => onOrderApprove(selected.id), children: L.approve }),
1651
+ (selected.status === "ordered" || selected.status === "partially-received") && onReceiveItems && /* @__PURE__ */ jsxRuntime.jsx(
1652
+ "button",
1653
+ {
1654
+ type: "button",
1655
+ onClick: () => onReceiveItems(selected.id, selected.items.map((it) => ({ itemId: it.itemId, quantity: it.quantity - (it.receivedQuantity ?? 0) }))),
1656
+ children: L.receive
1657
+ }
1658
+ ),
1659
+ onOrderUpdate && selected.status === "draft" && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => onOrderUpdate({ ...selected, status: "pending-approval" }), children: "Submit" })
1660
+ ] })
1661
+ ] }),
1662
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "nice-purchase-order__items", children: [
1663
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1664
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.sku }),
1665
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.name }),
1666
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.qty }),
1667
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.received }),
1668
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.unitPrice }),
1669
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.lineTotal })
1670
+ ] }) }),
1671
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: selected.items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1672
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: it.sku }),
1673
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: it.itemName }),
1674
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: it.quantity }),
1675
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: it.receivedQuantity ?? 0 }),
1676
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney(it.unitPrice.amount, it.unitPrice.currency, locale) }),
1677
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: fmtMoney(it.lineTotal.amount, it.lineTotal.currency, locale) })
1678
+ ] }, it.itemId)) }),
1679
+ /* @__PURE__ */ jsxRuntime.jsx("tfoot", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1680
+ /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: 5, className: "nice-num", children: L.total }),
1681
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: /* @__PURE__ */ jsxRuntime.jsx("strong", { children: fmtMoney(selected.total.amount, selected.total.currency, locale) }) })
1682
+ ] }) })
1683
+ ] }),
1684
+ selected.notes && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "nice-purchase-order__notes", children: [
1685
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
1686
+ L.notes,
1687
+ ":"
1688
+ ] }),
1689
+ " ",
1690
+ selected.notes
1691
+ ] })
1692
+ ] })
1693
+ ] });
1694
+ }
1695
+ );
1696
+ const NiceHRDashboard = React.forwardRef(
1697
+ function NiceHRDashboard2({ employees, labels, hideWidgets, locale, density = "comfortable", onWidgetClick, className, style, id }, ref) {
1698
+ const L = {
1699
+ headcount: "Headcount",
1700
+ fte: "FTE",
1701
+ vacationBalance: "Avg vacation balance",
1702
+ sickLeave: "Avg sick days (YTD)",
1703
+ departments: "Departments",
1704
+ activeEmployees: "Active",
1705
+ ...labels
1706
+ };
1707
+ const stats = React.useMemo(() => {
1708
+ const active = employees.filter((e) => e.active !== false);
1709
+ const fte = active.reduce((s, e) => s + (e.fte ?? 1), 0);
1710
+ const vacationAvg = active.length === 0 ? 0 : active.reduce((s, e) => s + (e.vacationBalanceDays ?? 0), 0) / active.length;
1711
+ const sickAvg = active.length === 0 ? 0 : active.reduce((s, e) => s + (e.sickLeaveDaysYtd ?? 0), 0) / active.length;
1712
+ const byDepartment = /* @__PURE__ */ new Map();
1713
+ for (const e of active) {
1714
+ const k = e.department ?? "—";
1715
+ byDepartment.set(k, (byDepartment.get(k) ?? 0) + 1);
1716
+ }
1717
+ return { headcount: employees.length, active: active.length, fte, vacationAvg, sickAvg, byDepartment };
1718
+ }, [employees]);
1719
+ const fmt = (n, d = 1) => n.toLocaleString(locale, { maximumFractionDigits: d });
1720
+ const Widget = ({ kind, label, value, hint }) => /* @__PURE__ */ jsxRuntime.jsxs(
1721
+ "button",
1722
+ {
1723
+ type: "button",
1724
+ className: "nice-hr-dashboard__widget",
1725
+ onClick: () => onWidgetClick == null ? void 0 : onWidgetClick(kind),
1726
+ children: [
1727
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nice-hr-dashboard__label", children: label }),
1728
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nice-hr-dashboard__value", children: value }),
1729
+ hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nice-hr-dashboard__hint", children: hint })
1730
+ ]
1731
+ }
1732
+ );
1733
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, id, className: `nice-hr-dashboard nice-hr-dashboard--${density} ${className ?? ""}`, style, role: "group", "aria-label": "HR dashboard", children: [
1734
+ !(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)}` }),
1735
+ !(hideWidgets == null ? void 0 : hideWidgets.fte) && /* @__PURE__ */ jsxRuntime.jsx(Widget, { kind: "fte", label: L.fte, value: fmt(stats.fte, 2) }),
1736
+ !(hideWidgets == null ? void 0 : hideWidgets.vacation) && /* @__PURE__ */ jsxRuntime.jsx(Widget, { kind: "vacation", label: L.vacationBalance, value: `${fmt(stats.vacationAvg, 1)} d` }),
1737
+ !(hideWidgets == null ? void 0 : hideWidgets.sick) && /* @__PURE__ */ jsxRuntime.jsx(Widget, { kind: "sick", label: L.sickLeave, value: `${fmt(stats.sickAvg, 1)} d` }),
1738
+ !(hideWidgets == null ? void 0 : hideWidgets.departments) && /* @__PURE__ */ jsxRuntime.jsx(
1739
+ Widget,
1740
+ {
1741
+ kind: "departments",
1742
+ label: L.departments,
1743
+ value: fmt(stats.byDepartment.size, 0),
1744
+ 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: [
1745
+ d,
1746
+ ": ",
1747
+ n
1748
+ ] }, d)) })
1749
+ }
1750
+ )
1751
+ ] });
1752
+ }
1753
+ );
1754
+ const wait = (ms) => new Promise((r) => setTimeout(r, ms));
1755
+ const NICE_VAT_PRESETS = {
1756
+ PL: [
1757
+ { code: "PL-23", rate: 0.23, label: "23%", description: "Stawka podstawowa" },
1758
+ { code: "PL-8", rate: 0.08, label: "8%", description: "Stawka obniżona" },
1759
+ { code: "PL-5", rate: 0.05, label: "5%", description: "Stawka obniżona" },
1760
+ { code: "PL-0", rate: 0, label: "0%", description: "Stawka zerowa (eksport)" },
1761
+ { code: "PL-zw", rate: 0, label: "zw.", description: "Zwolnienie" }
1762
+ ],
1763
+ EU: [
1764
+ { code: "EU-21", rate: 0.21, label: "21%" },
1765
+ { code: "EU-19", rate: 0.19, label: "19%" },
1766
+ { code: "EU-9", rate: 0.09, label: "9%" },
1767
+ { code: "EU-0", rate: 0, label: "0%" }
1768
+ ],
1769
+ UK: [
1770
+ { code: "UK-20", rate: 0.2, label: "20%", description: "Standard" },
1771
+ { code: "UK-5", rate: 0.05, label: "5%", description: "Reduced" },
1772
+ { code: "UK-0", rate: 0, label: "0%", description: "Zero" }
1773
+ ]
1774
+ };
1775
+ const DEFAULT_SEED = {
1776
+ invoices: [],
1777
+ purchaseOrders: [],
1778
+ inventory: [],
1779
+ suppliers: [],
1780
+ employees: [],
1781
+ resources: [],
1782
+ vatRates: NICE_VAT_PRESETS.PL
1783
+ };
1784
+ function useMockErpApi(options = {}) {
1785
+ const { latencyMs = 300, errorRate = 0, seed } = options;
1786
+ const [loading, setLoading] = React.useState(true);
1787
+ const [error, setError] = React.useState(null);
1788
+ const [data, setData] = React.useState(() => ({ ...DEFAULT_SEED, ...seed }));
1789
+ const settledRef = React.useRef(false);
1790
+ const refresh = React.useCallback(async () => {
1791
+ setLoading(true);
1792
+ setError(null);
1793
+ await wait(latencyMs);
1794
+ if (Math.random() < errorRate) {
1795
+ setError(new Error("Mock ERP API: simulated failure"));
1796
+ } else {
1797
+ setData((d) => ({ ...d }));
1798
+ }
1799
+ setLoading(false);
1800
+ }, [latencyMs, errorRate]);
1801
+ React.useEffect(() => {
1802
+ if (settledRef.current) return;
1803
+ settledRef.current = true;
1804
+ void refresh();
1805
+ }, [refresh]);
1806
+ const writeWith = React.useCallback(
1807
+ async (key, item) => {
1808
+ await wait(latencyMs);
1809
+ if (Math.random() < errorRate) throw new Error("Mock ERP API: write failed");
1810
+ setData((d) => {
1811
+ const arr = [...d[key]];
1812
+ const idx = arr.findIndex((i) => i.id === item.id);
1813
+ if (idx >= 0) arr[idx] = item;
1814
+ else arr.push(item);
1815
+ return { ...d, [key]: arr };
1816
+ });
1817
+ },
1818
+ [latencyMs, errorRate]
1819
+ );
1820
+ return React.useMemo(
1821
+ () => ({
1822
+ loading,
1823
+ error,
1824
+ invoices: data.invoices,
1825
+ purchaseOrders: data.purchaseOrders,
1826
+ inventory: data.inventory,
1827
+ suppliers: data.suppliers,
1828
+ employees: data.employees,
1829
+ resources: data.resources,
1830
+ vatRates: data.vatRates,
1831
+ refresh,
1832
+ upsertInvoice: (i) => writeWith("invoices", i),
1833
+ upsertPurchaseOrder: (p) => writeWith("purchaseOrders", p),
1834
+ upsertInventory: (i) => writeWith("inventory", i)
1835
+ }),
1836
+ [loading, error, data, refresh, writeWith]
1837
+ );
1838
+ }
1839
+ const NiceVatTable = React.forwardRef(
1840
+ function NiceVatTable2({ country = "PL", rates, editable = false, onChange, onRemove, locale, labels, density = "comfortable", className, style, id }, ref) {
1841
+ const [internal, setInternal] = React.useState(rates ?? NICE_VAT_PRESETS[country]);
1842
+ const L = { code: "Code", rate: "Rate", label: "Label", description: "Description", add: "+ Add", remove: "Remove", ...labels };
1843
+ const update = React.useCallback(
1844
+ (next) => {
1845
+ setInternal(next);
1846
+ onChange == null ? void 0 : onChange(next);
1847
+ },
1848
+ [onChange]
1849
+ );
1850
+ const onCellEdit = (idx, key, raw) => {
1851
+ const next = [...internal];
1852
+ const r = { ...next[idx] };
1853
+ if (key === "rate") {
1854
+ const n = Number(raw.replace(",", "."));
1855
+ if (!Number.isFinite(n)) return;
1856
+ r.rate = n > 1 ? n / 100 : n;
1857
+ } else if (key === "code" || key === "label" || key === "description") {
1858
+ r[key] = raw;
1859
+ }
1860
+ next[idx] = r;
1861
+ update(next);
1862
+ };
1863
+ const addRow = () => {
1864
+ update([...internal, { code: `NEW-${internal.length + 1}`, rate: 0, label: "0%" }]);
1865
+ };
1866
+ const removeRow = (idx) => {
1867
+ const code = internal[idx].code;
1868
+ const next = internal.filter((_, i) => i !== idx);
1869
+ update(next);
1870
+ onRemove == null ? void 0 : onRemove(code);
1871
+ };
1872
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, id, className: `nice-vat-table nice-vat-table--${density} ${className ?? ""}`, style, children: [
1873
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { children: [
1874
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1875
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.code }),
1876
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "nice-num", children: L.rate }),
1877
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.label }),
1878
+ /* @__PURE__ */ jsxRuntime.jsx("th", { children: L.description }),
1879
+ editable && /* @__PURE__ */ jsxRuntime.jsx("th", { "aria-label": L.remove })
1880
+ ] }) }),
1881
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: internal.map((r, idx) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1882
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: editable ? /* @__PURE__ */ jsxRuntime.jsx("input", { value: r.code, onChange: (e) => onCellEdit(idx, "code", e.target.value) }) : r.code }),
1883
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "nice-num", children: editable ? /* @__PURE__ */ jsxRuntime.jsx("input", { type: "number", step: "0.01", min: 0, max: 1, value: r.rate, onChange: (e) => onCellEdit(idx, "rate", e.target.value) }) : `${(r.rate * 100).toLocaleString(locale, { maximumFractionDigits: 2 })}%` }),
1884
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: editable ? /* @__PURE__ */ jsxRuntime.jsx("input", { value: r.label ?? "", onChange: (e) => onCellEdit(idx, "label", e.target.value) }) : r.label ?? "" }),
1885
+ /* @__PURE__ */ jsxRuntime.jsx("td", { children: editable ? /* @__PURE__ */ jsxRuntime.jsx("input", { value: r.description ?? "", onChange: (e) => onCellEdit(idx, "description", e.target.value) }) : r.description ?? "" }),
1886
+ editable && /* @__PURE__ */ jsxRuntime.jsx("td", { children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => removeRow(idx), "aria-label": L.remove, children: "×" }) })
1887
+ ] }, r.code)) })
1888
+ ] }),
1889
+ editable && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "nice-vat-table__add", onClick: addRow, children: L.add })
1890
+ ] });
1891
+ }
1892
+ );
1893
+ function pad(n) {
1894
+ return n < 10 ? `0${n}` : String(n);
1895
+ }
1896
+ function isoDate(d) {
1897
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
1898
+ }
1899
+ function escapeXml(s) {
1900
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
1901
+ }
1902
+ function defaultBuildXml(opts) {
1903
+ const { format, period, taxpayer, invoices } = opts;
1904
+ const lines = [];
1905
+ lines.push('<?xml version="1.0" encoding="UTF-8"?>');
1906
+ lines.push(`<JPK xmlns="http://jpk.mf.gov.pl/wzor/2022/01/01/${format}/" formCode="${format}">`);
1907
+ lines.push(" <Naglowek>");
1908
+ lines.push(` <KodFormularza>${format}</KodFormularza>`);
1909
+ lines.push(` <DataOd>${isoDate(period.from)}</DataOd>`);
1910
+ lines.push(` <DataDo>${isoDate(period.to)}</DataDo>`);
1911
+ lines.push(" </Naglowek>");
1912
+ lines.push(" <Podmiot1>");
1913
+ lines.push(` <NIP>${escapeXml(taxpayer.nip)}</NIP>`);
1914
+ lines.push(` <PelnaNazwa>${escapeXml(taxpayer.name)}</PelnaNazwa>`);
1915
+ if (taxpayer.regon) lines.push(` <REGON>${escapeXml(taxpayer.regon)}</REGON>`);
1916
+ lines.push(" </Podmiot1>");
1917
+ for (const inv of invoices) {
1918
+ lines.push(" <Faktura>");
1919
+ lines.push(` <NumerFaktury>${escapeXml(inv.invoiceNumber)}</NumerFaktury>`);
1920
+ lines.push(` <DataWystawienia>${isoDate(inv.issueDate instanceof Date ? inv.issueDate : new Date(inv.issueDate))}</DataWystawienia>`);
1921
+ lines.push(` <NazwaNabywcy>${escapeXml(inv.buyer.name)}</NazwaNabywcy>`);
1922
+ if (inv.buyer.vatId) lines.push(` <NIPNabywcy>${escapeXml(inv.buyer.vatId)}</NIPNabywcy>`);
1923
+ let net = 0;
1924
+ let vat = 0;
1925
+ for (const ln of inv.lines) {
1926
+ const n = Math.round(ln.quantity * ln.unitPrice.amount * (1 - (ln.discount ?? 0)));
1927
+ const v = Math.round(n * ln.vatRate);
1928
+ net += n;
1929
+ vat += v;
1930
+ }
1931
+ lines.push(` <SumaNetto>${(net / 100).toFixed(2)}</SumaNetto>`);
1932
+ lines.push(` <SumaVAT>${(vat / 100).toFixed(2)}</SumaVAT>`);
1933
+ lines.push(` <SumaBrutto>${((net + vat) / 100).toFixed(2)}</SumaBrutto>`);
1934
+ lines.push(" </Faktura>");
1935
+ }
1936
+ lines.push("</JPK>");
1937
+ return lines.join("\n");
1938
+ }
1939
+ const NiceJpkExporter = React.forwardRef(
1940
+ function NiceJpkExporter2({ invoices, taxpayer, defaultFormat = "JPK_V7M", defaultPeriod, buildXml = defaultBuildXml, onExport, filenameFor, labels, className, style, id }, ref) {
1941
+ const today = /* @__PURE__ */ new Date();
1942
+ const [format, setFormat] = React.useState(defaultFormat);
1943
+ const [from, setFrom] = React.useState(isoDate((defaultPeriod == null ? void 0 : defaultPeriod.from) ?? new Date(today.getFullYear(), today.getMonth(), 1)));
1944
+ const [to, setTo] = React.useState(isoDate((defaultPeriod == null ? void 0 : defaultPeriod.to) ?? new Date(today.getFullYear(), today.getMonth() + 1, 0)));
1945
+ const L = { format: "Format", from: "From", to: "To", export: "Export", ...labels };
1946
+ const exportNow = React.useCallback(() => {
1947
+ const opts = {
1948
+ format,
1949
+ period: { from: new Date(from), to: new Date(to) },
1950
+ taxpayer,
1951
+ invoices
1952
+ };
1953
+ const xml = buildXml(opts);
1954
+ const blob = new Blob([xml], { type: "application/xml" });
1955
+ const filename = (filenameFor == null ? void 0 : filenameFor(opts)) ?? `${format}_${from}_${to}.xml`;
1956
+ onExport == null ? void 0 : onExport(xml, blob, opts);
1957
+ if (typeof window !== "undefined" && typeof URL.createObjectURL === "function") {
1958
+ const url = URL.createObjectURL(blob);
1959
+ const a = document.createElement("a");
1960
+ a.href = url;
1961
+ a.download = filename;
1962
+ document.body.appendChild(a);
1963
+ a.click();
1964
+ a.remove();
1965
+ URL.revokeObjectURL(url);
1966
+ }
1967
+ }, [format, from, to, taxpayer, invoices, buildXml, onExport, filenameFor]);
1968
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, id, className: `nice-jpk-exporter ${className ?? ""}`, style, children: [
1969
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
1970
+ L.format,
1971
+ /* @__PURE__ */ jsxRuntime.jsxs("select", { value: format, onChange: (e) => setFormat(e.target.value), children: [
1972
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "JPK_V7M", children: "JPK_V7M" }),
1973
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "JPK_V7K", children: "JPK_V7K" }),
1974
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "JPK_FA", children: "JPK_FA" })
1975
+ ] })
1976
+ ] }),
1977
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
1978
+ L.from,
1979
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "date", value: from, onChange: (e) => setFrom(e.target.value) })
1980
+ ] }),
1981
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
1982
+ L.to,
1983
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "date", value: to, onChange: (e) => setTo(e.target.value) })
1984
+ ] }),
1985
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: exportNow, children: L.export }),
1986
+ /* @__PURE__ */ jsxRuntime.jsxs("small", { children: [
1987
+ invoices.length,
1988
+ " invoices ready"
1989
+ ] })
1990
+ ] });
1991
+ }
1992
+ );
1993
+ exports.NICE_VAT_PRESETS = NICE_VAT_PRESETS;
1994
+ exports.NiceHRDashboard = NiceHRDashboard;
1269
1995
  exports.NiceInventoryManager = NiceInventoryManager;
1996
+ exports.NiceInvoiceView = NiceInvoiceView;
1997
+ exports.NiceJpkExporter = NiceJpkExporter;
1998
+ exports.NicePurchaseOrder = NicePurchaseOrder;
1270
1999
  exports.NiceResourceAllocation = NiceResourceAllocation;
2000
+ exports.NiceVatTable = NiceVatTable;
2001
+ exports.NiceWarehouseView = NiceWarehouseView;
2002
+ exports.buildJpkXml = defaultBuildXml;
2003
+ exports.useMockErpApi = useMockErpApi;
1271
2004
  //# sourceMappingURL=index.cjs.map