medusajs-documents-plugin 1.1.60 → 1.1.61

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.
@@ -410,6 +410,10 @@ const DocumentsPage = () => {
410
410
  const [zohoLiveDocs, setZohoLiveDocs] = react.useState([]);
411
411
  const [loadingZoho, setLoadingZoho] = react.useState(false);
412
412
  const [isSyncingRepairs, setIsSyncingRepairs] = react.useState(false);
413
+ const [displayLimit, setDisplayLimit] = react.useState(100);
414
+ const [totalBackendCount, setTotalBackendCount] = react.useState(0);
415
+ const [isLoadingMore, setIsLoadingMore] = react.useState(false);
416
+ const sentinelRef = react.useRef(null);
413
417
  const [groupByJob, setGroupByJob] = react.useState(true);
414
418
  const [expandedGroups, setExpandedGroups] = react.useState({});
415
419
  const toggleGroup = (groupId) => {
@@ -729,10 +733,16 @@ const DocumentsPage = () => {
729
733
  custom_message: "",
730
734
  subject: ""
731
735
  });
732
- const loadDocuments = () => {
736
+ const loadDocuments = (resetLimit = true) => {
733
737
  setLoading(true);
734
- fetch("/admin/documents", { credentials: "include" }).then((res) => res.json()).then((data) => {
738
+ fetch("/admin/documents?take=100&skip=0", { credentials: "include" }).then((res) => res.json()).then((data) => {
735
739
  setDocuments(data.documents || []);
740
+ if (data.count != null) {
741
+ setTotalBackendCount(Number(data.count));
742
+ }
743
+ if (resetLimit) {
744
+ setDisplayLimit(100);
745
+ }
736
746
  }).catch((err) => console.error("Error loading documents:", err)).finally(() => setLoading(false));
737
747
  };
738
748
  const loadSettings = () => {
@@ -1201,6 +1211,71 @@ const DocumentsPage = () => {
1201
1211
  return true;
1202
1212
  });
1203
1213
  }, [documents, sourceFilter, typeFilter, searchTerm]);
1214
+ const totalItemCount = groupByJob ? documentGroups.length : filteredDocs.length;
1215
+ const hasMoreLocally = displayLimit < totalItemCount;
1216
+ const hasMoreBackend = documents.length < totalBackendCount;
1217
+ const canLoadMore = hasMoreLocally || hasMoreBackend;
1218
+ const handleLoadMore = react.useCallback(async () => {
1219
+ if (isLoadingMore || loading) return;
1220
+ if (hasMoreLocally) {
1221
+ setDisplayLimit((prev) => prev + 100);
1222
+ return;
1223
+ }
1224
+ if (hasMoreBackend) {
1225
+ setIsLoadingMore(true);
1226
+ try {
1227
+ const nextSkip = documents.length;
1228
+ const res = await fetch(`/admin/documents?take=100&skip=${nextSkip}`, { credentials: "include" });
1229
+ const data = await res.json();
1230
+ if (data.documents && data.documents.length > 0) {
1231
+ setDocuments((prev) => {
1232
+ const existingIds = new Set(prev.map((d) => d.id));
1233
+ const newUnique = data.documents.filter((d) => !existingIds.has(d.id));
1234
+ return [...prev, ...newUnique];
1235
+ });
1236
+ if (data.count != null) {
1237
+ setTotalBackendCount(Number(data.count));
1238
+ }
1239
+ setDisplayLimit((prev) => prev + 100);
1240
+ } else {
1241
+ setTotalBackendCount(documents.length);
1242
+ }
1243
+ } catch (err) {
1244
+ console.error("Error loading more documents:", err);
1245
+ } finally {
1246
+ setIsLoadingMore(false);
1247
+ }
1248
+ }
1249
+ }, [isLoadingMore, loading, hasMoreLocally, hasMoreBackend, documents.length, totalBackendCount]);
1250
+ react.useEffect(() => {
1251
+ setDisplayLimit(100);
1252
+ }, [searchTerm, typeFilter, sourceFilter, groupByJob]);
1253
+ react.useEffect(() => {
1254
+ const el = sentinelRef.current;
1255
+ if (!el || !canLoadMore || isLoadingMore || loading) return;
1256
+ const observer = new IntersectionObserver(
1257
+ (entries) => {
1258
+ if (entries[0].isIntersecting) {
1259
+ handleLoadMore();
1260
+ }
1261
+ },
1262
+ { rootMargin: "300px" }
1263
+ );
1264
+ observer.observe(el);
1265
+ return () => observer.disconnect();
1266
+ }, [handleLoadMore, canLoadMore, isLoadingMore, loading]);
1267
+ react.useEffect(() => {
1268
+ const handleScroll = () => {
1269
+ if (!canLoadMore || isLoadingMore || loading) return;
1270
+ const scrollPosition = window.innerHeight + window.scrollY;
1271
+ const threshold = document.documentElement.scrollHeight - 350;
1272
+ if (scrollPosition >= threshold) {
1273
+ handleLoadMore();
1274
+ }
1275
+ };
1276
+ window.addEventListener("scroll", handleScroll, { passive: true });
1277
+ return () => window.removeEventListener("scroll", handleScroll);
1278
+ }, [handleLoadMore, canLoadMore, isLoadingMore, loading]);
1204
1279
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-0", children: [
1205
1280
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col md:flex-row md:items-center justify-between p-6 border-b border-ui-border-base gap-4 bg-ui-bg-base", children: [
1206
1281
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
@@ -1364,340 +1439,183 @@ const DocumentsPage = () => {
1364
1439
  loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-12 text-center text-ui-fg-muted text-sm", children: "Loading documents..." }) : (groupByJob ? documentGroups.length === 0 : filteredDocs.length === 0) ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-12 text-center text-ui-fg-muted border border-dashed border-ui-border-base rounded-lg", children: [
1365
1440
  /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm", children: "No documents found." }),
1366
1441
  /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-ui-fg-subtle mt-1", children: "Create a manual invoice or process an order to generate your first document." })
1367
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
1368
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1369
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Reference" }),
1370
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Type" }),
1371
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Recipient" }),
1372
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Amount" }),
1373
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Status" }),
1374
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Source" }),
1375
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Date" }),
1376
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: "text-right", children: "Actions" })
1377
- ] }) }),
1378
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: groupByJob ? documentGroups.map((group) => {
1379
- const isExpanded = !!expandedGroups[group.groupId];
1380
- const doc = group.primaryDoc;
1381
- const isPaid = doc.payment_status === "paid" || doc.status === "paid";
1382
- const isZoho = doc.source === "zoho";
1383
- const hasMultiple = group.documents.length > 1;
1384
- return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
1385
- /* @__PURE__ */ jsxRuntime.jsxs(
1386
- ui.Table.Row,
1387
- {
1388
- className: `transition-colors ${isExpanded ? "bg-ui-bg-subtle" : "hover:bg-ui-bg-subtle-hover"}`,
1389
- children: [
1390
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
1391
- hasMultiple ? /* @__PURE__ */ jsxRuntime.jsx(
1392
- "button",
1393
- {
1394
- type: "button",
1395
- onClick: () => toggleGroup(group.groupId),
1396
- className: "p-1 rounded hover:bg-ui-bg-base text-ui-fg-subtle hover:text-ui-fg-base cursor-pointer transition-colors",
1397
- title: isExpanded ? "Collapse related documents" : `Expand ${group.documents.length} related documents`,
1398
- children: isExpanded ? /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDown, { className: "w-4 h-4 text-purple-600" }) : /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRight, { className: "w-4 h-4 text-ui-fg-subtle" })
1399
- }
1400
- ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-5 inline-block" }),
1401
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 flex-wrap", children: [
1402
- /* @__PURE__ */ jsxRuntime.jsx(
1442
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
1443
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
1444
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1445
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Reference" }),
1446
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Type" }),
1447
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Recipient" }),
1448
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Amount" }),
1449
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Status" }),
1450
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Source" }),
1451
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Date" }),
1452
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: "text-right", children: "Actions" })
1453
+ ] }) }),
1454
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: groupByJob ? documentGroups.slice(0, displayLimit).map((group) => {
1455
+ const isExpanded = !!expandedGroups[group.groupId];
1456
+ const doc = group.primaryDoc;
1457
+ const isPaid = doc.payment_status === "paid" || doc.status === "paid";
1458
+ const isZoho = doc.source === "zoho";
1459
+ const hasMultiple = group.documents.length > 1;
1460
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
1461
+ /* @__PURE__ */ jsxRuntime.jsxs(
1462
+ ui.Table.Row,
1463
+ {
1464
+ className: `transition-colors ${isExpanded ? "bg-ui-bg-subtle" : "hover:bg-ui-bg-subtle-hover"}`,
1465
+ children: [
1466
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
1467
+ hasMultiple ? /* @__PURE__ */ jsxRuntime.jsx(
1403
1468
  "button",
1404
1469
  {
1405
1470
  type: "button",
1406
- onClick: () => handleViewDocument(doc.id, doc.display_id),
1407
- className: "font-medium text-ui-fg-interactive hover:underline text-left cursor-pointer bg-transparent border-0 p-0",
1408
- children: doc.display_id
1409
- }
1410
- ),
1411
- hasMultiple && /* @__PURE__ */ jsxRuntime.jsxs(
1412
- ui.Badge,
1413
- {
1414
- size: "2xsmall",
1415
- color: "purple",
1416
- className: "cursor-pointer hover:opacity-80 transition-opacity",
1417
1471
  onClick: () => toggleGroup(group.groupId),
1418
- children: [
1419
- group.documents.length,
1420
- " docs"
1421
- ]
1472
+ className: "p-1 rounded hover:bg-ui-bg-base text-ui-fg-subtle hover:text-ui-fg-base cursor-pointer transition-colors",
1473
+ title: isExpanded ? "Collapse related documents" : `Expand ${group.documents.length} related documents`,
1474
+ children: isExpanded ? /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDown, { className: "w-4 h-4 text-purple-600" }) : /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRight, { className: "w-4 h-4 text-ui-fg-subtle" })
1422
1475
  }
1423
- )
1424
- ] })
1425
- ] }) }),
1426
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1427
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-ui-fg-base", children: doc.title }),
1428
- hasMultiple && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-ui-fg-subtle truncate max-w-[220px]", title: group.includedTypesSummary, children: [
1429
- "Includes: ",
1430
- group.includedTypesSummary
1431
- ] })
1432
- ] }) }),
1433
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1434
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: group.customerName || "Guest" }),
1435
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-ui-fg-subtle", children: group.customerEmail || group.customerPhone || "-" })
1436
- ] }) }),
1437
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold", children: formatCurrency(group.totalAmount, group.currencyCode) }) }),
1438
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: isPaid ? "green" : doc.payment_status === "unpaid" ? "red" : "blue", size: "small", children: doc.payment_status || doc.status }) }),
1439
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: isZoho ? "purple" : "grey", size: "small", children: isZoho ? "Zoho Books" : "PDFKit" }) }),
1440
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-ui-fg-subtle", children: new Date(group.latestCreatedAt).toLocaleDateString() }) }),
1441
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-1.5", children: [
1442
- hasMultiple && /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
1443
- /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
1444
- "button",
1445
- {
1446
- type: "button",
1447
- className: "flex items-center gap-1 text-[11px] font-medium px-2 py-1 rounded bg-ui-bg-subtle hover:bg-ui-bg-base border border-ui-border-base text-ui-fg-base transition-colors",
1448
- title: "View all related documents for this job/order",
1449
- children: [
1450
- /* @__PURE__ */ jsxRuntime.jsx(icons.DocumentText, { className: "w-3.5 h-3.5 text-purple-600" }),
1451
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1452
- "Docs (",
1476
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-5 inline-block" }),
1477
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 flex-wrap", children: [
1478
+ /* @__PURE__ */ jsxRuntime.jsx(
1479
+ "button",
1480
+ {
1481
+ type: "button",
1482
+ onClick: () => handleViewDocument(doc.id, doc.display_id),
1483
+ className: "font-medium text-ui-fg-interactive hover:underline text-left cursor-pointer bg-transparent border-0 p-0",
1484
+ children: doc.display_id
1485
+ }
1486
+ ),
1487
+ hasMultiple && /* @__PURE__ */ jsxRuntime.jsxs(
1488
+ ui.Badge,
1489
+ {
1490
+ size: "2xsmall",
1491
+ color: "purple",
1492
+ className: "cursor-pointer hover:opacity-80 transition-opacity",
1493
+ onClick: () => toggleGroup(group.groupId),
1494
+ children: [
1453
1495
  group.documents.length,
1454
- ")"
1455
- ] }),
1456
- /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDown, { className: "w-3 h-3 text-ui-fg-subtle" })
1457
- ]
1458
- }
1459
- ) }),
1460
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { align: "end", className: "w-72 p-1.5 z-50", children: [
1461
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Label, { className: "text-xs font-semibold px-2 py-1.5 text-ui-fg-muted", children: [
1462
- "Related Documents (",
1463
- group.documents.length,
1464
- ")"
1465
- ] }),
1466
- /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Separator, {}),
1467
- group.documents.map((subDoc) => /* @__PURE__ */ jsxRuntime.jsxs(
1468
- ui.DropdownMenu.Item,
1496
+ " docs"
1497
+ ]
1498
+ }
1499
+ )
1500
+ ] })
1501
+ ] }) }),
1502
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1503
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-ui-fg-base", children: doc.title }),
1504
+ hasMultiple && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-ui-fg-subtle truncate max-w-[220px]", title: group.includedTypesSummary, children: [
1505
+ "Includes: ",
1506
+ group.includedTypesSummary
1507
+ ] })
1508
+ ] }) }),
1509
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1510
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: group.customerName || "Guest" }),
1511
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-ui-fg-subtle", children: group.customerEmail || group.customerPhone || "-" })
1512
+ ] }) }),
1513
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold", children: formatCurrency(group.totalAmount, group.currencyCode) }) }),
1514
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: isPaid ? "green" : doc.payment_status === "unpaid" ? "red" : "blue", size: "small", children: doc.payment_status || doc.status }) }),
1515
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: isZoho ? "purple" : "grey", size: "small", children: isZoho ? "Zoho Books" : "PDFKit" }) }),
1516
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-ui-fg-subtle", children: new Date(group.latestCreatedAt).toLocaleDateString() }) }),
1517
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-1.5", children: [
1518
+ hasMultiple && /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
1519
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
1520
+ "button",
1469
1521
  {
1470
- onClick: () => handleViewDocument(subDoc.id, subDoc.display_id),
1471
- className: "flex items-center justify-between px-2 py-2 cursor-pointer hover:bg-ui-bg-subtle-hover rounded text-xs transition-colors",
1522
+ type: "button",
1523
+ className: "flex items-center gap-1 text-[11px] font-medium px-2 py-1 rounded bg-ui-bg-subtle hover:bg-ui-bg-base border border-ui-border-base text-ui-fg-base transition-colors",
1524
+ title: "View all related documents for this job/order",
1472
1525
  children: [
1473
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col text-left", children: [
1474
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: subDoc.title }),
1475
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-ui-fg-subtle", children: subDoc.display_id })
1526
+ /* @__PURE__ */ jsxRuntime.jsx(icons.DocumentText, { className: "w-3.5 h-3.5 text-purple-600" }),
1527
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1528
+ "Docs (",
1529
+ group.documents.length,
1530
+ ")"
1476
1531
  ] }),
