@fayz-ai/plugin-financial 0.21.0 → 0.21.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"CnabRemittanceModal.d.ts","sourceRoot":"","sources":["../../src/components/CnabRemittanceModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAgC,OAAO,EAAE,MAAM,UAAU,CAAA;AAkIlF,wBAAgB,mBAAmB,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;IACjF,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,QAAQ,EAAE,qBAAqB,CAAA;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,qBAqfA"}
1
+ {"version":3,"file":"CnabRemittanceModal.d.ts","sourceRoot":"","sources":["../../src/components/CnabRemittanceModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAgC,OAAO,EAAE,MAAM,UAAU,CAAA;AAmIlF,wBAAgB,mBAAmB,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;IACjF,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,QAAQ,EAAE,qBAAqB,CAAA;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,qBAqfA"}
@@ -1 +1 @@
1
- {"version":3,"file":"InstallmentRow.d.ts","sourceRoot":"","sources":["../../src/components/InstallmentRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GACrF,EAAE;IACD,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,iDAAiD;IACjD,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACzC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,qBAiCA;AAID,mFAAmF;AACnF,wBAAgB,oBAAoB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAmB,EAAE,EAAE;IAChG,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;CAChC,qBAeA;AAED,kDAAkD;AAClD,wBAAgB,uBAAuB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IACzE,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,IAAI,EAAE,KAAK,CAAC,WAAW,CAAA;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,qBAOA;AAED,oHAAoH;AACpH,wBAAgB,wBAAwB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;IACrF,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,qBAeA"}
1
+ {"version":3,"file":"InstallmentRow.d.ts","sourceRoot":"","sources":["../../src/components/InstallmentRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GACrF,EAAE;IACD,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,iDAAiD;IACjD,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACzC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,qBAiCA;AAID,mFAAmF;AACnF,wBAAgB,oBAAoB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAmB,EAAE,EAAE;IAChG,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;CAChC,qBAeA;AAED,kDAAkD;AAClD,wBAAgB,uBAAuB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IACzE,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,IAAI,EAAE,KAAK,CAAC,WAAW,CAAA;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,qBAOA;AAED,oHAAoH;AACpH,wBAAgB,wBAAwB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;IACrF,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,qBAkBA"}
@@ -1 +1 @@
1
- {"version":3,"file":"InvoiceAttachmentsModal.d.ts","sourceRoot":"","sources":["../../src/components/InvoiceAttachmentsModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAc1D;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE;IACzE,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB,qBAsIA"}
1
+ {"version":3,"file":"InvoiceAttachmentsModal.d.ts","sourceRoot":"","sources":["../../src/components/InvoiceAttachmentsModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAc1D;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE;IACzE,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB,qBA8IA"}
@@ -3,7 +3,9 @@ import React from 'react';
3
3
  * Devolve o `input` escondido (que precisa estar montado em algum lugar da
4
4
  * árvore) e o `open` que o abre.
5
5
  */
6
- export declare function useReceiptPicker(onPick: (dataUrl: string) => void): {
6
+ export declare function useReceiptPicker(onPick: (dataUrl: string) => void,
7
+ /** When given, a PDF is accepted too and handed over as a file (a bill, not a receipt). */
8
+ onPickDocument?: (file: File) => void): {
7
9
  open: () => void;
8
10
  input: React.ReactElement;
9
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ReceiptPicker.d.ts","sourceRoot":"","sources":["../../src/components/ReceiptPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiB,MAAM,OAAO,CAAA;AAsBrC;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG;IACnE,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,KAAK,EAAE,KAAK,CAAC,YAAY,CAAA;CAC1B,CAiCA"}
1
+ {"version":3,"file":"ReceiptPicker.d.ts","sourceRoot":"","sources":["../../src/components/ReceiptPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiB,MAAM,OAAO,CAAA;AAsBrC;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;AACjC,2FAA2F;AAC3F,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,GACpC;IACD,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,KAAK,EAAE,KAAK,CAAC,YAAY,CAAA;CAC1B,CAsCA"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React25 from 'react';
2
2
  import React25__default, { useState, useEffect, useMemo, useRef, useCallback } from 'react';
3
- import { recordRailFields, RECORD_GROUP, activeFacet, createConnectionStore, connectionSettings, connectionStatus, settingsStatus, connectionRuns, registerTranslations, getSupabaseClientOptional, createSafeDataProvider, registerMessageDefaults, reportDataError, useTranslation, createPendingCommand, useUnitMode, useDataChanged, countByTenant, tl, resolveDataProvider, useActiveUnitId, getActiveTenantId, emitDataChanged, exportCSV } from '@fayz-ai/core';
4
- import { INLINE_LINK_TONE, SearchSelect, ModalTask, toast, Button, useInModalTaskHost, useSaveBar, tourAnchor, DatePicker, SubpageHeader, defineKpiWidget, defineChartWidget, defineCustomWidget, defineTableWidget, Modal, ModalContent, ModalHeader, ModalTitle, ModalDescription, ModalBody, DataTable, Card, CardContent, Skeleton, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, MultiSelect, PageTransition, ModulePage, Badge, TooltipProvider, ConfirmDialog, CurrencyInput, Input, PageHeaderActions, ChoiceSelect, Hint, ModalFooter, PageTabs, Tooltip, TooltipTrigger, TooltipContent, Checkbox, Popover, PopoverTrigger, PopoverContent, openPrintWindow, printDocument, DashboardCanvas, ComingSoon, StatTiles, ListView, DateRangeControl, FilterPanel, FilterPanelField, SegmentedControl, RequiredFilter, FilterMenuRow, ChoiceList, ModalFlow, Switch, WizardSteps, KpiCard, ChartWidget, CardHeader, CardTitle, TableWidget, useDashboardNavigate, GoldCard } from '@fayz-ai/ui';
3
+ import { recordRailFields, RECORD_GROUP, activeFacet, createConnectionStore, connectionSettings, connectionStatus, settingsStatus, connectionRuns, registerTranslations, getSupabaseClientOptional, createSafeDataProvider, registerMessageDefaults, reportDataError, useTranslation, createPendingCommand, useUnitMode, useDataChanged, countByTenant, tl, resolveDataProvider, useActiveUnitId, getActiveTenantId, emitDataChanged, describeError, exportCSV } from '@fayz-ai/core';
4
+ import { INLINE_LINK_TONE, SearchSelect, ModalTask, toast, Button, useInModalTaskHost, useSaveBar, tourAnchor, DatePicker, SubpageHeader, defineKpiWidget, defineChartWidget, defineCustomWidget, defineTableWidget, Modal, ModalContent, ModalHeader, ModalTitle, ModalDescription, ModalBody, DataTable, Card, CardContent, Skeleton, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, MultiSelect, PageTransition, ModulePage, Badge, TooltipProvider, ConfirmDialog, CurrencyInput, Input, PageHeaderActions, ChoiceSelect, ModalFooter, Hint, PageTabs, Tooltip, TooltipTrigger, TooltipContent, Checkbox, Popover, PopoverTrigger, PopoverContent, openPrintWindow, printDocument, DashboardCanvas, ComingSoon, StatTiles, ListView, DateRangeControl, FilterPanel, FilterPanelField, SegmentedControl, RequiredFilter, FilterMenuRow, ChoiceList, ModalFlow, Switch, WizardSteps, KpiCard, ChartWidget, CardHeader, CardTitle, TableWidget, useDashboardNavigate, GoldCard } from '@fayz-ai/ui';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
  import { createPluginContext, fayzConnectorOAuth, formatCurrency, RightRailPage, createCrudPage, PluginSettingsPanel, dedup, useUnitFilter, useLimitGuard, usePermissionOptional, useLookupCreate, OrderFormSkeleton, WidgetSlot, OrderFormBlock, OrderFormView, OrderFormItemsCard, OrderFormItemRow, adminNavigateTo, OrderFormAddItemStep, useUnitStore, OrderDetailSkeleton, PageActions, OrderDetailBlock, OrderDetailView, PersonLink, useTenantPluginSettings, useModuleNavigation, usePluginOnboardingGate, useModuleNavAccess, PluginOnboardingGateSkeleton, ModuleActionBar, SettingsGroup, ToggleRow, createArchetypeLookup, invalidateLimit, useAgentSurface, parseViewId, EntitlementGate, UpgradePrompt, useChatStore, revealPage, useAuth, GetStarted, resolveEntityRoute, PermissionGate, createOneShotAsk, askAI, requestChatUpload, toInlineFile, shrinkForVision } from '@fayz-ai/admin';
7
7
  import { Landmark, CircleDollarSign, FileText, TriangleAlert, Loader2, Check, X, MoreVertical, Ban, CircleDashed, CircleAlert, CircleCheckBig, CircleEllipsis, Pencil, Receipt, Gift, Briefcase, Package, CalendarDays, ExternalLink, DollarSign, LayoutList, Layers, Paperclip, Ticket, FileCheck, ArrowRightLeft, CreditCard, QrCode, Banknote, Undo2, Wallet, Plus, AlertTriangle, Filter, TrendingUp, Copy, Trash2, Search, ChevronsUpDown, ChevronsDownUp, ChevronRight, Building2, Image, UploadCloud, Calendar, User, Unlink, ChevronDown, Eye, Inbox, Clock, ClipboardCheck, BookOpen, Info, FolderOpen, Folder, RotateCcw, Settings, ArrowLeft, ChevronLeft, Calculator, Square, Play, ChevronUp, Printer, CalendarClock, BadgeCheck, Target, ArrowRight, Users, RefreshCw, Download, Camera, Sparkles, Link2, FileSearch, CheckCheck, Pause, ShoppingCart, Car, Home, Utensils, Zap, Film, HeartPulse, Dumbbell, Music, ShoppingBag, FileDown, ArrowUpRight, ArrowDownRight, EyeOff } from 'lucide-react';
@@ -1477,7 +1477,7 @@ function CnabRemittanceModal({ invoices, bankAccounts, provider, onClose }) {
1477
1477
  const byContact = new Map(loaded.payees.map((payee) => [payee.contactId, payee]));
1478
1478
  setLines(invoices.map((invoice) => lineFromInvoice(invoice, byContact.get(invoice.contactId ?? ""))));
1479
1479
  } catch (cause) {
1480
- setError(cause instanceof Error ? cause.message : "N\xE3o foi poss\xEDvel carregar os favorecidos.");
1480
+ setError(describeError(cause, "N\xE3o foi poss\xEDvel carregar os favorecidos."));
1481
1481
  setLines(invoices.map((invoice) => lineFromInvoice(invoice, void 0)));
1482
1482
  } finally {
1483
1483
  setLoadingContext(false);
@@ -1531,7 +1531,7 @@ function CnabRemittanceModal({ invoices, bankAccounts, provider, onClose }) {
1531
1531
  await saveCompany();
1532
1532
  setStep(1);
1533
1533
  } catch (cause) {
1534
- setError(cause instanceof Error ? cause.message : "N\xE3o foi poss\xEDvel salvar os dados banc\xE1rios.");
1534
+ setError(describeError(cause, "N\xE3o foi poss\xEDvel salvar os dados banc\xE1rios."));
1535
1535
  } finally {
1536
1536
  setBusy(false);
1537
1537
  }
@@ -1608,7 +1608,7 @@ function CnabRemittanceModal({ invoices, bankAccounts, provider, onClose }) {
1608
1608
  URL.revokeObjectURL(url);
1609
1609
  onClose();
1610
1610
  } catch (cause) {
1611
- setError(cause instanceof Error ? cause.message : "N\xE3o foi poss\xEDvel gerar o arquivo.");
1611
+ setError(describeError(cause, "N\xE3o foi poss\xEDvel gerar o arquivo."));
1612
1612
  } finally {
1613
1613
  setBusy(false);
1614
1614
  }
@@ -1874,6 +1874,7 @@ function InvoiceAttachmentsModal({ invoiceId, onClose, onChanged }) {
1874
1874
  const [uploading, setUploading] = useState(0);
1875
1875
  const [over, setOver] = useState(false);
1876
1876
  const [preview, setPreview] = useState(null);
1877
+ const [added, setAdded] = useState(0);
1877
1878
  async function load() {
1878
1879
  try {
1879
1880
  setItems(await (provider.getInvoiceAttachments?.(invoiceId) ?? Promise.resolve([])));
@@ -1896,6 +1897,7 @@ function InvoiceAttachmentsModal({ invoiceId, onClose, onChanged }) {
1896
1897
  for (const file of ok) {
1897
1898
  try {
1898
1899
  await provider.addInvoiceAttachment(invoiceId, file);
1900
+ setAdded((n) => n + 1);
1899
1901
  } catch (e) {
1900
1902
  toast.error(`${file.name}: ${e?.message ?? String(e)}`);
1901
1903
  } finally {
@@ -1988,7 +1990,8 @@ function InvoiceAttachmentsModal({ invoiceId, onClose, onChanged }) {
1988
1990
  }
1989
1991
  }
1990
1992
  )
1991
- ] })
1993
+ ] }),
1994
+ /* @__PURE__ */ jsx(ModalFooter, { children: /* @__PURE__ */ jsx(Button, { onClick: onClose, disabled: uploading > 0, variant: added > 0 ? "default" : "outline", children: uploading > 0 ? "Enviando\u2026" : added > 0 ? "Concluir" : "Fechar" }) })
1992
1995
  ] }) }) });
1993
1996
  }
