@fayz-ai/plugin-financial 0.9.0 → 0.9.1

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.
Files changed (91) hide show
  1. package/README.md +3 -3
  2. package/dist/components/PersonStatementWidget.d.ts +1 -1
  3. package/dist/components/PersonStatementWidget.d.ts.map +1 -1
  4. package/dist/{FinancialContext.d.ts → context.d.ts} +4 -2
  5. package/dist/context.d.ts.map +1 -0
  6. package/dist/data/registries.d.ts.map +1 -0
  7. package/dist/index.d.ts +10 -4
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +1208 -1368
  10. package/dist/index.js.map +1 -1
  11. package/dist/lib/message-events.d.ts +12 -0
  12. package/dist/lib/message-events.d.ts.map +1 -0
  13. package/dist/{quick-add.d.ts → lib/quick-add.d.ts} +1 -1
  14. package/dist/lib/quick-add.d.ts.map +1 -0
  15. package/dist/locales/en.d.ts.map +1 -1
  16. package/dist/locales/pt-BR.d.ts.map +1 -1
  17. package/dist/{FinancialPage.d.ts → views/FinancialPage.d.ts} +3 -3
  18. package/dist/views/FinancialPage.d.ts.map +1 -0
  19. package/dist/views/InvoiceDetailView.d.ts.map +1 -1
  20. package/dist/views/InvoiceFormView.d.ts.map +1 -1
  21. package/dist/views/InvoiceListView.d.ts.map +1 -1
  22. package/dist/views/PayablesView.d.ts +1 -1
  23. package/dist/views/PayablesView.d.ts.map +1 -1
  24. package/dist/views/ReceivablesView.d.ts +1 -1
  25. package/dist/views/ReceivablesView.d.ts.map +1 -1
  26. package/dist/views/StatementsView.d.ts.map +1 -1
  27. package/dist/views/dashboardWidgets.d.ts +1 -1
  28. package/dist/views/dashboardWidgets.d.ts.map +1 -1
  29. package/package.json +12 -14
  30. package/dist/FinancialContext.d.ts.map +0 -1
  31. package/dist/FinancialPage.d.ts.map +0 -1
  32. package/dist/contract.test.d.ts +0 -2
  33. package/dist/contract.test.d.ts.map +0 -1
  34. package/dist/quick-add.d.ts.map +0 -1
  35. package/dist/registries.d.ts.map +0 -1
  36. package/src/FinancialContext.tsx +0 -59
  37. package/src/FinancialPage.tsx +0 -413
  38. package/src/README.md +0 -155
  39. package/src/components/FinancialGeneralSettings.tsx +0 -39
  40. package/src/components/FinancialOnboarding.tsx +0 -87
  41. package/src/components/FinancialSettings.tsx +0 -31
  42. package/src/components/PaymentModal.tsx +0 -369
  43. package/src/components/PersonStatementWidget.tsx +0 -133
  44. package/src/components/TransferModal.tsx +0 -150
  45. package/src/contract.test.ts +0 -58
  46. package/src/data/capability.test.ts +0 -135
  47. package/src/data/index.ts +0 -3
  48. package/src/data/mock.ts +0 -842
  49. package/src/data/supabase.ts +0 -968
  50. package/src/data/tables.ts +0 -13
  51. package/src/data/types.ts +0 -86
  52. package/src/index.ts +0 -487
  53. package/src/lib/tenant.ts +0 -3
  54. package/src/locales/en.ts +0 -493
  55. package/src/locales/index.ts +0 -7
  56. package/src/locales/pt-BR.ts +0 -493
  57. package/src/migrations/000_plg_rename.sql +0 -30
  58. package/src/migrations/001_financial_base.sql +0 -109
  59. package/src/migrations/002_chart_of_accounts.sql +0 -28
  60. package/src/migrations/003_card_brands.sql +0 -12
  61. package/src/migrations/004_order_to_cash.sql +0 -178
  62. package/src/migrations/005_seed_defaults.sql +0 -38
  63. package/src/migrations/006_rls_policies.sql +0 -37
  64. package/src/migrations/006b_extract_fee_amount.sql +0 -20
  65. package/src/migrations/007_reconciliation.sql +0 -32
  66. package/src/migrations/007b_movement_payment_method_type.sql +0 -6
  67. package/src/migrations/008_split_payment_movements.sql +0 -29
  68. package/src/migrations/009_agent_rpcs.sql +0 -165
  69. package/src/migrations/010_invoice_internal.sql +0 -133
  70. package/src/migrations/011_nfe.sql +0 -58
  71. package/src/migrations/index.ts +0 -923
  72. package/src/quick-add.ts +0 -58
  73. package/src/registries.ts +0 -308
  74. package/src/store.ts +0 -329
  75. package/src/types.ts +0 -592
  76. package/src/views/CardsView.tsx +0 -213
  77. package/src/views/CashRegistersView.tsx +0 -597
  78. package/src/views/CommissionsView.tsx +0 -18
  79. package/src/views/InvoiceDetailView.tsx +0 -616
  80. package/src/views/InvoiceFormView.tsx +0 -945
  81. package/src/views/InvoiceListView.tsx +0 -323
  82. package/src/views/NotasFiscaisView.tsx +0 -209
  83. package/src/views/PayablesView.tsx +0 -48
  84. package/src/views/QuickTransactionForm.tsx +0 -548
  85. package/src/views/ReceivablesView.tsx +0 -48
  86. package/src/views/ReconciliationView.tsx +0 -211
  87. package/src/views/StatementsView.tsx +0 -335
  88. package/src/views/SummaryView.tsx +0 -203
  89. package/src/views/dashboardWidgets.tsx +0 -437
  90. package/src/views/navReferrer.ts +0 -24
  91. /package/dist/{registries.d.ts → data/registries.d.ts} +0 -0
