@fayz-ai/plugin-dashboard 0.1.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.
- package/dist/DashboardPage.d.ts +23 -0
- package/dist/DashboardPage.d.ts.map +1 -0
- package/dist/builders.d.ts +13 -0
- package/dist/builders.d.ts.map +1 -0
- package/dist/index.cjs +286 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +242 -0
- package/dist/index.js.map +1 -0
- package/dist/locales/en.d.ts +2 -0
- package/dist/locales/en.d.ts.map +1 -0
- package/dist/locales/index.d.ts +2 -0
- package/dist/locales/index.d.ts.map +1 -0
- package/dist/locales/pt-BR.d.ts +2 -0
- package/dist/locales/pt-BR.d.ts.map +1 -0
- package/dist/types.d.ts +102 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +52 -0
- package/src/DashboardPage.tsx +42 -0
- package/src/builders.tsx +94 -0
- package/src/index.ts +200 -0
- package/src/locales/en.ts +23 -0
- package/src/locales/index.ts +7 -0
- package/src/locales/pt-BR.ts +23 -0
- package/src/types.ts +127 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import type { PluginManifest, PluginScope, VerticalId, DashboardWidgetDef, DashboardLayoutConfig } from '@fayz-ai/core'
|
|
3
|
+
import { DashboardCanvas, type DashboardCanvasProps } from '@fayz-ai/ui'
|
|
4
|
+
import { DashboardPage } from './DashboardPage'
|
|
5
|
+
import { metricsToWidgets, sectionsToWidgets, onboardingToWidget } from './builders'
|
|
6
|
+
import { dashboardLocales } from './locales'
|
|
7
|
+
import type { DashboardMetric, DashboardSection, OnboardingStep } from './types'
|
|
8
|
+
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Public types
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
export interface DashboardPluginLabels {
|
|
14
|
+
pageTitle: string
|
|
15
|
+
pageSubtitle: string
|
|
16
|
+
kpiTitle: string
|
|
17
|
+
onboardingTitle: string
|
|
18
|
+
onboardingSubtitle: string
|
|
19
|
+
settingsTitle: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface DashboardPluginOptions {
|
|
23
|
+
/** KPI metrics to show on the dashboard */
|
|
24
|
+
metrics?: DashboardMetric[]
|
|
25
|
+
/** Custom sections injected by the consumer app */
|
|
26
|
+
sections?: DashboardSection[]
|
|
27
|
+
/** Onboarding steps for the getting-started checklist */
|
|
28
|
+
onboardingSteps?: OnboardingStep[]
|
|
29
|
+
/** Label overrides */
|
|
30
|
+
labels?: Partial<DashboardPluginLabels>
|
|
31
|
+
/** Currency config for metrics that use 'currency' format */
|
|
32
|
+
currency?: { code?: string; locale?: string; symbol?: string }
|
|
33
|
+
/** Plugin scope */
|
|
34
|
+
scope?: PluginScope
|
|
35
|
+
/** Vertical ID */
|
|
36
|
+
verticalId?: VerticalId
|
|
37
|
+
/** Whether to show onboarding module. Default: true if onboardingSteps provided */
|
|
38
|
+
showOnboarding?: boolean
|
|
39
|
+
/** Nav position (default: 0 — first item) */
|
|
40
|
+
navPosition?: number
|
|
41
|
+
/** Nav section (default: 'main') */
|
|
42
|
+
navSection?: 'main' | 'secondary'
|
|
43
|
+
/** Navigation icon override (default: 'LayoutDashboard') */
|
|
44
|
+
navIcon?: string
|
|
45
|
+
/** Skip adding a navigation entry (use when the consumer app provides its own page entry for '/') */
|
|
46
|
+
skipNavigation?: boolean
|
|
47
|
+
/** Render the in-content title/subtitle. Set false when the app shell owns the
|
|
48
|
+
* page title (sidebar/GHL-style layouts). Default: true. */
|
|
49
|
+
showHeader?: boolean
|
|
50
|
+
/** App-level curation of the home surface — which widgets show, order, span.
|
|
51
|
+
* Applied on top of every plugin's registered defaults. */
|
|
52
|
+
layout?: DashboardLayoutConfig
|
|
53
|
+
/** Custom widgets the consumer app contributes directly to the home surface. */
|
|
54
|
+
customWidgets?: DashboardWidgetDef[]
|
|
55
|
+
/** Show the shared, sticky time-range control on the home. Pass `true` for
|
|
56
|
+
* defaults (7d/30d/90d) or an options object. Widgets read it via
|
|
57
|
+
* useDashboardRange(); provide `onChange` to drive app-level refetching. */
|
|
58
|
+
range?: DashboardCanvasProps['range']
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Defaults
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
const DEFAULT_LABELS: DashboardPluginLabels = {
|
|
66
|
+
pageTitle: 'Dashboard',
|
|
67
|
+
pageSubtitle: 'Business overview',
|
|
68
|
+
kpiTitle: 'Key Metrics',
|
|
69
|
+
onboardingTitle: 'Getting Started',
|
|
70
|
+
onboardingSubtitle: 'Complete these steps to set up your business',
|
|
71
|
+
settingsTitle: 'Dashboard',
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Factory
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
export function createDashboardPlugin(options?: DashboardPluginOptions): PluginManifest {
|
|
79
|
+
const labels: DashboardPluginLabels = { ...DEFAULT_LABELS, ...options?.labels }
|
|
80
|
+
const onboardingSteps = options?.onboardingSteps ?? []
|
|
81
|
+
const showOnboarding = options?.showOnboarding ?? onboardingSteps.length > 0
|
|
82
|
+
|
|
83
|
+
// Everything the dashboard plugin owns flows through the widget registry:
|
|
84
|
+
// legacy metrics/sections, the onboarding checklist, and app custom widgets.
|
|
85
|
+
const dashboardWidgets: DashboardWidgetDef[] = [
|
|
86
|
+
...metricsToWidgets(options?.metrics ?? [], options?.currency),
|
|
87
|
+
...sectionsToWidgets(options?.sections ?? []),
|
|
88
|
+
...(showOnboarding && onboardingSteps.length > 0
|
|
89
|
+
? [onboardingToWidget(onboardingSteps, { title: labels.onboardingTitle, subtitle: labels.onboardingSubtitle })]
|
|
90
|
+
: []),
|
|
91
|
+
...(options?.customWidgets ?? []),
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
const PageComponent: React.ComponentType<unknown> = () =>
|
|
95
|
+
React.createElement(DashboardCanvas, {
|
|
96
|
+
surface: 'home',
|
|
97
|
+
title: labels.pageTitle,
|
|
98
|
+
subtitle: labels.pageSubtitle,
|
|
99
|
+
showHeader: options?.showHeader,
|
|
100
|
+
appLayout: options?.layout,
|
|
101
|
+
range: options?.range,
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
id: 'dashboard',
|
|
106
|
+
name: labels.pageTitle,
|
|
107
|
+
icon: 'LayoutDashboard',
|
|
108
|
+
version: '1.0.0',
|
|
109
|
+
scope: options?.scope ?? 'universal',
|
|
110
|
+
verticalId: options?.verticalId,
|
|
111
|
+
defaultEnabled: true,
|
|
112
|
+
dependencies: [],
|
|
113
|
+
declaredFeatures: [
|
|
114
|
+
{ id: 'dashboard', label: labels.pageTitle, group: 'Core' },
|
|
115
|
+
],
|
|
116
|
+
|
|
117
|
+
navigation: options?.skipNavigation ? [] : [
|
|
118
|
+
{
|
|
119
|
+
section: options?.navSection ?? 'main',
|
|
120
|
+
position: options?.navPosition ?? 0,
|
|
121
|
+
label: labels.pageTitle,
|
|
122
|
+
route: '/',
|
|
123
|
+
icon: options?.navIcon ?? 'LayoutDashboard',
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
|
|
127
|
+
routes: [
|
|
128
|
+
{
|
|
129
|
+
path: '/',
|
|
130
|
+
component: PageComponent,
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
|
|
134
|
+
widgets: [],
|
|
135
|
+
dashboardWidgets,
|
|
136
|
+
|
|
137
|
+
aiTools: [
|
|
138
|
+
{
|
|
139
|
+
id: 'dashboard.kpi-summary',
|
|
140
|
+
name: 'getKpiSummary',
|
|
141
|
+
description: 'Returns a summary of all KPI metrics for the current dashboard, including trends and comparisons.',
|
|
142
|
+
icon: 'BarChart3',
|
|
143
|
+
mode: 'read' as const,
|
|
144
|
+
category: 'Dashboard',
|
|
145
|
+
parameters: {
|
|
146
|
+
type: 'object' as const,
|
|
147
|
+
properties: {
|
|
148
|
+
category: {
|
|
149
|
+
type: 'string' as const,
|
|
150
|
+
description: 'Filter by metric category',
|
|
151
|
+
enum: ['revenue', 'operations', 'clients', 'custom', 'all'],
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
suggestions: [
|
|
156
|
+
{ label: 'How is my business doing today?' },
|
|
157
|
+
{ label: "What's my revenue today?" },
|
|
158
|
+
{ label: 'Give me a summary of today' },
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
|
|
163
|
+
locales: dashboardLocales,
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
// Re-exports
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
export { DashboardPage } from './DashboardPage'
|
|
172
|
+
export {
|
|
173
|
+
DashboardCanvas,
|
|
174
|
+
DashboardNavigateProvider,
|
|
175
|
+
useDashboardNavigate,
|
|
176
|
+
resolveDashboardLayout,
|
|
177
|
+
useDashboardPreferences,
|
|
178
|
+
type DashboardCanvasProps,
|
|
179
|
+
type LaidOutWidget,
|
|
180
|
+
type DashboardPreferencesState,
|
|
181
|
+
} from '@fayz-ai/ui'
|
|
182
|
+
export {
|
|
183
|
+
metricsToWidgets,
|
|
184
|
+
sectionsToWidgets,
|
|
185
|
+
onboardingToWidget,
|
|
186
|
+
} from './builders'
|
|
187
|
+
|
|
188
|
+
export type {
|
|
189
|
+
DashboardMetric,
|
|
190
|
+
MetricValue,
|
|
191
|
+
MetricCategory,
|
|
192
|
+
MetricFormat,
|
|
193
|
+
ResolvedMetric,
|
|
194
|
+
DashboardSection,
|
|
195
|
+
DashboardSectionProps,
|
|
196
|
+
DashboardZone,
|
|
197
|
+
OnboardingStep,
|
|
198
|
+
OnboardingProgress,
|
|
199
|
+
DashboardPreferences,
|
|
200
|
+
} from './types'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const en: Record<string, string> = {
|
|
2
|
+
'dashboard.title': 'Dashboard',
|
|
3
|
+
'dashboard.subtitle': 'Business overview',
|
|
4
|
+
'dashboard.kpi.title': 'Key Metrics',
|
|
5
|
+
'dashboard.kpi.noData': 'No metrics configured',
|
|
6
|
+
'dashboard.kpi.error': 'Failed to load',
|
|
7
|
+
'dashboard.kpi.refresh': 'Refresh',
|
|
8
|
+
'dashboard.onboarding.title': 'Getting Started',
|
|
9
|
+
'dashboard.onboarding.subtitle': 'Complete these steps to set up your business',
|
|
10
|
+
'dashboard.onboarding.completed': 'Completed',
|
|
11
|
+
'dashboard.onboarding.allDone': "All done! You're all set.",
|
|
12
|
+
'dashboard.onboarding.dismiss': 'Dismiss',
|
|
13
|
+
'dashboard.onboarding.step': 'Step',
|
|
14
|
+
'dashboard.onboarding.of': 'of',
|
|
15
|
+
'dashboard.settings.title': 'Dashboard',
|
|
16
|
+
'dashboard.settings.subtitle': 'Choose which metrics appear on your dashboard',
|
|
17
|
+
'dashboard.settings.metricsVisibility': 'Visible Metrics',
|
|
18
|
+
'dashboard.settings.metricOrder': 'Metric Order',
|
|
19
|
+
'dashboard.settings.resetDefaults': 'Reset to Defaults',
|
|
20
|
+
'dashboard.settings.saved': 'Dashboard preferences saved',
|
|
21
|
+
'dashboard.empty.title': 'Welcome!',
|
|
22
|
+
'dashboard.empty.subtitle': 'Your dashboard will show key metrics and information here.',
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const ptBR: Record<string, string> = {
|
|
2
|
+
'dashboard.title': 'Painel',
|
|
3
|
+
'dashboard.subtitle': 'Visao geral do seu negocio',
|
|
4
|
+
'dashboard.kpi.title': 'Metricas',
|
|
5
|
+
'dashboard.kpi.noData': 'Nenhuma metrica configurada',
|
|
6
|
+
'dashboard.kpi.error': 'Falha ao carregar',
|
|
7
|
+
'dashboard.kpi.refresh': 'Atualizar',
|
|
8
|
+
'dashboard.onboarding.title': 'Primeiros Passos',
|
|
9
|
+
'dashboard.onboarding.subtitle': 'Complete estes passos para configurar seu negocio',
|
|
10
|
+
'dashboard.onboarding.completed': 'Concluido',
|
|
11
|
+
'dashboard.onboarding.allDone': 'Tudo pronto! Voce esta configurado.',
|
|
12
|
+
'dashboard.onboarding.dismiss': 'Dispensar',
|
|
13
|
+
'dashboard.onboarding.step': 'Passo',
|
|
14
|
+
'dashboard.onboarding.of': 'de',
|
|
15
|
+
'dashboard.settings.title': 'Painel',
|
|
16
|
+
'dashboard.settings.subtitle': 'Escolha quais metricas aparecem no seu painel',
|
|
17
|
+
'dashboard.settings.metricsVisibility': 'Metricas Visiveis',
|
|
18
|
+
'dashboard.settings.metricOrder': 'Ordem das Metricas',
|
|
19
|
+
'dashboard.settings.resetDefaults': 'Restaurar Padrao',
|
|
20
|
+
'dashboard.settings.saved': 'Preferencias do painel salvas',
|
|
21
|
+
'dashboard.empty.title': 'Bem-vindo!',
|
|
22
|
+
'dashboard.empty.subtitle': 'Seu painel mostrara metricas e informacoes importantes aqui.',
|
|
23
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type React from 'react'
|
|
2
|
+
import type { VerticalId } from '@fayz-ai/core'
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// KPI Metric system
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
export type MetricCategory = 'revenue' | 'operations' | 'clients' | 'custom'
|
|
9
|
+
export type MetricFormat = 'number' | 'currency' | 'percent' | 'duration'
|
|
10
|
+
|
|
11
|
+
export interface MetricValue {
|
|
12
|
+
/** Primary numeric value */
|
|
13
|
+
value: number
|
|
14
|
+
/** Comparison value for trend (e.g., yesterday, last week) */
|
|
15
|
+
previousValue?: number
|
|
16
|
+
/** Unit suffix (e.g., 'min', 'BRL') */
|
|
17
|
+
unit?: string
|
|
18
|
+
/** Trend direction for visual indicator */
|
|
19
|
+
trend?: 'up' | 'down' | 'neutral'
|
|
20
|
+
/** Optional series (oldest → newest) rendered as an inline sparkline. */
|
|
21
|
+
spark?: number[]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface DashboardMetric {
|
|
25
|
+
/** Unique metric ID, e.g. 'revenue-today' */
|
|
26
|
+
id: string
|
|
27
|
+
/** i18n key or plain label */
|
|
28
|
+
label: string
|
|
29
|
+
/** Tooltip description */
|
|
30
|
+
description?: string
|
|
31
|
+
/** Lucide icon name */
|
|
32
|
+
icon: string
|
|
33
|
+
/** Grouping category */
|
|
34
|
+
category: MetricCategory
|
|
35
|
+
/** Async function that computes the current value */
|
|
36
|
+
compute: () => Promise<MetricValue>
|
|
37
|
+
/** Whether visible by default (before user customization) */
|
|
38
|
+
defaultVisible: boolean
|
|
39
|
+
/** Default display order (lower = first) */
|
|
40
|
+
defaultOrder: number
|
|
41
|
+
/** How to format the value */
|
|
42
|
+
format?: MetricFormat
|
|
43
|
+
/** Render the card as a radial gauge toward this goal value. */
|
|
44
|
+
goal?: number
|
|
45
|
+
/** Accent color for the gauge/sparkline. Defaults to a trend-aware color. */
|
|
46
|
+
accent?: string
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface ResolvedMetric extends DashboardMetric {
|
|
50
|
+
/** Current computed value (null while loading) */
|
|
51
|
+
currentValue: MetricValue | null
|
|
52
|
+
/** Whether this metric is currently loading */
|
|
53
|
+
loading: boolean
|
|
54
|
+
/** Error message if compute() failed */
|
|
55
|
+
error?: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// Section system
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
export type DashboardZone = 'main' | 'sidebar' | 'bottom-right'
|
|
63
|
+
|
|
64
|
+
export interface DashboardSectionProps {
|
|
65
|
+
tenantId?: string
|
|
66
|
+
onNavigate?: (path: string) => void
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface DashboardSection {
|
|
70
|
+
/** Unique section ID */
|
|
71
|
+
id: string
|
|
72
|
+
/** i18n key or plain title */
|
|
73
|
+
title: string
|
|
74
|
+
/** Lucide icon name */
|
|
75
|
+
icon?: string
|
|
76
|
+
/** Zone placement on the dashboard */
|
|
77
|
+
zone: DashboardZone
|
|
78
|
+
/** Column span on the 4-col grid (1–4). Default: 2 (half width). */
|
|
79
|
+
span?: 1 | 2 | 3 | 4
|
|
80
|
+
/** Sort order within zone (lower = first) */
|
|
81
|
+
order: number
|
|
82
|
+
/** React component to render */
|
|
83
|
+
component: React.ComponentType<DashboardSectionProps>
|
|
84
|
+
/** Only show for specific verticals */
|
|
85
|
+
verticalId?: VerticalId
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// Onboarding system
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
|
|
92
|
+
export interface OnboardingStep {
|
|
93
|
+
/** Unique step ID, e.g. 'add-first-client' */
|
|
94
|
+
id: string
|
|
95
|
+
/** i18n key or plain title */
|
|
96
|
+
title: string
|
|
97
|
+
/** i18n key or plain description */
|
|
98
|
+
description: string
|
|
99
|
+
/** Lucide icon name */
|
|
100
|
+
icon: string
|
|
101
|
+
/** Async check: returns true if this step is already completed */
|
|
102
|
+
check: () => Promise<boolean>
|
|
103
|
+
/** Route path to navigate to, or a callback */
|
|
104
|
+
action: string | (() => void)
|
|
105
|
+
/** Sort order (lower = first) */
|
|
106
|
+
order: number
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface OnboardingProgress {
|
|
110
|
+
stepId: string
|
|
111
|
+
completedAt: string | null
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Preferences (DB-backed per-tenant)
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
export interface DashboardPreferences {
|
|
119
|
+
id: string
|
|
120
|
+
tenantId: string
|
|
121
|
+
/** Ordered list of metric IDs the user wants visible */
|
|
122
|
+
visibleMetrics: string[]
|
|
123
|
+
/** Full metric ordering (visible + hidden) */
|
|
124
|
+
metricOrder: string[]
|
|
125
|
+
createdAt: string
|
|
126
|
+
updatedAt: string
|
|
127
|
+
}
|