1994
1997
  function AttachmentPreview({ items, index, onIndex, onBack }) {
@@ -2409,7 +2412,7 @@ function InvoiceListView({ direction, onNew, onNewReceipt, onEdit }) {
2409
2412
  else void fetchInvoices(query);
2410
2413
  }).catch((err) => {
2411
2414
  toast.error(t2("financial.invoice.consolidateFailed"), {
2412
- description: err instanceof Error ? err.message : String(err)
2415
+ description: describeError(err)
2413
2416
  });
2414
2417
  }).finally(() => setConsolidating(null));
2415
2418
  }, [provider, t2, fetchInvoices, query, onEdit]);
@@ -4061,7 +4064,7 @@ function createFinancialAgentMount(deps) {
4061
4064
  FinancialAgentMount.displayName = "FinancialAgentMount";
4062
4065
  return FinancialAgentMount;
4063
4066
  }
4064
- function useReceiptPicker(onPick) {
4067
+ function useReceiptPicker(onPick, onPickDocument) {
4065
4068
  const t2 = useTranslation();
4066
4069
  const ref = useRef(null);
4067
4070
  const input = /* @__PURE__ */ jsx(
@@ -4069,13 +4072,17 @@ function useReceiptPicker(onPick) {
4069
4072
  {
4070
4073
  ref,
4071
4074
  type: "file",
4072
- accept: "image/*",
4073
- capture: "environment",
4075
+ accept: onPickDocument ? "image/*,application/pdf" : "image/*",
4076
+ capture: onPickDocument ? void 0 : "environment",
4074
4077
  className: "hidden",
4075
4078
  onChange: (e) => {
4076
4079
  const file = e.target.files?.[0];
4077
4080
  e.target.value = "";
4078
4081
  if (!file) return;
4082
+ if (onPickDocument && file.type === "application/pdf") {
4083
+ onPickDocument(file);
4084
+ return;
4085
+ }
4079
4086
  if (!file.type.startsWith("image/")) {
4080
4087
  toast.error(t2("financial.quickTx.receiptInvalid"));
4081
4088
  return;
@@ -4945,10 +4952,10 @@ function InstallmentReceiptButton({ onClick, title, attached, pending: pending2,
4945
4952
  onClick,
4946
4953
  title,
4947
4954
  "aria-label": title,
4948
- className: `inline-flex shrink-0 items-center gap-1 rounded-lg border bg-card px-2.5 py-1.5 text-xs font-medium shadow-button transition-colors hover:bg-muted active:shadow-button-inset ${attached ? "text-success" : pending2 ? "text-primary" : ""}`,
4955
+ className: `relative inline-flex shrink-0 items-center gap-1 rounded-lg border bg-card px-2.5 py-1.5 text-xs font-medium shadow-button transition-colors hover:bg-muted active:shadow-button-inset ${attached ? "text-success" : pending2 ? "text-primary" : ""}`,
4949
4956
  children: [
4950
4957
  /* @__PURE__ */ jsx(Paperclip, { className: "h-3 w-3" }),
4951
- !!count && /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: count })
4958
+ !!count && /* @__PURE__ */ jsx("span", { className: "absolute -right-1.5 -top-1.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-primary px-1 text-[10px] font-semibold leading-none text-primary-foreground tabular-nums", children: count })
4952
4959
  ]
4953
4960
  }
4954
4961
  );
@@ -5200,6 +5207,15 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
5200
5207
  const canManageFinancial = can("financial", "manage");
5201
5208
  const isEdit = !!editId;
5202
5209
  const [attachmentsOpen, setAttachmentsOpen] = useState(false);
5210
+ const [attachmentCount, setAttachmentCount] = useState(0);
5211
+ const loadAttachmentCount = React25__default.useCallback(() => {
5212
+ if (!editId || !provider.getInvoiceAttachments) return;
5213
+ provider.getInvoiceAttachments(editId).then((list) => setAttachmentCount(list.length)).catch(() => {
5214
+ });
5215
+ }, [editId, provider]);
5216
+ useEffect(() => {
5217
+ loadAttachmentCount();
5218
+ }, [loadAttachmentCount]);
5203
5219
  useEffect(() => {
5204
5220
  void fetchBankAccounts();
5205
5221
  void fetchPaymentMethods();
@@ -5271,6 +5287,7 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
5271
5287
  });
5272
5288
  const [pendingContact, setPendingContact] = useState(null);
5273
5289
  const [receiptTarget, setReceiptTarget] = useState(null);
5290
+ const [pendingDocs, setPendingDocs] = useState([]);
5274
5291
  const receiptPicker = useReceiptPicker((dataUrl) => {
5275
5292
  const i = receiptTarget;
5276
5293
  setReceiptTarget(null);
@@ -5283,7 +5300,10 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
5283
5300
  return;
5284
5301
  }
5285
5302
  setInstallments((prev) => prev.map((inst, idx) => idx === i ? { ...inst, receiptUrl: dataUrl } : inst));
5286
- });
5303
+ }, provider.addInvoiceAttachment ? (file) => {
5304
+ setReceiptTarget(null);
5305
+ setPendingDocs((prev) => [...prev, file]);
5306
+ } : void 0);
5287
5307
  const [saving, setSaving] = useState(false);
5288
5308
  const [menuOpen, setMenuOpen] = useState(false);
5289
5309
  const [confirmCancel, setConfirmCancel] = useState(false);
@@ -5687,6 +5707,16 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
5687
5707
  });