1477
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1478
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-semibold text-ui-fg-base", children: subDoc.total_amount != null && Number(subDoc.total_amount) > 0 ? formatCurrency(subDoc.total_amount, subDoc.currency_code) : "—" }),
1479
- /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownTray, { className: "w-3.5 h-3.5 text-ui-fg-subtle" })
1480
- ] })
1532
+ /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDown, { className: "w-3 h-3 text-ui-fg-subtle" })
1481
1533
  ]
1482
- },
1483
- subDoc.id
1484
- ))
1485
- ] })
1486
- ] }),
1487
- /* @__PURE__ */ jsxRuntime.jsx(
1488
- "button",
1489
- {
1490
- type: "button",
1491
- onClick: () => handleViewDocument(doc.id, doc.display_id),
1492
- className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base cursor-pointer",
1493
- title: "View / Download PDF",
1494
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownTray, { className: "w-4 h-4" })
1495
- }
1496
- ),
1497
- (doc.type === "invoice" || doc.type === "estimate" || doc.type === "quote") && /* @__PURE__ */ jsxRuntime.jsx(
1498
- "button",
1499
- {
1500
- type: "button",
1501
- onClick: () => handleOpenEditModal(doc),
1502
- className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-purple-600 cursor-pointer",
1503
- title: "Edit Quote / Invoice & Sync with Zoho Books",
1504
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, { className: "w-4 h-4" })
1505
- }
1506
- ),
1507
- /* @__PURE__ */ jsxRuntime.jsx(
1508
- "button",
1509
- {
1510
- onClick: () => {
1511
- setSelectedDoc(doc);
1512
- setSendForm({
1513
- channels: ["email"],
1514
- custom_message: "",
1515
- subject: `${settings.company_name}: ${doc.title} #${doc.display_id}`
1516
- });
1517
- setSendModalOpen(true);
1518
- },
1519
- className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base",
1520
- title: "Send via Email / SMS / WhatsApp",
1521
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.Envelope, { className: "w-4 h-4" })
1522
- }
1523
- ),
1524
- !isZoho && settings.zoho_books_enabled && (doc.type === "invoice" || doc.type === "estimate") && Number(doc.total_amount || 0) > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1525
- ui.Button,
1526
- {
1527
- variant: "transparent",
1528
- size: "small",
1529
- onClick: () => handleSyncToZoho(doc.id),
1530
- className: "text-xs text-purple-600 hover:text-purple-700",
1531
- children: "Push Zoho"
1532
- }
1533
- ),
1534
- doc.short_payment_link && /* @__PURE__ */ jsxRuntime.jsx(
1535
- "button",
1536
- {
1537
- onClick: () => {
1538
- navigator.clipboard.writeText(doc.short_payment_link);
1539
- alert("Short payment link copied to clipboard!");
1540
- },
1541
- className: "text-[11px] text-ui-fg-interactive hover:underline px-1.5 py-1",
1542
- title: "Copy Short Payment Link",
1543
- children: "Copy Link"
1544
- }
1545
- ),
1546
- /* @__PURE__ */ jsxRuntime.jsx(
1547
- "button",
1548
- {
1549
- type: "button",
1550
- onClick: () => {
1551
- if (doc.repair_ticket_id) {
1552
- handleDeleteRepairDocuments(doc.repair_ticket_id);
1553
- } else {
1554
- handleDeleteDocument(doc.id);
1555
1534
  }
1556
- },
1557
- className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-red-600 transition-colors",
1558
- title: doc.repair_ticket_id ? "Delete / Reset All Documents for this Repair Ticket (including in Zoho Books)" : "Delete Document Record",
1559
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "w-4 h-4 text-red-500 hover:text-red-700" })
1560
- }
1561
- )
1562
- ] }) })
1563
- ]
1564
- }
1565
- ),
1566
- isExpanded && hasMultiple && /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { className: "bg-ui-bg-subtle hover:bg-ui-bg-subtle border-b border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { colSpan: 8, className: "p-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-3 px-6 bg-ui-bg-subtle/80 border-l-4 border-l-purple-500 my-1 mx-2 rounded-r-md", children: [
1567
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
1568
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1569
- /* @__PURE__ */ jsxRuntime.jsx(icons.DocumentText, { className: "w-4 h-4 text-purple-600" }),
1570
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-semibold text-ui-fg-base", children: [
1571
- "Related Documents for this Job / Order (",
1572
- group.documents.length,
1573
- ")"
1574
- ] })
1575
- ] }),
1576
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1577
- group.repair_ticket_id && /* @__PURE__ */ jsxRuntime.jsxs(
1578
- "button",
1579
- {
1580
- type: "button",
1581
- onClick: () => handleDeleteRepairDocuments(group.repair_ticket_id),
1582
- className: "text-[11px] text-red-600 hover:text-red-700 hover:underline flex items-center gap-1 font-medium",
1583
- title: "Delete all generated documents for this repair job in database & Zoho Books to allow clean regeneration",
1584
- children: [
1585
- /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "w-3 h-3" }),
1586
- " Reset / Delete Job Documents"
1587
- ]
1588
- }
1589
- ),
1590
- /* @__PURE__ */ jsxRuntime.jsx(
1591
- "button",
1592
- {
1593
- type: "button",
1594
- onClick: () => toggleGroup(group.groupId),
1595
- className: "text-[11px] text-ui-fg-interactive hover:underline",
1596
- children: "Collapse"
1597
- }
1598
- )
1599
- ] })
1600
- ] }),
1601
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded border border-ui-border-base bg-ui-bg-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left border-collapse", children: [
1602
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-ui-border-base bg-ui-bg-subtle text-[11px] text-ui-fg-muted font-medium", children: [
1603
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Document Type" }),
1604
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Reference" }),
1605
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Amount" }),
1606
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Status" }),
1607
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Source" }),
1608
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Created Date" }),
1609
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3 text-right", children: "Actions" })
1610
- ] }) }),
1611
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-base text-xs", children: group.documents.map((subDoc) => {
1612
- const subIsPaid = subDoc.payment_status === "paid" || subDoc.status === "paid";
1613
- const subIsZoho = subDoc.source === "zoho";
1614
- return /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "hover:bg-ui-bg-subtle-hover transition-colors", children: [
1615
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3", children: /* @__PURE__ */ jsxRuntime.jsx(
1616
- ui.Badge,
1617
- {
1618
- size: "2xsmall",
1619
- color: subDoc.type === "invoice" ? "green" : subDoc.type === "estimate" ? "blue" : subDoc.type === "job_card" ? "orange" : subDoc.type === "receipt" ? "purple" : "grey",
1620
- children: subDoc.title
1621
- }
1622
- ) }),
1623
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3 font-medium", children: /* @__PURE__ */ jsxRuntime.jsx(
1624
- "button",
1625
- {
1626
- type: "button",
1627
- onClick: () => handleViewDocument(subDoc.id, subDoc.display_id),
1628
- className: "text-ui-fg-interactive hover:underline text-left cursor-pointer bg-transparent border-0 p-0 font-medium",
1629
- children: subDoc.display_id
1630
- }
1631
- ) }),
1632
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3 font-semibold text-ui-fg-base", children: subDoc.total_amount != null && Number(subDoc.total_amount) > 0 ? formatCurrency(subDoc.total_amount, subDoc.currency_code) : "—" }),
1633
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3", children: /* @__PURE__ */ jsxRuntime.jsx(
1634
- ui.Badge,
1635
- {
1636
- size: "2xsmall",
1637
- color: subIsPaid ? "green" : subDoc.payment_status === "unpaid" ? "red" : "blue",
1638
- children: subDoc.payment_status || subDoc.status
1639
- }
1640
- ) }),
1641
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: subIsZoho ? "purple" : "grey", children: subIsZoho ? "Zoho Books" : "PDFKit" }) }),
1642
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3 text-ui-fg-subtle text-[11px]", children: new Date(subDoc.created_at).toLocaleString() }),
1643
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3 text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-1.5", children: [
1535
+ ) }),
1536
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { align: "end", className: "w-72 p-1.5 z-50", children: [
1537
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Label, { className: "text-xs font-semibold px-2 py-1.5 text-ui-fg-muted", children: [
1538
+ "Related Documents (",
1539
+ group.documents.length,
1540
+ ")"
1541
+ ] }),
1542
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Separator, {}),
1543
+ group.documents.map((subDoc) => /* @__PURE__ */ jsxRuntime.jsxs(
1544
+ ui.DropdownMenu.Item,
1545
+ {
1546
+ onClick: () => handleViewDocument(subDoc.id, subDoc.display_id),
1547
+ className: "flex items-center justify-between px-2 py-2 cursor-pointer hover:bg-ui-bg-subtle-hover rounded text-xs transition-colors",
1548
+ children: [
1549
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col text-left", children: [
1550
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: subDoc.title }),
1551
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-ui-fg-subtle", children: subDoc.display_id })
1552
+ ] }),
1553
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1554
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-semibold text-ui-fg-base", children: subDoc.total_amount != null && Number(subDoc.total_amount) > 0 ? formatCurrency(subDoc.total_amount, subDoc.currency_code) : "—" }),
1555
+ /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownTray, { className: "w-3.5 h-3.5 text-ui-fg-subtle" })
1556
+ ] })
1557
+ ]
1558
+ },
1559
+ subDoc.id
1560
+ ))
1561
+ ] })
1562
+ ] }),
1644
1563
  /* @__PURE__ */ jsxRuntime.jsx(
1645
1564
  "button",
1646
1565
  {
1647
1566
  type: "button",
1648
- onClick: () => handleViewDocument(subDoc.id, subDoc.display_id),
1649
- className: "p-1 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base",
1567
+ onClick: () => handleViewDocument(doc.id, doc.display_id),
1568
+ className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base cursor-pointer",
1650
1569
  title: "View / Download PDF",
1651
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownTray, { className: "w-3.5 h-3.5" })
1570
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownTray, { className: "w-4 h-4" })
1652
1571
  }
