@pattern-stack/frontend-patterns 0.0.4 → 0.0.6
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/atoms/composed/SalesPanel/SalesPanel.d.ts +19 -0
- package/dist/atoms/composed/SalesPanel/SalesPanel.d.ts.map +1 -0
- package/dist/atoms/composed/SalesPanel/index.d.ts +2 -0
- package/dist/atoms/composed/SalesPanel/index.d.ts.map +1 -0
- package/dist/atoms/composed/SalesPanel/mockSalesData.d.ts +63 -0
- package/dist/atoms/composed/SalesPanel/mockSalesData.d.ts.map +1 -0
- package/dist/atoms/composed/index.d.ts +1 -0
- package/dist/atoms/composed/index.d.ts.map +1 -1
- package/dist/atoms/types/entity-config.d.ts +117 -0
- package/dist/atoms/types/entity-config.d.ts.map +1 -0
- package/dist/atoms/types/index.d.ts +2 -0
- package/dist/atoms/types/index.d.ts.map +1 -1
- package/dist/atoms/types/navigation.d.ts +30 -0
- package/dist/atoms/types/navigation.d.ts.map +1 -0
- package/dist/atoms/ui/ErrorBoundary.d.ts +1 -1
- package/dist/atoms/ui/button.d.ts +1 -1
- package/dist/atoms/utils/icon-resolver.d.ts +72 -0
- package/dist/atoms/utils/icon-resolver.d.ts.map +1 -0
- package/dist/atoms/utils/metric-engine.d.ts +30 -0
- package/dist/atoms/utils/metric-engine.d.ts.map +1 -0
- package/dist/atoms/utils/utils.d.ts +2 -0
- package/dist/atoms/utils/utils.d.ts.map +1 -1
- package/dist/features/auth/components/ProtectedRoute.d.ts +1 -1
- package/dist/frontend-patterns.css +1 -1
- package/dist/index.es.js +402 -14
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +402 -14
- package/dist/index.js.map +1 -1
- package/dist/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.d.ts +16 -0
- package/dist/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.d.ts.map +1 -0
- package/dist/molecules/layout/DashboardWithSidePanel/index.d.ts +2 -0
- package/dist/molecules/layout/DashboardWithSidePanel/index.d.ts.map +1 -0
- package/dist/molecules/layout/NavigationContext.d.ts +15 -0
- package/dist/molecules/layout/NavigationContext.d.ts.map +1 -0
- package/dist/molecules/layout/Sidebar.d.ts.map +1 -1
- package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts +2 -0
- package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts.map +1 -1
- package/dist/molecules/layout/index.d.ts +3 -0
- package/dist/molecules/layout/index.d.ts.map +1 -1
- package/dist/templates/factory.d.ts +2 -1
- package/dist/templates/factory.d.ts.map +1 -1
- package/dist/templates/index.d.ts.map +1 -1
- package/package.json +7 -3
- package/src/App.tsx +11 -1
- package/src/__tests__/atoms/composed/databadge.test.tsx +106 -0
- package/src/__tests__/atoms/composed/statcard.test.tsx +133 -0
- package/src/__tests__/atoms/utils/icon-resolver.test.tsx +140 -0
- package/src/atoms/composed/SalesPanel/SalesPanel.tsx +116 -0
- package/src/atoms/composed/SalesPanel/index.ts +1 -0
- package/src/atoms/composed/SalesPanel/mockSalesData.ts +151 -0
- package/src/atoms/composed/index.ts +1 -0
- package/src/atoms/types/entity-config.ts +127 -0
- package/src/atoms/types/index.ts +3 -1
- package/src/atoms/types/navigation.ts +43 -0
- package/src/atoms/utils/icon-resolver.tsx +54 -0
- package/src/atoms/utils/metric-engine.ts +236 -0
- package/src/atoms/utils/utils.ts +4 -2
- package/src/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.tsx +42 -0
- package/src/molecules/layout/DashboardWithSidePanel/index.ts +1 -0
- package/src/molecules/layout/NavigationContext.tsx +63 -0
- package/src/molecules/layout/Sidebar.tsx +10 -23
- package/src/molecules/layout/SidebarButton/SidebarButton.tsx +32 -10
- package/src/molecules/layout/index.ts +4 -1
- package/src/organisms/entity/CategoryBreakdownPanel.tsx +427 -0
- package/src/organisms/entity/EntityListPanel.tsx +339 -0
- package/src/organisms/entity/MetricsOverviewPanel.tsx +236 -0
- package/src/organisms/entity/TrendAnalysisPanel.tsx +337 -0
- package/src/organisms/entity/index.ts +4 -0
- package/src/organisms/index.ts +5 -1
- package/src/pages/AdminShowcase/AdminDashboardShowcase.tsx +77 -75
- package/src/pages/AdminShowcase/SalesPerformanceDashboard.tsx +158 -0
- package/src/pages/AdminShowcase/index.tsx +2 -1
- package/src/pages/EntityShowcase/EntityManagementShowcase.tsx +137 -0
- package/src/pages/EntityShowcase/EntityPerformanceShowcase.tsx +117 -0
- package/src/pages/EntityShowcase/index.ts +2 -0
- package/src/pages/EntityTemplateExample.tsx +229 -0
- package/src/pages/TestEntityTemplate.tsx +40 -0
- package/src/pages/index.ts +2 -1
- package/src/templates/entity/EntityManagementTemplate.tsx +430 -0
- package/src/templates/entity/EntityPerformanceDashboardTemplate.tsx +277 -0
- package/src/templates/entity/configs/financial-config.ts +141 -0
- package/src/templates/entity/configs/index.ts +1 -0
- package/src/templates/entity/index.ts +3 -0
- package/src/templates/factory.tsx +14 -7
- package/src/templates/financial/FinancialDashboardTemplate.tsx +326 -0
- package/src/templates/index.ts +4 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { cn } from '../../atoms/utils/utils';
|
|
3
|
+
import { SectionHeader } from '../../molecules/layout/SectionHeader';
|
|
4
|
+
import { Card } from '../../atoms/ui/card';
|
|
5
|
+
import { StatCard } from '../../atoms/composed/StatCard';
|
|
6
|
+
import { DashboardGrid } from '../DashboardTemplate';
|
|
7
|
+
import { DataBadge } from '../../atoms/composed/DataBadge';
|
|
8
|
+
import { TrendingUp, TrendingDown, DollarSign, PiggyBank, Target, AlertTriangle } from 'lucide-react';
|
|
9
|
+
|
|
10
|
+
export interface FinancialOverviewProps {
|
|
11
|
+
/** Total account balance */
|
|
12
|
+
totalBalance: number;
|
|
13
|
+
/** Monthly income */
|
|
14
|
+
monthlyIncome?: number;
|
|
15
|
+
/** Monthly expenses */
|
|
16
|
+
monthlyExpenses?: number;
|
|
17
|
+
/** Net worth change */
|
|
18
|
+
netWorthChange?: {
|
|
19
|
+
amount: number;
|
|
20
|
+
percentage: number;
|
|
21
|
+
period: string;
|
|
22
|
+
};
|
|
23
|
+
/** Savings rate */
|
|
24
|
+
savingsRate?: number;
|
|
25
|
+
/** Budget utilization */
|
|
26
|
+
budgetUtilization?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface AccountSummary {
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
type: 'checking' | 'savings' | 'credit' | 'investment' | 'loan';
|
|
33
|
+
balance: number;
|
|
34
|
+
change?: {
|
|
35
|
+
amount: number;
|
|
36
|
+
percentage: number;
|
|
37
|
+
};
|
|
38
|
+
status?: 'healthy' | 'warning' | 'critical';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface BudgetAlert {
|
|
42
|
+
id: string;
|
|
43
|
+
category: string;
|
|
44
|
+
spent: number;
|
|
45
|
+
budget: number;
|
|
46
|
+
severity: 'warning' | 'critical';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface FinancialGoal {
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
target: number;
|
|
53
|
+
current: number;
|
|
54
|
+
deadline?: string;
|
|
55
|
+
status: 'on-track' | 'behind' | 'achieved';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface FinancialDashboardTemplateProps {
|
|
59
|
+
/** Page title */
|
|
60
|
+
title?: string;
|
|
61
|
+
/** Page description */
|
|
62
|
+
description?: string;
|
|
63
|
+
/** Financial overview metrics */
|
|
64
|
+
overview: FinancialOverviewProps;
|
|
65
|
+
/** Account summaries */
|
|
66
|
+
accounts?: AccountSummary[];
|
|
67
|
+
/** Budget alerts */
|
|
68
|
+
budgetAlerts?: BudgetAlert[];
|
|
69
|
+
/** Financial goals */
|
|
70
|
+
goals?: FinancialGoal[];
|
|
71
|
+
/** Recent transactions preview */
|
|
72
|
+
recentTransactions?: Array<{
|
|
73
|
+
id: string;
|
|
74
|
+
description: string;
|
|
75
|
+
amount: number;
|
|
76
|
+
category: string;
|
|
77
|
+
date: string;
|
|
78
|
+
}>;
|
|
79
|
+
/** Header actions */
|
|
80
|
+
actions?: React.ReactNode;
|
|
81
|
+
/** Additional content */
|
|
82
|
+
children?: React.ReactNode;
|
|
83
|
+
/** Additional CSS classes */
|
|
84
|
+
className?: string;
|
|
85
|
+
/** Category-based styling */
|
|
86
|
+
category?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
|
87
|
+
/** Loading state */
|
|
88
|
+
isLoading?: boolean;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const FinancialDashboardTemplate: React.FC<FinancialDashboardTemplateProps> = ({
|
|
92
|
+
title = "Financial Dashboard",
|
|
93
|
+
description = "Your complete financial overview",
|
|
94
|
+
overview,
|
|
95
|
+
accounts = [],
|
|
96
|
+
budgetAlerts = [],
|
|
97
|
+
goals = [],
|
|
98
|
+
recentTransactions = [],
|
|
99
|
+
actions,
|
|
100
|
+
children,
|
|
101
|
+
className,
|
|
102
|
+
category = 2, // Green theme for financial
|
|
103
|
+
isLoading = false
|
|
104
|
+
}) => {
|
|
105
|
+
const formatCurrency = (amount: number) => {
|
|
106
|
+
return new Intl.NumberFormat('en-US', {
|
|
107
|
+
style: 'currency',
|
|
108
|
+
currency: 'USD'
|
|
109
|
+
}).format(amount);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const getAccountIcon = (type: AccountSummary['type']) => {
|
|
113
|
+
switch (type) {
|
|
114
|
+
case 'savings': return <PiggyBank className="w-4 h-4" />;
|
|
115
|
+
case 'investment': return <TrendingUp className="w-4 h-4" />;
|
|
116
|
+
case 'credit': return <AlertTriangle className="w-4 h-4" />;
|
|
117
|
+
default: return <DollarSign className="w-4 h-4" />;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const getAccountStatus = (account: AccountSummary) => {
|
|
122
|
+
if (account.type === 'credit' && account.balance > 0) return 'warning';
|
|
123
|
+
if (account.type === 'loan' && account.balance > 0) return 'error';
|
|
124
|
+
return account.status || 'success';
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<div className={cn('flex flex-col min-h-0 flex-1', className)}>
|
|
129
|
+
{/* Header Section */}
|
|
130
|
+
<div className="flex-shrink-0 border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
131
|
+
<div className="container mx-auto px-6 py-6">
|
|
132
|
+
<div className="flex items-start justify-between">
|
|
133
|
+
<div className="flex-1 min-w-0">
|
|
134
|
+
<SectionHeader
|
|
135
|
+
title={title}
|
|
136
|
+
description={description}
|
|
137
|
+
size="lg"
|
|
138
|
+
className="text-left"
|
|
139
|
+
/>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
{actions && (
|
|
143
|
+
<div className="ml-6 flex-shrink-0">
|
|
144
|
+
{actions}
|
|
145
|
+
</div>
|
|
146
|
+
)}
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
|
|
151
|
+
{/* Main Content */}
|
|
152
|
+
<div className="flex-1 min-h-0 overflow-auto">
|
|
153
|
+
<div className="container mx-auto px-6 py-6 space-y-6">
|
|
154
|
+
{/* Financial Overview */}
|
|
155
|
+
<div>
|
|
156
|
+
<h2 className="text-lg font-semibold mb-4">Financial Overview</h2>
|
|
157
|
+
<DashboardGrid columns={4} gap="md">
|
|
158
|
+
<StatCard
|
|
159
|
+
title="Total Balance"
|
|
160
|
+
value={formatCurrency(overview.totalBalance)}
|
|
161
|
+
icon={<DollarSign className="w-5 h-5" />}
|
|
162
|
+
category={category}
|
|
163
|
+
isLoading={isLoading}
|
|
164
|
+
/>
|
|
165
|
+
|
|
166
|
+
{overview.monthlyIncome && (
|
|
167
|
+
<StatCard
|
|
168
|
+
title="Monthly Income"
|
|
169
|
+
value={formatCurrency(overview.monthlyIncome)}
|
|
170
|
+
icon={<TrendingUp className="w-5 h-5" />}
|
|
171
|
+
category={category}
|
|
172
|
+
isLoading={isLoading}
|
|
173
|
+
/>
|
|
174
|
+
)}
|
|
175
|
+
|
|
176
|
+
{overview.monthlyExpenses && (
|
|
177
|
+
<StatCard
|
|
178
|
+
title="Monthly Expenses"
|
|
179
|
+
value={formatCurrency(overview.monthlyExpenses)}
|
|
180
|
+
icon={<TrendingDown className="w-5 h-5" />}
|
|
181
|
+
category={category}
|
|
182
|
+
isLoading={isLoading}
|
|
183
|
+
/>
|
|
184
|
+
)}
|
|
185
|
+
|
|
186
|
+
{overview.savingsRate && (
|
|
187
|
+
<StatCard
|
|
188
|
+
title="Savings Rate"
|
|
189
|
+
value={`${overview.savingsRate}%`}
|
|
190
|
+
icon={<Target className="w-5 h-5" />}
|
|
191
|
+
category={category}
|
|
192
|
+
isLoading={isLoading}
|
|
193
|
+
/>
|
|
194
|
+
)}
|
|
195
|
+
</DashboardGrid>
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
{/* Accounts Overview */}
|
|
199
|
+
{accounts.length > 0 && (
|
|
200
|
+
<div>
|
|
201
|
+
<h2 className="text-lg font-semibold mb-4">Accounts</h2>
|
|
202
|
+
<DashboardGrid columns={2} gap="md">
|
|
203
|
+
{accounts.map((account) => (
|
|
204
|
+
<Card key={account.id} category={category} className="p-4">
|
|
205
|
+
<div className="flex items-start justify-between">
|
|
206
|
+
<div className="flex items-center gap-3">
|
|
207
|
+
{getAccountIcon(account.type)}
|
|
208
|
+
<div>
|
|
209
|
+
<h3 className="font-medium">{account.name}</h3>
|
|
210
|
+
<p className="text-sm text-muted-foreground capitalize">{account.type}</p>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
<div className="text-right">
|
|
214
|
+
<p className="font-semibold">{formatCurrency(account.balance)}</p>
|
|
215
|
+
{account.change && (
|
|
216
|
+
<div className="flex items-center gap-1 text-sm">
|
|
217
|
+
{account.change.amount > 0 ? (
|
|
218
|
+
<TrendingUp className="w-3 h-3 text-green-500" />
|
|
219
|
+
) : (
|
|
220
|
+
<TrendingDown className="w-3 h-3 text-red-500" />
|
|
221
|
+
)}
|
|
222
|
+
<span className={account.change.amount > 0 ? 'text-green-500' : 'text-red-500'}>
|
|
223
|
+
{Math.abs(account.change.percentage)}%
|
|
224
|
+
</span>
|
|
225
|
+
</div>
|
|
226
|
+
)}
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
<div className="mt-3">
|
|
230
|
+
<DataBadge
|
|
231
|
+
variant="status"
|
|
232
|
+
status={getAccountStatus(account)}
|
|
233
|
+
>
|
|
234
|
+
{account.status || 'healthy'}
|
|
235
|
+
</DataBadge>
|
|
236
|
+
</div>
|
|
237
|
+
</Card>
|
|
238
|
+
))}
|
|
239
|
+
</DashboardGrid>
|
|
240
|
+
</div>
|
|
241
|
+
)}
|
|
242
|
+
|
|
243
|
+
{/* Budget Alerts */}
|
|
244
|
+
{budgetAlerts.length > 0 && (
|
|
245
|
+
<div>
|
|
246
|
+
<h2 className="text-lg font-semibold mb-4">Budget Alerts</h2>
|
|
247
|
+
<div className="space-y-3">
|
|
248
|
+
{budgetAlerts.map((alert) => (
|
|
249
|
+
<Card key={alert.id} className="p-4">
|
|
250
|
+
<div className="flex items-center justify-between">
|
|
251
|
+
<div className="flex items-center gap-3">
|
|
252
|
+
<AlertTriangle className={cn(
|
|
253
|
+
"w-5 h-5",
|
|
254
|
+
alert.severity === 'critical' ? 'text-red-500' : 'text-yellow-500'
|
|
255
|
+
)} />
|
|
256
|
+
<div>
|
|
257
|
+
<h3 className="font-medium">{alert.category}</h3>
|
|
258
|
+
<p className="text-sm text-muted-foreground">
|
|
259
|
+
{formatCurrency(alert.spent)} of {formatCurrency(alert.budget)} spent
|
|
260
|
+
</p>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
<div className="text-right">
|
|
264
|
+
<DataBadge
|
|
265
|
+
variant="status"
|
|
266
|
+
status={alert.severity === 'critical' ? 'error' : 'warning'}
|
|
267
|
+
>
|
|
268
|
+
{Math.round((alert.spent / alert.budget) * 100)}% used
|
|
269
|
+
</DataBadge>
|
|
270
|
+
</div>
|
|
271
|
+
</div>
|
|
272
|
+
</Card>
|
|
273
|
+
))}
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
)}
|
|
277
|
+
|
|
278
|
+
{/* Financial Goals */}
|
|
279
|
+
{goals.length > 0 && (
|
|
280
|
+
<div>
|
|
281
|
+
<h2 className="text-lg font-semibold mb-4">Financial Goals</h2>
|
|
282
|
+
<DashboardGrid columns={1} gap="md">
|
|
283
|
+
{goals.map((goal) => {
|
|
284
|
+
const progress = (goal.current / goal.target) * 100;
|
|
285
|
+
return (
|
|
286
|
+
<Card key={goal.id} category={category} className="p-4">
|
|
287
|
+
<div className="flex items-start justify-between mb-3">
|
|
288
|
+
<div>
|
|
289
|
+
<h3 className="font-medium">{goal.name}</h3>
|
|
290
|
+
<p className="text-sm text-muted-foreground">
|
|
291
|
+
{formatCurrency(goal.current)} of {formatCurrency(goal.target)}
|
|
292
|
+
</p>
|
|
293
|
+
</div>
|
|
294
|
+
<DataBadge
|
|
295
|
+
variant="status"
|
|
296
|
+
status={goal.status === 'achieved' ? 'success' : goal.status === 'behind' ? 'warning' : 'info'}
|
|
297
|
+
>
|
|
298
|
+
{goal.status}
|
|
299
|
+
</DataBadge>
|
|
300
|
+
</div>
|
|
301
|
+
<div className="w-full bg-muted rounded-full h-2">
|
|
302
|
+
<div
|
|
303
|
+
className={cn(
|
|
304
|
+
'h-2 rounded-full transition-all',
|
|
305
|
+
`bg-category-${category}`
|
|
306
|
+
)}
|
|
307
|
+
style={{ width: `${Math.min(progress, 100)}%` }}
|
|
308
|
+
/>
|
|
309
|
+
</div>
|
|
310
|
+
<p className="text-sm text-muted-foreground mt-2">
|
|
311
|
+
{Math.round(progress)}% complete
|
|
312
|
+
</p>
|
|
313
|
+
</Card>
|
|
314
|
+
);
|
|
315
|
+
})}
|
|
316
|
+
</DashboardGrid>
|
|
317
|
+
</div>
|
|
318
|
+
)}
|
|
319
|
+
|
|
320
|
+
{/* Additional Content */}
|
|
321
|
+
{children}
|
|
322
|
+
</div>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
);
|
|
326
|
+
};
|
package/src/templates/index.ts
CHANGED
|
@@ -28,6 +28,10 @@ export {
|
|
|
28
28
|
// Admin templates for administrative interfaces
|
|
29
29
|
export * from './admin';
|
|
30
30
|
|
|
31
|
+
// Entity templates for cross-domain configurable layouts
|
|
32
|
+
// TODO: Fix TypeScript errors in entity templates before uncommenting
|
|
33
|
+
// export * from './entity';
|
|
34
|
+
|
|
31
35
|
// React App Factory
|
|
32
36
|
export {
|
|
33
37
|
createReactApp,
|