5688
5708
  }
5689
5709
  }
5710
+ if (pendingDocs.length > 0 && provider.addInvoiceAttachment) {
5711
+ const failed = [];
5712
+ for (const file of pendingDocs) {
5713
+ await provider.addInvoiceAttachment(invoice.id, file).catch(() => {
5714
+ failed.push(file.name);
5715
+ });
5716
+ }
5717
+ setPendingDocs([]);
5718
+ if (failed.length) toast.error(t2("financial.invoiceForm.attachFailed"), { description: failed.join(", ") });
5719
+ }
5690
5720
  createdId.current = invoice.id;
5691
5721
  if (!opts?.stay) onSaved?.(invoice.id);
5692
5722
  savedId = invoice.id;
@@ -5844,7 +5874,8 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
5844
5874
  (canAttach || isEdit) && /* @__PURE__ */ jsx(
5845
5875
  InstallmentReceiptButton,
5846
5876
  {
5847
- attached: !!inst.receiptUrl,
5877
+ attached: !!inst.receiptUrl || isEdit && attachmentCount > 0,
5878
+ count: isEdit ? attachmentCount : void 0,
5848
5879
  pending: !inst.receiptUrl && !!pendingReceipt,
5849
5880
  title: !inst.receiptUrl && pendingReceipt ? t2("financial.receipt.attachRead") : t2("financial.quickTx.receiptCapture"),
5850
5881
  onClick: () => {
@@ -5898,7 +5929,25 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
5898
5929
  )
5899
5930
  ] })