1653
1572
  ),
1654
- (subDoc.type === "invoice" || subDoc.type === "estimate" || subDoc.type === "quote") && /* @__PURE__ */ jsxRuntime.jsx(
1573
+ (doc.type === "invoice" || doc.type === "estimate" || doc.type === "quote") && /* @__PURE__ */ jsxRuntime.jsx(
1655
1574
  "button",
1656
1575
  {
1657
1576
  type: "button",
1658
- onClick: () => handleOpenEditModal(subDoc),
1659
- className: "p-1 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-purple-600",
1577
+ onClick: () => handleOpenEditModal(doc),
1578
+ className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-purple-600 cursor-pointer",
1660
1579
  title: "Edit Quote / Invoice & Sync with Zoho Books",
1661
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, { className: "w-3.5 h-3.5" })
1580
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, { className: "w-4 h-4" })
1662
1581
  }
1663
1582
  ),
1664
1583
  /* @__PURE__ */ jsxRuntime.jsx(
1665
1584
  "button",
1666
1585
  {
1667
- type: "button",
1668
1586
  onClick: () => {
1669
- setSelectedDoc(subDoc);
1587
+ setSelectedDoc(doc);
1670
1588
  setSendForm({
1671
1589
  channels: ["email"],
1672
1590
  custom_message: "",
1673
- subject: `${settings.company_name}: ${subDoc.title} #${subDoc.display_id}`
1591
+ subject: `${settings.company_name}: ${doc.title} #${doc.display_id}`
1674
1592
  });
1675
1593
  setSendModalOpen(true);
1676
1594
  },
1677
- className: "p-1 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base",
1678
- title: "Send Document",
1679
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.Envelope, { className: "w-3.5 h-3.5" })
1595
+ className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base",
1596
+ title: "Send via Email / SMS / WhatsApp",
1597
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Envelope, { className: "w-4 h-4" })
1680
1598
  }