@@ -1,213 +0,0 @@
1
- import React, { useEffect, useMemo, useState } from 'react'
2
- import { CreditCard, Plus, CalendarClock } from 'lucide-react'
3
- import { useFinancialConfig, useFinancialStore, formatCurrency } from '../FinancialContext'
4
- import { SubpageHeader } from '@fayz-ai/ui'
5
- import { PermissionGate } from '@fayz-ai/saas'
6
- import { useTranslation } from '@fayz-ai/core'
7
- import type { BankAccount } from '../types'
8
- import { QuickTransactionForm } from './QuickTransactionForm'
9
-
10
- // ---------------------------------------------------------------------------
11
- // Per-card money math. Credit-card balances are stored as debt (negative), so
12
- // the current bill (fatura) is the magnitude owed; the available limit is what
13
- // remains of the credit line.
14
- // ---------------------------------------------------------------------------
15
-
16
- function cardMath(acc: BankAccount) {
17
- const limit = acc.creditLimit ?? 0
18
- const used = Math.max(0, -acc.currentBalance)
19
- const available = Math.max(0, limit - used)
20
- const pct = limit > 0 ? Math.min(100, (used / limit) * 100) : 0
21
- return { limit, used, available, pct }
22
- }
23
-
24
- export function CardsView() {
25
- const t = useTranslation()
26
- const { currency } = useFinancialConfig()
27
- const bankAccounts = useFinancialStore((s) => s.bankAccounts)
28
- const bankAccountsLoading = useFinancialStore((s) => s.bankAccountsLoading)
29
- const fetchBankAccounts = useFinancialStore((s) => s.fetchBankAccounts)
30
-
31
- const [tab, setTab] = useState<'open' | 'closed'>('open')
32
- const [addOpen, setAddOpen] = useState(false)
33
- const [addCardId, setAddCardId] = useState<string | undefined>()
34
-
35
- useEffect(() => { fetchBankAccounts() }, [])
36
-
37
- const cards = useMemo(
38
- () => bankAccounts.filter((a) => a.accountType === 'credit_card'),
39
- [bankAccounts],
40
- )
41
- const openCards = useMemo(() => cards.filter((c) => c.isActive), [cards])
42
- const closedCards = useMemo(() => cards.filter((c) => !c.isActive), [cards])
43
- const visibleCards = tab === 'open' ? openCards : closedCards
44
-
45
- // Summary strip is computed over the active (open) cards — the money that is
46
- // actually in play this cycle.
47
- const summary = useMemo(() => {
48
- let totalAvailable = 0
49
- let totalBills = 0
50
- for (const c of openCards) {
51
- const { available, used } = cardMath(c)
52
- totalAvailable += available
53
- totalBills += used
54
- }
55
- return { totalAvailable, totalBills }
56
- }, [openCards])
57
-
58
- function openAddExpense(cardId: string) {
59
- setAddCardId(cardId)
60
- setAddOpen(true)
61
- }
62
-
63
- return (
64
- <div className="space-y-4">
65
- <SubpageHeader title={t('financial.cards.title')} subtitle={t('financial.cards.subtitle')} />
66
-
67
- {bankAccountsLoading && cards.length === 0 ? (
68
- <div className="text-center py-12 text-sm text-muted-foreground">Loading...</div>
69
- ) : cards.length === 0 ? (
70
- <div className="flex flex-col items-center justify-center py-12 text-center rounded-2xl border-2 border-dashed border-muted">
71
- <div className="flex h-12 w-12 items-center justify-center rounded-xl bg-gradient-to-br from-amber-300 to-yellow-600 mb-3 text-white shadow-sm">
72
- <CreditCard className="h-6 w-6" />
73
- </div>
74
- <p className="text-sm font-medium">{t('financial.cards.noCards')}</p>
75
- <p className="text-xs text-muted-foreground mt-0.5 max-w-xs">{t('financial.cards.noCardsHint')}</p>
76
- </div>
77
- ) : (
78
- <>
79
- {/* Summary strip — available limit + total bills across open cards */}
80
- <div className="grid grid-cols-2 gap-px overflow-hidden rounded-2xl border bg-border shadow-sm">
81
- <div className="bg-card px-4 py-3">
82
- <p className="text-xs text-muted-foreground">{t('financial.cards.availableLimit')}</p>
83
- <p className="mt-0.5 text-lg font-bold tabular-nums text-success">
84
- {formatCurrency(summary.totalAvailable, currency)}
85
- </p>
86
- </div>
87
- <div className="bg-card px-4 py-3">
88
- <p className="text-xs text-muted-foreground">{t('financial.cards.allBillsValue')}</p>
89
- <p className="mt-0.5 text-lg font-bold tabular-nums">
90
- {formatCurrency(summary.totalBills, currency)}
91
- </p>
92
- </div>
93
- </div>
94
-
95
- {/* Open / Closed tabs (only when there are closed cards to switch to) */}
96
- {closedCards.length > 0 && (
97
- <div className="flex gap-1 rounded-full bg-muted p-1 w-full max-w-xs">
98
- {(['open', 'closed'] as const).map((k) => (
99
- <button
100
- key={k}
101
- onClick={() => setTab(k)}
102
- className={`flex-1 rounded-full px-3 py-1.5 text-xs font-medium transition-colors ${
103
- tab === k ? 'bg-card text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'
104
- }`}
105
- >
106
- {k === 'open' ? t('financial.cards.tabOpen') : t('financial.cards.tabClosed')}
107
- </button>
108
- ))}
109
- </div>
110
- )}
111
-
112
- {/* Card tiles — stacked on mobile, grid on desktop */}
113
- <div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
114
- {visibleCards.map((card) => {
115
- const { limit, used, available, pct } = cardMath(card)
116
- const over = pct >= 90
117
- // Per-brand color so cards match the bank (and the Home card), not a uniform gold.
118
- const brand = `${card.bankName ?? ''} ${card.name ?? ''}`.toLowerCase()
119
- const headerGrad =
120
- brand.includes('nubank') || brand.includes('nu ') ? 'from-purple-500 via-purple-600 to-indigo-700'
121
- : brand.includes('ita') ? 'from-orange-400 via-orange-500 to-amber-600'
122
- : brand.includes('inter') ? 'from-orange-500 via-orange-600 to-orange-700'
123
- : 'from-indigo-500 via-indigo-600 to-violet-700'
124
- const barGrad =
125
- brand.includes('nubank') || brand.includes('nu ') ? 'from-purple-500 to-indigo-600'
126
- : brand.includes('ita') ? 'from-orange-400 to-amber-500'
127
- : brand.includes('inter') ? 'from-orange-500 to-orange-600'
128
- : 'from-indigo-500 to-violet-600'
129
- return (
130
- <div key={card.id} className="overflow-hidden rounded-2xl border bg-card shadow-sm">
131
- {/* Per-brand header */}
132
- <div className={`bg-gradient-to-br ${headerGrad} px-4 py-4 text-white`}>
133
- <div className="flex items-start justify-between">
134
- <div className="flex items-center gap-2">
135
- <CreditCard className="h-5 w-5" />
136
- <span className="text-sm font-semibold">{card.name}</span>
137
- </div>
138
- {card.bankName && (
139
- <span className="text-[11px] font-medium uppercase tracking-wide opacity-80">
140
- {card.bankName}
141
- </span>
142
- )}
143
- </div>
144
- <div className="mt-4">
145
- <p className="text-[11px] uppercase tracking-wide opacity-80">
146
- {t('financial.cards.currentBill')}
147
- </p>
148
- <p className="text-2xl font-bold tabular-nums leading-tight">
149
- {formatCurrency(used, currency)}
150
- </p>
151
- </div>
152
- </div>
153
-
154
- {/* Body */}
155
- <div className="space-y-3 px-4 py-3">
156
- {/* Usage progress bar */}
157
- <div>
158
- <div className="flex items-center justify-between text-[11px] text-muted-foreground">
159
- <span>{t('financial.cards.usedOfLimit', { percent: String(Math.round(pct)) })}</span>
160
- <span className="tabular-nums">{formatCurrency(limit, currency)}</span>
161
- </div>
162
- <div className="mt-1 h-2 overflow-hidden rounded-full bg-muted">
163
- <div
164
- className={`h-full rounded-full ${
165
- over ? 'bg-destructive' : `bg-gradient-to-r ${barGrad}`
166
- }`}
167
- style={{ width: `${pct}%` }}
168
- />
169
- </div>
170
- </div>
171
-
172
- {/* Available limit + due date */}
173
- <div className="flex items-center justify-between">
174
- <div>
175
- <p className="text-[11px] text-muted-foreground">{t('financial.cards.availableLimit')}</p>
176
- <p className="text-sm font-semibold tabular-nums">{formatCurrency(available, currency)}</p>
177
- </div>
178
- {card.dueDay != null && (
179
- <div className="flex items-center gap-1.5 text-right text-xs text-muted-foreground">
180
- <CalendarClock className="h-3.5 w-3.5" />
181
- <span>{t('financial.cards.dueOn', { day: String(card.dueDay) })}</span>
182
- </div>
183
- )}
184
- </div>
185
-
186
- {/* Add expense against this card — gated on the role's create action */}
187
- <PermissionGate feature="financial" action="create">
188
- <button
189
- type="button"
190
- onClick={() => openAddExpense(card.id)}
191
- className="flex w-full items-center justify-center gap-1.5 rounded-input border border-input bg-card px-3 py-2 text-xs font-medium text-foreground transition-colors hover:bg-muted/40"
192
- >
193
- <Plus className="h-3.5 w-3.5" />
194
- {t('financial.cards.addExpense')}
195
- </button>
196
- </PermissionGate>
197
- </div>
198
- </div>
199
- )
200
- })}
201
- </div>
202
- </>
203
- )}
204
-
205
- <QuickTransactionForm
206
- open={addOpen}
207
- onOpenChange={setAddOpen}
208
- defaultType="expense"
209
- defaultAccountId={addCardId}
210
- />
211
- </div>
212
- )
213
- }