@fayz-ai/plugin-reports 0.9.0 → 0.10.0

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 (79) hide show
  1. package/README.md +4 -4
  2. package/dist/{chunk-LODXZ2SC.js → chunk-2ZFN6ECM.js} +3 -3
  3. package/dist/chunk-2ZFN6ECM.js.map +1 -0
  4. package/dist/data/aggregate.d.ts +14 -0
  5. package/dist/data/aggregate.d.ts.map +1 -0
  6. package/dist/data/analytics-mock.d.ts +3 -0
  7. package/dist/data/analytics-mock.d.ts.map +1 -0
  8. package/dist/data/analytics-supabase.d.ts +7 -0
  9. package/dist/data/analytics-supabase.d.ts.map +1 -0
  10. package/dist/{excel-QHUSM6IH.js → excel-WE73YE2V.js} +3 -3
  11. package/dist/{excel-QHUSM6IH.js.map → excel-WE73YE2V.js.map} +1 -1
  12. package/dist/index.d.ts +73 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1207 -654
  15. package/dist/index.js.map +1 -1
  16. package/dist/lib/lastViewed.d.ts +5 -0
  17. package/dist/lib/lastViewed.d.ts.map +1 -0
  18. package/dist/lib/legacy.d.ts +5 -0
  19. package/dist/lib/legacy.d.ts.map +1 -0
  20. package/dist/lib/tenant.d.ts +1 -0
  21. package/dist/lib/tenant.d.ts.map +1 -1
  22. package/dist/locales/en.d.ts.map +1 -1
  23. package/dist/locales/pt-BR.d.ts.map +1 -1
  24. package/dist/{pdf-HETKN26Y.js → pdf-E6DXHFXU.js} +3 -3
  25. package/dist/{pdf-HETKN26Y.js.map → pdf-E6DXHFXU.js.map} +1 -1
  26. package/dist/views/AnalyticsModule.d.ts +10 -0
  27. package/dist/views/AnalyticsModule.d.ts.map +1 -0
  28. package/dist/views/AnalyticsOverview.d.ts +3 -0
  29. package/dist/views/AnalyticsOverview.d.ts.map +1 -0
  30. package/dist/views/AnalyticsReportViewer.d.ts +5 -0
  31. package/dist/views/AnalyticsReportViewer.d.ts.map +1 -0
  32. package/dist/views/AnalyticsSurface.d.ts +97 -0
  33. package/dist/views/AnalyticsSurface.d.ts.map +1 -0
  34. package/dist/views/LiveViewPage.d.ts +3 -0
  35. package/dist/views/LiveViewPage.d.ts.map +1 -0
  36. package/dist/views/ReportsListPage.d.ts +3 -0
  37. package/dist/views/ReportsListPage.d.ts.map +1 -0
  38. package/package.json +5 -7
  39. package/dist/ReportsContext.d.ts +0 -16
  40. package/dist/ReportsContext.d.ts.map +0 -1
  41. package/dist/ReportsPage.d.ts +0 -8
  42. package/dist/ReportsPage.d.ts.map +0 -1
  43. package/dist/chunk-LODXZ2SC.js.map +0 -1
  44. package/dist/components/ReportCard.d.ts +0 -9
  45. package/dist/components/ReportCard.d.ts.map +0 -1
  46. package/dist/components/ReportFilterBar.d.ts +0 -12
  47. package/dist/components/ReportFilterBar.d.ts.map +0 -1
  48. package/dist/components/ReportSummaryRow.d.ts +0 -10
  49. package/dist/components/ReportSummaryRow.d.ts.map +0 -1
  50. package/dist/hooks/useReportData.d.ts +0 -19
  51. package/dist/hooks/useReportData.d.ts.map +0 -1
  52. package/dist/views/ReportHub.d.ts +0 -8
  53. package/dist/views/ReportHub.d.ts.map +0 -1
  54. package/dist/views/ReportViewer.d.ts +0 -9
  55. package/dist/views/ReportViewer.d.ts.map +0 -1
  56. package/src/ReportsContext.tsx +0 -33
  57. package/src/ReportsPage.tsx +0 -62
  58. package/src/components/ExportDropdown.tsx +0 -63
  59. package/src/components/ReportCard.tsx +0 -38
  60. package/src/components/ReportFilterBar.tsx +0 -132
  61. package/src/components/ReportPagination.tsx +0 -59
  62. package/src/components/ReportSummaryRow.tsx +0 -68
  63. package/src/data/index.ts +0 -4
  64. package/src/data/mock.ts +0 -9
  65. package/src/data/supabase.ts +0 -200
  66. package/src/data/types.ts +0 -10
  67. package/src/export/csv.ts +0 -21
  68. package/src/export/excel.ts +0 -42
  69. package/src/export/pdf.ts +0 -47
  70. package/src/hooks/useReportData.ts +0 -123
  71. package/src/index.ts +0 -142
  72. package/src/lib/columns.ts +0 -130
  73. package/src/lib/tenant.ts +0 -3
  74. package/src/locales/en.ts +0 -28
  75. package/src/locales/index.ts +0 -7
  76. package/src/locales/pt-BR.ts +0 -28
  77. package/src/types.ts +0 -171
  78. package/src/views/ReportHub.tsx +0 -97
  79. package/src/views/ReportViewer.tsx +0 -182