1681
1599
  ),
1682
- !subIsZoho && settings.zoho_books_enabled && (subDoc.type === "invoice" || subDoc.type === "estimate") && Number(subDoc.total_amount || 0) > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1600
+ !isZoho && settings.zoho_books_enabled && (doc.type === "invoice" || doc.type === "estimate") && Number(doc.total_amount || 0) > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1683
1601
  ui.Button,
1684
1602
  {
1685
1603
  variant: "transparent",
1686
1604
  size: "small",
1687
- onClick: () => handleSyncToZoho(subDoc.id),
1688
- className: "text-[11px] text-purple-600 hover:text-purple-700 py-0.5 px-1.5",
1605
+ onClick: () => handleSyncToZoho(doc.id),
1606
+ className: "text-xs text-purple-600 hover:text-purple-700",
1689
1607
  children: "Push Zoho"
1690
1608
  }
1691
1609
  ),
1692
- subDoc.short_payment_link && /* @__PURE__ */ jsxRuntime.jsx(
1610
+ doc.short_payment_link && /* @__PURE__ */ jsxRuntime.jsx(
1693
1611
  "button",
1694
1612
  {
1695
1613
  onClick: () => {
1696
- navigator.clipboard.writeText(subDoc.short_payment_link);
1614
+ navigator.clipboard.writeText(doc.short_payment_link);
1697
1615
  alert("Short payment link copied to clipboard!");
1698
1616
  },
1699
- className: "text-[10px] text-ui-fg-interactive hover:underline px-1 py-0.5",
1700
- title: "Copy Short Link",
1617
+ className: "text-[11px] text-ui-fg-interactive hover:underline px-1.5 py-1",
1618
+ title: "Copy Short Payment Link",
1701
1619
  children: "Copy Link"
1702
1620
  }
1703
1621
  ),
@@ -1706,124 +1624,319 @@ const DocumentsPage = () => {
1706
1624
  {
1707
1625
  type: "button",
1708
1626
  onClick: () => {
1709
- if (subDoc.repair_ticket_id) {
1710
- handleDeleteRepairDocuments(subDoc.repair_ticket_id);
1627
+ if (doc.repair_ticket_id) {
1628
+ handleDeleteRepairDocuments(doc.repair_ticket_id);
1711
1629
  } else {
1712
- handleDeleteDocument(subDoc.id);
1630
+ handleDeleteDocument(doc.id);
1713
1631
  }
1714
1632
  },
1715
- className: "p-1 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-red-600 transition-colors",
1716
- title: subDoc.repair_ticket_id ? "Delete / Reset All Documents for this Repair Ticket (including in Zoho Books)" : "Delete Document Record",
1717
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "w-3.5 h-3.5 text-red-500 hover:text-red-700" })
1633
+ className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-red-600 transition-colors",
1634
+ title: doc.repair_ticket_id ? "Delete / Reset All Documents for this Repair Ticket (including in Zoho Books)" : "Delete Document Record",
1635
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "w-4 h-4 text-red-500 hover:text-red-700" })
1718
1636
  }