5900
5931
  ] }, inst._id);
5901
- }) })
5932
+ }) }),
5933
+ pendingDocs.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: pendingDocs.map((file, idx) => /* @__PURE__ */ jsxs("span", { className: "inline-flex max-w-full items-center gap-1.5 rounded-md border bg-muted/30 px-2 py-1 text-xs", children: [
5934
+ /* @__PURE__ */ jsx(FileText, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
5935
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: file.name }),
5936
+ /* @__PURE__ */ jsxs("span", { className: "shrink-0 text-muted-foreground", children: [
5937
+ "\xB7 ",
5938
+ t2("financial.invoiceForm.attachOnSave")
5939
+ ] }),
5940
+ /* @__PURE__ */ jsx(
5941
+ "button",
5942
+ {
5943
+ type: "button",
5944
+ onClick: () => setPendingDocs((prev) => prev.filter((_, j) => j !== idx)),
5945
+ "aria-label": t2("financial.quickTx.receiptRemove"),
5946
+ className: "flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-muted hover:text-foreground",
5947
+ children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
5948
+ }
5949
+ )
5950
+ ] }, `${file.name}-${idx}`)) })
5902
5951
  ] }) }) })
5903
5952
  );
5904
5953
  const contactSection = /* @__PURE__ */ jsx("div", { ...tourAnchor("financial.contact"), children: /* @__PURE__ */ jsxs(OrderFormBlock, { title: direction === "debit" ? t2("financial.invoiceForm.payTo") : t2("financial.invoiceForm.receiveFrom"), children: [
@@ -6193,7 +6242,7 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
6193
6242
  }
6194
6243
  ),
6195
6244
  receiptPicker.input,
6196
- attachmentsOpen && editId && /* @__PURE__ */ jsx(InvoiceAttachmentsModal, { invoiceId: editId, onClose: () => setAttachmentsOpen(false) }),
6245
+ attachmentsOpen && editId && /* @__PURE__ */ jsx(InvoiceAttachmentsModal, { invoiceId: editId, onClose: () => setAttachmentsOpen(false), onChanged: loadAttachmentCount }),
6197
6246
  payingMovement && /* @__PURE__ */ jsx(
6198
6247
  PaymentModal,
6199
6248
  {
@@ -18486,6 +18535,8 @@ var en = {
18486
18535
  "financial.invoiceForm.scheduleSourceHint": "Method and account are set on each due date.",
18487
18536
  "financial.invoiceForm.paidNeedsMethod": "Tell us the payment method and the account",
18488
18537
  "financial.invoiceForm.willBePaid": "This installment will be settled",
18538
+ "financial.invoiceForm.attachFailed": "The bill was saved, but an attachment did not upload",
18539
+ "financial.invoiceForm.attachOnSave": "attached on save",
18489
18540
  "financial.invoiceForm.clear": "Clear",
18490
18541
  "financial.invoiceForm.manageAccounts": "Manage accounts",
18491
18542
  "financial.invoiceForm.manageChart": "Manage chart of accounts",
@@ -19254,11 +19305,11 @@ var en = {
19254
19305
  "financial.quickTx.attachment": "Attachment",
19255
19306
  "financial.quickTx.attachmentSoon": "Attachments coming soon",
19256
19307
  "financial.quickTx.receipt": "Receipt",
19257
- "financial.quickTx.receiptCapture": "Snap or attach a receipt",
19308
+ "financial.quickTx.receiptCapture": "Attach a receipt or bill (photo or PDF)",
19258
19309
  "financial.quickTx.receiptAttached": "Receipt attached",
19259
19310
  "financial.quickTx.receiptReplace": "Replace",
19260
19311
  "financial.quickTx.receiptRemove": "Remove receipt",
19261
- "financial.quickTx.receiptInvalid": "Please choose an image file",
19312
+ "financial.quickTx.receiptInvalid": "Please choose an image or PDF",
19262
19313
  "financial.quickTx.sendReceipt": "Send receipt",
19263
19314
  "financial.quickTx.digitizeExpense": "Digitize expense",
19264
19315
  "financial.quickTx.digitizeReceipt": "Digitize receipt",
@@ -19426,6 +19477,8 @@ var ptBR = {
19426
19477
  "financial.invoiceForm.scheduleSourceHint": "Forma e conta ficam configur\xE1veis em cada vencimento.",
19427
19478
  "financial.invoiceForm.paidNeedsMethod": "Diga a forma de pagamento e a conta",
19428
19479
  "financial.invoiceForm.willBePaid": "Esta parcela entra como paga",
19480
+ "financial.invoiceForm.attachFailed": "A conta foi salva, mas um anexo n\xE3o subiu",
19481
+ "financial.invoiceForm.attachOnSave": "anexa ao salvar",
19429
19482
  "financial.invoiceForm.clear": "Limpar",
19430
19483
  "financial.invoiceForm.manageAccounts": "Gerenciar contas",
19431
19484
  "financial.invoiceForm.manageChart": "Gerenciar plano de contas",
@@ -20197,11 +20250,11 @@ var ptBR = {
20197
20250
  "financial.quickTx.attachment": "Anexo",
20198
20251
  "financial.quickTx.attachmentSoon": "Anexos em breve",
20199
20252
  "financial.quickTx.receipt": "Recibo",
20200
- "financial.quickTx.receiptCapture": "Fotografar ou anexar recibo",
20253
+ "financial.quickTx.receiptCapture": "Anexar comprovante ou boleto (foto ou PDF)",
20201
20254
  "financial.quickTx.receiptAttached": "Recibo anexado",
20202
20255
  "financial.quickTx.receiptReplace": "Substituir",
20203
20256
  "financial.quickTx.receiptRemove": "Remover recibo",
20204
- "financial.quickTx.receiptInvalid": "Escolha um arquivo de imagem",
20257
+ "financial.quickTx.receiptInvalid": "Escolha uma imagem ou PDF",
20205
20258
  "financial.quickTx.sendReceipt": "Enviar recibo",
20206
20259
  "financial.quickTx.digitizeExpense": "Digitalizar despesa",
20207
20260
  "financial.quickTx.digitizeReceipt": "Digitalizar comprovante",