@@ -1,97 +0,0 @@
1
- import React, { useMemo, useState } from 'react'
2
- import { Search } from 'lucide-react'
3
- import { Input } from '@fayz-ai/ui'
4
- import { useTranslation } from '@fayz-ai/core'
5
- import { ReportCard } from '../components/ReportCard'
6
- import { useReportsContext } from '../ReportsContext'
7
- import type { ReportDef } from '../types'
8
-
9
- interface ReportHubProps {
10
- onSelect: (report: ReportDef) => void
11
- }
12
-
13
- interface CategoryGroup {
14
- name: string
15
- reports: ReportDef[]
16
- }
17
-
18
- export function ReportHub({ onSelect }: ReportHubProps) {
19
- const t = useTranslation()
20
- const { config } = useReportsContext()
21
- const [search, setSearch] = useState('')
22
-
23
- const categories = useMemo(() => {
24
- const filtered = search
25
- ? config.reports.filter(
26
- (r) =>
27
- r.name.toLowerCase().includes(search.toLowerCase()) ||
28
- r.description?.toLowerCase().includes(search.toLowerCase()),
29
- )
30
- : config.reports
31
-
32
- const map = new Map<string, ReportDef[]>()
33
- for (const report of filtered) {
34
- const list = map.get(report.category) ?? []
35
- list.push(report)
36
- map.set(report.category, list)
37
- }
38
-
39
- const groups: CategoryGroup[] = []
40
- for (const [name, reports] of map) {
41
- groups.push({ name, reports })
42
- }
43
- return groups
44
- }, [config.reports, search])
45
-
46
- const totalReports = config.reports.length
47
-
48
- return (
49
- <div className="space-y-6">
50
- {/* Header (omitted when the app shell owns the page title) */}
51
- {config.showHeader && (
52
- <div>
53
- <h1 className="text-2xl font-bold">{t('reports.pageTitle')}</h1>
54
- <p className="text-muted-foreground mt-1">{t('reports.pageSubtitle')}</p>
55
- </div>
56
- )}
57
-
58
- {/* Search */}
59
- {totalReports > 6 && (
60
- <div className="relative max-w-md">
61
- <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
62
- <Input
63
- value={search}
64
- onChange={(e) => setSearch(e.target.value)}
65
- placeholder={t('reports.search')}
66
- className="pl-9"
67
- />
68
- </div>
69
- )}
70
-
71
- {/* Categories */}
72
- <div className="space-y-8">
73
- {categories.map((category) => (
74
- <div key={category.name} className="rounded-xl border bg-card shadow-sm p-5">
75
- <div className="flex items-center justify-between mb-4">
76
- <h2 className="font-semibold">{category.name}</h2>
77
- <span className="text-sm text-muted-foreground">
78
- {category.reports.length} {t('reports.reports')}
79
- </span>
80
- </div>
81
- <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
82
- {category.reports.map((report) => (
83
- <ReportCard key={report.id} report={report} onClick={onSelect} />
84
- ))}
85
- </div>
86
- </div>
87
- ))}
88
- </div>
89
-
90
- {categories.length === 0 && search && (
91
- <div className="text-center py-12 text-muted-foreground">
92
- {t('reports.noResults')}
93
- </div>
94
- )}
95
- </div>
96
- )
97
- }
@@ -1,182 +0,0 @@
1
- import React, { useMemo } from 'react'
2
- import { ArrowLeft, Play, SlidersHorizontal, Construction, Loader2, Printer } from 'lucide-react'
3
- import { Button } from '@fayz-ai/ui'
4
- import { DataTable } from '@fayz-ai/ui'
5
- import { useTranslation } from '@fayz-ai/core'
6
- import { useReportsContext } from '../ReportsContext'
7
- import { useReportData } from '../hooks/useReportData'
8
- import { reportColumnsToTanstack } from '../lib/columns'
9
- import { ReportFilterBar } from '../components/ReportFilterBar'
10
- import { ReportPagination } from '../components/ReportPagination'
11
- import { ReportSummaryRow } from '../components/ReportSummaryRow'
12
- import { ExportDropdown } from '../components/ExportDropdown'
13
- import type { ReportDef } from '../types'
14
-
15
- interface ReportViewerProps {
16
- report: ReportDef
17
- onBack: () => void
18
- }
19
-
20
- export function ReportViewer({ report, onBack }: ReportViewerProps) {
21
- const t = useTranslation()
22
- const { config, provider } = useReportsContext()
23
- const {
24
- data,
25
- total,
26
- loading,
27
- generated,
28
- error,
29
- query,
30
- generate,
31
- setDateRange,
32
- setFilter,
33
- setPage,
34
- setPageSize,
35
- } = useReportData(report, provider, config.defaultPageSize)
36
-
37
- const isAvailable = report.available !== false
38
- const tanstackColumns = useMemo(
39
- () => reportColumnsToTanstack(report.columns, config.currency.code),
40
- [report.columns, config.currency.code],
41
- )
42
-
43
- return (
44
- <div className="space-y-4">
45
- {/* Breadcrumb — hidden in print */}
46
- <div className="flex items-center gap-1.5 text-sm no-print">
47
- <button
48
- onClick={onBack}
49
- className="flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors"
50
- >
51
- <ArrowLeft className="h-3.5 w-3.5" />
52
- {t('reports.pageTitle')}
53
- </button>
54
- <span className="text-muted-foreground">/</span>
55
- <span className="font-medium">{report.name}</span>
56
- </div>
57
-
58
- <div>
59
- <h2 className="text-lg font-bold">{report.name}</h2>
60
- {report.description && (
61
- <p className="text-xs text-muted-foreground mt-0.5">{report.description}</p>
62
- )}
63
- </div>
64
-
65
- {/* Filters + Generate — hidden in print */}
66
- <div className="flex flex-wrap items-end gap-3 no-print">
67
- <ReportFilterBar
68
- dateRange={query.dateRange}
69
- onDateRangeChange={setDateRange}
70
- filters={report.filters ?? []}
71
- filterValues={query.filters}
72
- onFilterChange={setFilter}
73
- />
74
- <Button onClick={generate} disabled={loading || !isAvailable} size="sm" className="h-9">
75
- {loading
76
- ? <Loader2 className="h-3.5 w-3.5 mr-1.5 animate-spin" />
77
- : <Play className="h-3.5 w-3.5 mr-1.5" />
78
- }
79
- {t('reports.generate')}
80
- </Button>
81
- {generated && (
82
- <>
83
- <ExportDropdown
84
- columns={report.columns}
85
- data={data}
86
- filename={report.id}
87
- currency={config.currency.code}
88
- title={report.name}
89
- />
90
- <Button variant="outline" size="sm" className="h-9" onClick={() => window.print()}>
91
- <Printer className="h-3.5 w-3.5 mr-1.5" />
92
- {t('reports.print')}
93
- </Button>
94
- </>
95
- )}
96
- </div>
97
-
98
- {/* Print-only: compact filter summary as document header */}
99
- {generated && (
100
- <div className="print-only hidden text-[10px] border-b pb-2 mb-2">
101
- <div className="flex flex-wrap gap-x-4 gap-y-0.5">
102
- {query.dateRange.from && (
103
- <span><strong>{t('reports.filterFrom')}:</strong> {new Date(query.dateRange.from + 'T12:00').toLocaleDateString()}</span>
104
- )}
105
- {query.dateRange.to && (
106
- <span><strong>{t('reports.filterTo')}:</strong> {new Date(query.dateRange.to + 'T12:00').toLocaleDateString()}</span>
107
- )}
108
- {Object.entries(query.filters).map(([key, value]) =>
109
- value ? <span key={key}><strong>{key}:</strong> {String(value)}</span> : null
110
- )}
111
- <span><strong>{t('reports.filterResults')}:</strong> {total}</span>
112
- </div>
113
- </div>
114
- )}
115
-
116
- {/* Error */}
117
- {error && (
118
- <div className="rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive">
119
- {error}
120
- </div>
121
- )}
122
-
123
- {/* Empty state — before generate */}
124
- {!generated && !loading && (
125
- <div className="flex flex-col items-center justify-center rounded-xl border border-dashed py-16 text-center">
126
- {isAvailable ? (
127
- <>
128
- <div className="flex h-12 w-12 items-center justify-center rounded-full bg-muted mb-4">
129
- <SlidersHorizontal className="h-5 w-5 text-muted-foreground" />
130
- </div>
131
- <p className="font-medium">{t('reports.emptyStateTitle')}</p>
132
- <p className="text-sm text-muted-foreground mt-1 max-w-sm">{t('reports.emptyStateDescription')}</p>
133
- </>
134
- ) : (
135
- <>
136
- <div className="flex h-12 w-12 items-center justify-center rounded-full bg-muted mb-4">
137
- <Construction className="h-5 w-5 text-muted-foreground" />
138
- </div>
139
- <p className="font-medium">{t('reports.unavailableTitle')}</p>
140
- <p className="text-sm text-muted-foreground mt-1 max-w-sm">{t('reports.unavailableDescription')}</p>
141
- </>
142
- )}
143
- </div>
144
- )}
145
-
146
- {/* Results — only shown after generate */}
147
- {(generated || loading) && (
148
- <>
149
- <DataTable
150
- columns={tanstackColumns}
151
- data={data}
152
- loading={loading}
153
- skeletonRows={5}
154
- emptyMessage={t('reports.noResults')}
155
- variant="card"
156
- compact
157
- />
158
-
159
- {report.showSummary && !loading && (
160
- <ReportSummaryRow
161
- columns={report.columns}
162
- data={data}
163
- currency={config.currency.code}
164
- />
165
- )}
166
-
167
- {!loading && (
168
- <div className="no-print">
169
- <ReportPagination
170
- page={query.page}
171
- pageSize={query.pageSize}
172
- total={total}
173
- onPageChange={setPage}
174
- onPageSizeChange={setPageSize}
175
- />
176
- </div>
177
- )}
178
- </>
179
- )}
180
- </div>
181
- )
182
- }