1719
1637
  )
1720
1638
  ] }) })
1721
- ] }, subDoc.id);
1722
- }) })
1723
- ] }) })
1724
- ] }) }) })
1725
- ] }, group.groupId);
1726
- }) : filteredDocs.map((doc) => {
1727
- const isPaid = doc.payment_status === "paid" || doc.status === "paid";
1728
- const isZoho = doc.source === "zoho";
1729
- return /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { className: "hover:bg-ui-bg-subtle-hover transition-colors", children: [
1730
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
1731
- "button",
1732
- {
1733
- type: "button",
1734
- onClick: () => handleViewDocument(doc.id, doc.display_id),
1735
- className: "font-medium text-ui-fg-interactive hover:underline text-left cursor-pointer bg-transparent border-0 p-0",
1736
- children: doc.display_id
1737
- }
1738
- ) }),
1739
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-ui-fg-base", children: doc.title }) }),
1740
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1741
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: doc.customer_name || "Guest" }),
1742
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-ui-fg-subtle", children: doc.customer_email || doc.customer_phone || "-" })
1743
- ] }) }),
1744
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold", children: formatCurrency(doc.total_amount, doc.currency_code) }) }),
1745
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: isPaid ? "green" : doc.payment_status === "unpaid" ? "red" : "blue", size: "small", children: doc.payment_status || doc.status }) }),
1746
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: isZoho ? "purple" : "grey", size: "small", children: isZoho ? "Zoho Books" : "PDFKit" }) }),
1747
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-ui-fg-subtle", children: new Date(doc.created_at).toLocaleDateString() }) }),
1748
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-1.5", children: [
1749
- /* @__PURE__ */ jsxRuntime.jsx(
1750
- "button",
1751
- {
1752
- type: "button",
1753
- onClick: () => handleViewDocument(doc.id, doc.display_id),
1754
- className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base cursor-pointer",
1755
- title: "View / Download PDF",
1756
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownTray, { className: "w-4 h-4" })
1757
- }
1758
- ),
1759
- (doc.type === "invoice" || doc.type === "estimate" || doc.type === "quote") && /* @__PURE__ */ jsxRuntime.jsx(
1760
- "button",
1761
- {
1762
- type: "button",
1763
- onClick: () => handleOpenEditModal(doc),
1764
- className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-purple-600 cursor-pointer",
1765
- title: "Edit Quote / Invoice & Sync with Zoho Books",
1766
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, { className: "w-4 h-4" })
1767
- }
1768
- ),
1769
- /* @__PURE__ */ jsxRuntime.jsx(
1770
- "button",
1771
- {
1772
- onClick: () => {
1773
- setSelectedDoc(doc);
1774
- setSendForm({
1775
- channels: ["email"],
1776
- custom_message: "",
1777
- subject: `${settings.company_name}: ${doc.title} #${doc.display_id}`
1778
- });
1779
- setSendModalOpen(true);
1780
- },
1781
- className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base",
1782
- title: "Send via Email / SMS / WhatsApp",
1783
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.Envelope, { className: "w-4 h-4" })
1784
- }
1785
- ),
1786
- !isZoho && settings.zoho_books_enabled && (doc.type === "invoice" || doc.type === "estimate") && Number(doc.total_amount || 0) > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1787
- ui.Button,
1788
- {
1789
- variant: "transparent",
1790
- size: "small",
1791
- onClick: () => handleSyncToZoho(doc.id),
1792
- className: "text-xs text-purple-600 hover:text-purple-700",
1793
- children: "Push Zoho"
1794
- }
1795
- ),
1796
- doc.short_payment_link && /* @__PURE__ */ jsxRuntime.jsx(
1797
- "button",
1798
- {
1799
- onClick: () => {
1800
- navigator.clipboard.writeText(doc.short_payment_link);
1801
- alert("Short payment link copied to clipboard!");
1802
- },
1803
- className: "text-[11px] text-ui-fg-interactive hover:underline px-1.5 py-1",
1804
- title: "Copy Short Payment Link",
1805
- children: "Copy Link"
1639
+ ]
1806
1640
  }
1807
1641
  ),
1808
- /* @__PURE__ */ jsxRuntime.jsx(
1642
+ isExpanded && hasMultiple && /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { className: "bg-ui-bg-subtle hover:bg-ui-bg-subtle border-b border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { colSpan: 8, className: "p-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-3 px-6 bg-ui-bg-subtle/80 border-l-4 border-l-purple-500 my-1 mx-2 rounded-r-md", children: [
1643
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
1644
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1645
+ /* @__PURE__ */ jsxRuntime.jsx(icons.DocumentText, { className: "w-4 h-4 text-purple-600" }),
1646
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-semibold text-ui-fg-base", children: [
1647
+ "Related Documents for this Job / Order (",
1648
+ group.documents.length,
1649
+ ")"
1650
+ ] })
1651
+ ] }),
1652
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1653
+ group.repair_ticket_id && /* @__PURE__ */ jsxRuntime.jsxs(
1654
+ "button",
1655
+ {
1656
+ type: "button",
1657
+ onClick: () => handleDeleteRepairDocuments(group.repair_ticket_id),
1658
+ className: "text-[11px] text-red-600 hover:text-red-700 hover:underline flex items-center gap-1 font-medium",
1659
+ title: "Delete all generated documents for this repair job in database & Zoho Books to allow clean regeneration",
1660
+ children: [
1661
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "w-3 h-3" }),
1662
+ " Reset / Delete Job Documents"
1663
+ ]
1664
+ }
1665
+ ),
1666
+ /* @__PURE__ */ jsxRuntime.jsx(
1667
+ "button",
1668
+ {
1669
+ type: "button",
1670
+ onClick: () => toggleGroup(group.groupId),
1671
+ className: "text-[11px] text-ui-fg-interactive hover:underline",
1672
+ children: "Collapse"
1673
+ }
1674
+ )
1675
+ ] })
1676
+ ] }),
1677
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded border border-ui-border-base bg-ui-bg-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left border-collapse", children: [
1678
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-ui-border-base bg-ui-bg-subtle text-[11px] text-ui-fg-muted font-medium", children: [
1679
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Document Type" }),
1680
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Reference" }),
1681
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Amount" }),
1682
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Status" }),
1683
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Source" }),
1684
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3", children: "Created Date" }),
1685
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "py-1.5 px-3 text-right", children: "Actions" })
1686
+ ] }) }),
1687
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-base text-xs", children: group.documents.map((subDoc) => {
1688
+ const subIsPaid = subDoc.payment_status === "paid" || subDoc.status === "paid";
1689
+ const subIsZoho = subDoc.source === "zoho";
1690
+ return /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "hover:bg-ui-bg-subtle-hover transition-colors", children: [
1691
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3", children: /* @__PURE__ */ jsxRuntime.jsx(
1692
+ ui.Badge,
1693
+ {
1694
+ size: "2xsmall",
1695
+ color: subDoc.type === "invoice" ? "green" : subDoc.type === "estimate" ? "blue" : subDoc.type === "job_card" ? "orange" : subDoc.type === "receipt" ? "purple" : "grey",
1696
+ children: subDoc.title
1697
+ }
1698
+ ) }),
1699
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3 font-medium", children: /* @__PURE__ */ jsxRuntime.jsx(
1700
+ "button",
1701
+ {
1702
+ type: "button",
1703
+ onClick: () => handleViewDocument(subDoc.id, subDoc.display_id),
1704
+ className: "text-ui-fg-interactive hover:underline text-left cursor-pointer bg-transparent border-0 p-0 font-medium",
1705
+ children: subDoc.display_id
1706
+ }
1707
+ ) }),
1708
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3 font-semibold text-ui-fg-base", children: subDoc.total_amount != null && Number(subDoc.total_amount) > 0 ? formatCurrency(subDoc.total_amount, subDoc.currency_code) : "—" }),
1709
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3", children: /* @__PURE__ */ jsxRuntime.jsx(
1710
+ ui.Badge,
1711
+ {
1712
+ size: "2xsmall",
1713
+ color: subIsPaid ? "green" : subDoc.payment_status === "unpaid" ? "red" : "blue",
1714
+ children: subDoc.payment_status || subDoc.status
1715
+ }
1716
+ ) }),
1717
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: subIsZoho ? "purple" : "grey", children: subIsZoho ? "Zoho Books" : "PDFKit" }) }),
1718
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3 text-ui-fg-subtle text-[11px]", children: new Date(subDoc.created_at).toLocaleString() }),
1719
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 px-3 text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-1.5", children: [
1720
+ /* @__PURE__ */ jsxRuntime.jsx(
1721
+ "button",
1722
+ {
1723
+ type: "button",
1724
+ onClick: () => handleViewDocument(subDoc.id, subDoc.display_id),
1725
+ className: "p-1 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base",
1726
+ title: "View / Download PDF",
1727
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownTray, { className: "w-3.5 h-3.5" })
1728
+ }
1729
+ ),
1730
+ (subDoc.type === "invoice" || subDoc.type === "estimate" || subDoc.type === "quote") && /* @__PURE__ */ jsxRuntime.jsx(
1731
+ "button",
1732
+ {
1733
+ type: "button",
1734
+ onClick: () => handleOpenEditModal(subDoc),
1735
+ className: "p-1 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-purple-600",
1736
+ title: "Edit Quote / Invoice & Sync with Zoho Books",
1737
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, { className: "w-3.5 h-3.5" })
1738
+ }
1739
+ ),
1740
+ /* @__PURE__ */ jsxRuntime.jsx(
1741
+ "button",
1742
+ {
1743
+ type: "button",
1744
+ onClick: () => {
1745
+ setSelectedDoc(subDoc);
1746
+ setSendForm({
1747
+ channels: ["email"],
1748
+ custom_message: "",
1749
+ subject: `${settings.company_name}: ${subDoc.title} #${subDoc.display_id}`
1750
+ });
1751
+ setSendModalOpen(true);
1752
+ },
1753
+ className: "p-1 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base",
1754
+ title: "Send Document",
1755
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Envelope, { className: "w-3.5 h-3.5" })
1756
+ }
1757
+ ),
1758
+ !subIsZoho && settings.zoho_books_enabled && (subDoc.type === "invoice" || subDoc.type === "estimate") && Number(subDoc.total_amount || 0) > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1759
+ ui.Button,
1760
+ {
1761
+ variant: "transparent",
1762
+ size: "small",
1763
+ onClick: () => handleSyncToZoho(subDoc.id),
1764
+ className: "text-[11px] text-purple-600 hover:text-purple-700 py-0.5 px-1.5",
1765
+ children: "Push Zoho"
1766
+ }
1767
+ ),
1768
+ subDoc.short_payment_link && /* @__PURE__ */ jsxRuntime.jsx(
1769
+ "button",
1770
+ {
1771
+ onClick: () => {
1772
+ navigator.clipboard.writeText(subDoc.short_payment_link);
1773
+ alert("Short payment link copied to clipboard!");
1774
+ },
1775
+ className: "text-[10px] text-ui-fg-interactive hover:underline px-1 py-0.5",
1776
+ title: "Copy Short Link",
1777
+ children: "Copy Link"
1778
+ }
1779
+ ),
1780
+ /* @__PURE__ */ jsxRuntime.jsx(
1781
+ "button",
1782
+ {
1783
+ type: "button",
1784
+ onClick: () => {
1785
+ if (subDoc.repair_ticket_id) {
1786
+ handleDeleteRepairDocuments(subDoc.repair_ticket_id);
1787
+ } else {
1788
+ handleDeleteDocument(subDoc.id);
1789
+ }
1790
+ },
1791
+ className: "p-1 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-red-600 transition-colors",
1792
+ title: subDoc.repair_ticket_id ? "Delete / Reset All Documents for this Repair Ticket (including in Zoho Books)" : "Delete Document Record",
1793
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "w-3.5 h-3.5 text-red-500 hover:text-red-700" })
1794
+ }
1795
+ )
1796
+ ] }) })
1797
+ ] }, subDoc.id);
1798
+ }) })
1799
+ ] }) })
1800
+ ] }) }) })
1801
+ ] }, group.groupId);
1802
+ }) : filteredDocs.slice(0, displayLimit).map((doc) => {
1803
+ const isPaid = doc.payment_status === "paid" || doc.status === "paid";
1804
+ const isZoho = doc.source === "zoho";
1805
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { className: "hover:bg-ui-bg-subtle-hover transition-colors", children: [
1806
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
1809
1807
  "button",
1810
1808
  {
1811
1809
  type: "button",
1812
- onClick: () => {
1813
- if (doc.repair_ticket_id) {
1814
- handleDeleteRepairDocuments(doc.repair_ticket_id);
1815
- } else {
1816
- handleDeleteDocument(doc.id);
1817
- }
1818
- },
1819
- className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-red-600 transition-colors",
1820
- title: doc.repair_ticket_id ? "Delete / Reset All Documents for this Repair Ticket (including in Zoho Books)" : "Delete Document Record",
1821
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "w-4 h-4 text-red-500 hover:text-red-700" })
1810
+ onClick: () => handleViewDocument(doc.id, doc.display_id),
1811
+ className: "font-medium text-ui-fg-interactive hover:underline text-left cursor-pointer bg-transparent border-0 p-0",
1812
+ children: doc.display_id
1822
1813
  }
1823
- )
1824
- ] }) })
1825
- ] }, doc.id);
1826
- }) })
1814
+ ) }),
1815
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-ui-fg-base", children: doc.title }) }),
1816
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1817
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: doc.customer_name || "Guest" }),
1818
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-ui-fg-subtle", children: doc.customer_email || doc.customer_phone || "-" })
1819
+ ] }) }),
1820
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold", children: formatCurrency(doc.total_amount, doc.currency_code) }) }),
1821
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: isPaid ? "green" : doc.payment_status === "unpaid" ? "red" : "blue", size: "small", children: doc.payment_status || doc.status }) }),
1822
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: isZoho ? "purple" : "grey", size: "small", children: isZoho ? "Zoho Books" : "PDFKit" }) }),
1823
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-ui-fg-subtle", children: new Date(doc.created_at).toLocaleDateString() }) }),
1824
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-1.5", children: [
1825
+ /* @__PURE__ */ jsxRuntime.jsx(
1826
+ "button",
1827
+ {
1828
+ type: "button",
1829
+ onClick: () => handleViewDocument(doc.id, doc.display_id),
1830
+ className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base cursor-pointer",
1831
+ title: "View / Download PDF",
1832
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownTray, { className: "w-4 h-4" })
1833
+ }
1834
+ ),
1835
+ (doc.type === "invoice" || doc.type === "estimate" || doc.type === "quote") && /* @__PURE__ */ jsxRuntime.jsx(
1836
+ "button",
1837
+ {
1838
+ type: "button",
1839
+ onClick: () => handleOpenEditModal(doc),
1840
+ className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-purple-600 cursor-pointer",
1841
+ title: "Edit Quote / Invoice & Sync with Zoho Books",
1842
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, { className: "w-4 h-4" })
1843
+ }
1844
+ ),
1845
+ /* @__PURE__ */ jsxRuntime.jsx(
1846
+ "button",
1847
+ {
1848
+ onClick: () => {
1849
+ setSelectedDoc(doc);
1850
+ setSendForm({
1851
+ channels: ["email"],
1852
+ custom_message: "",
1853
+ subject: `${settings.company_name}: ${doc.title} #${doc.display_id}`
1854
+ });
1855
+ setSendModalOpen(true);
1856
+ },
1857
+ className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-ui-fg-base",
1858
+ title: "Send via Email / SMS / WhatsApp",
1859
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Envelope, { className: "w-4 h-4" })
1860
+ }
1861
+ ),
1862
+ !isZoho && settings.zoho_books_enabled && (doc.type === "invoice" || doc.type === "estimate") && Number(doc.total_amount || 0) > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1863
+ ui.Button,
1864
+ {
1865
+ variant: "transparent",
1866
+ size: "small",
1867
+ onClick: () => handleSyncToZoho(doc.id),
1868
+ className: "text-xs text-purple-600 hover:text-purple-700",
1869
+ children: "Push Zoho"
1870
+ }
1871
+ ),
1872
+ doc.short_payment_link && /* @__PURE__ */ jsxRuntime.jsx(
1873
+ "button",
1874
+ {
1875
+ onClick: () => {
1876
+ navigator.clipboard.writeText(doc.short_payment_link);
1877
+ alert("Short payment link copied to clipboard!");
1878
+ },
1879
+ className: "text-[11px] text-ui-fg-interactive hover:underline px-1.5 py-1",
1880
+ title: "Copy Short Payment Link",
1881
+ children: "Copy Link"
1882
+ }
1883
+ ),
1884
+ /* @__PURE__ */ jsxRuntime.jsx(
1885
+ "button",
1886
+ {
1887
+ type: "button",
1888
+ onClick: () => {
1889
+ if (doc.repair_ticket_id) {
1890
+ handleDeleteRepairDocuments(doc.repair_ticket_id);
1891
+ } else {
1892
+ handleDeleteDocument(doc.id);
1893
+ }
1894
+ },
1895
+ className: "p-1.5 rounded hover:bg-ui-bg-subtle text-ui-fg-subtle hover:text-red-600 transition-colors",
1896
+ title: doc.repair_ticket_id ? "Delete / Reset All Documents for this Repair Ticket (including in Zoho Books)" : "Delete Document Record",
1897
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "w-4 h-4 text-red-500 hover:text-red-700" })
1898
+ }
1899
+ )
1900
+ ] }) })
1901
+ ] }, doc.id);
1902
+ }) })
1903
+ ] }),
1904
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: sentinelRef, className: "h-6 w-full pointer-events-none" }),
1905
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row items-center justify-between p-4 border-t border-ui-border-base bg-ui-bg-subtle text-xs text-ui-fg-subtle gap-3", children: [
1906
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
1907
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1908
+ "Showing ",
1909
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "font-semibold text-ui-fg-base", children: Math.min(displayLimit, totalItemCount) }),
1910
+ " of",
1911
+ " ",
1912
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "font-semibold text-ui-fg-base", children: totalItemCount }),
1913
+ " ",
1914
+ groupByJob ? "jobs/orders" : "documents"
1915
+ ] }),
1916
+ totalBackendCount > documents.length && /* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { size: "2xsmall", color: "grey", children: [
1917
+ totalBackendCount,
1918
+ " total in database"
1919
+ ] }),
1920
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: "(capped at 100 per scroll batch)" })
1921
+ ] }),
1922
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1923
+ isLoadingMore && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-purple-600 font-medium", children: [
1924
+ /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, { className: "w-3.5 h-3.5 animate-spin" }),
1925
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Loading next batch..." })
1926
+ ] }),
1927
+ canLoadMore && !isLoadingMore && /* @__PURE__ */ jsxRuntime.jsx(
1928
+ ui.Button,
1929
+ {
1930
+ variant: "secondary",
1931
+ size: "small",
1932
+ onClick: handleLoadMore,
1933
+ className: "text-xs h-7",
1934
+ children: "Load More (+100)"
1935
+ }
1936
+ ),
1937
+ !canLoadMore && totalItemCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: "All documents loaded" })
1938
+ ] })
1939
+ ] })
1827
1940
  ] })
1828
1941
  ] }),
1829
1942
  activeTab === "templates" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 w-full flex flex-col gap-6", children: [