@wakastellar/ui 2.3.4 → 2.4.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.
- package/dist/blocks/dashboard/index.d.ts +4 -1
- package/dist/blocks/empty-states/index.d.ts +4 -1
- package/dist/blocks/error-pages/index.d.ts +4 -1
- package/dist/blocks/index.d.ts +1 -1
- package/dist/blocks/landing/index.d.ts +4 -1
- package/dist/blocks/pricing/index.d.ts +5 -1
- package/dist/blocks/sidebar/index.d.ts +5 -1
- package/dist/index.cjs.js +130 -130
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +7905 -7856
- package/dist/stories/Button.d.ts +14 -0
- package/dist/stories/Button.stories.d.ts +8 -0
- package/dist/stories/Header.d.ts +11 -0
- package/dist/stories/Header.stories.d.ts +6 -0
- package/dist/stories/Page.d.ts +2 -0
- package/dist/stories/Page.stories.d.ts +6 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/link.d.ts +23 -0
- package/package.json +11 -3
- package/src/blocks/activity-timeline/ActivityTimeline.stories.tsx +460 -0
- package/src/blocks/apm-overview/APMOverview.stories.tsx +435 -0
- package/src/blocks/auth-2fa/Auth2FA.stories.tsx +308 -0
- package/src/blocks/calendar-view/CalendarView.stories.tsx +398 -0
- package/src/blocks/chat/Chat.stories.tsx +466 -0
- package/src/blocks/chat-interface/ChatInterface.stories.tsx +412 -0
- package/src/blocks/checkout-flow/CheckoutFlow.stories.tsx +408 -0
- package/src/blocks/cicd-builder/CICDBuilder.stories.tsx +499 -0
- package/src/blocks/cloud-cost-dashboard/CloudCostDashboard.stories.tsx +356 -0
- package/src/blocks/container-orchestrator/ContainerOrchestrator.stories.tsx +461 -0
- package/src/blocks/dashboard/Dashboard.stories.tsx +559 -0
- package/src/blocks/dashboard/index.tsx +68 -27
- package/src/blocks/dashboard-kpi/DashboardKPI.stories.tsx +422 -0
- package/src/blocks/database-admin/DatabaseAdmin.stories.tsx +393 -0
- package/src/blocks/deployment-dashboard/DeploymentDashboard.stories.tsx +457 -0
- package/src/blocks/empty-states/EmptyStates.stories.tsx +467 -0
- package/src/blocks/empty-states/index.tsx +26 -8
- package/src/blocks/error-pages/ErrorPages.stories.tsx +401 -0
- package/src/blocks/error-pages/index.tsx +26 -8
- package/src/blocks/faq/FAQ.stories.tsx +416 -0
- package/src/blocks/file-manager/FileManager.stories.tsx +413 -0
- package/src/blocks/footer/Footer.stories.tsx +328 -0
- package/src/blocks/gitops-sync-status/GitOpsSyncStatus.stories.tsx +529 -0
- package/src/blocks/header/WakaHeader.stories.tsx +455 -0
- package/src/blocks/headtab/Headtab.stories.tsx +369 -0
- package/src/blocks/i18n-editor/I18nEditor.stories.tsx +451 -0
- package/src/blocks/incident-manager/IncidentManager.stories.tsx +464 -0
- package/src/blocks/index.ts +1 -1
- package/src/blocks/infrastructure-map/InfrastructureMap.stories.tsx +533 -0
- package/src/blocks/kanban-board/KanbanBoard.stories.tsx +494 -0
- package/src/blocks/landing/WakaLanding.stories.tsx +449 -0
- package/src/blocks/landing/index.tsx +125 -66
- package/src/blocks/language-selector/LanguageSelector.stories.tsx +345 -0
- package/src/blocks/layout/Layout.stories.tsx +373 -0
- package/src/blocks/login/Login.stories.tsx +443 -0
- package/src/blocks/on-call-schedule/OnCallSchedule.stories.tsx +381 -0
- package/src/blocks/player-profile/PlayerProfile.stories.tsx +316 -0
- package/src/blocks/pricing/WakaPricing.stories.tsx +530 -0
- package/src/blocks/pricing/index.tsx +38 -4
- package/src/blocks/profile/Profile.stories.tsx +371 -0
- package/src/blocks/release-notes/ReleaseNotes.stories.tsx +431 -0
- package/src/blocks/settings/Settings.stories.tsx +520 -0
- package/src/blocks/sidebar/WakaSidebar.stories.tsx +513 -0
- package/src/blocks/sidebar/index.tsx +49 -20
- package/src/blocks/theme-creator-block/ThemeCreatorBlock.stories.tsx +370 -0
- package/src/blocks/user-management/UserManagement.stories.tsx +411 -0
- package/src/blocks/wizard/Wizard.stories.tsx +683 -0
- package/src/components/accordion/Accordion.stories.tsx +93 -0
- package/src/components/alert/Alert.stories.tsx +95 -0
- package/src/components/alert-dialog/AlertDialog.stories.tsx +126 -0
- package/src/components/aspect-ratio/AspectRatio.stories.tsx +118 -0
- package/src/components/avatar/Avatar.stories.tsx +104 -0
- package/src/components/button/Button.stories.tsx +12 -1
- package/src/components/calendar/Calendar.stories.tsx +102 -0
- package/src/components/card/Card.stories.tsx +125 -0
- package/src/components/checkbox/Checkbox.stories.tsx +100 -0
- package/src/components/code/Code.stories.tsx +402 -0
- package/src/components/collapsible/Collapsible.stories.tsx +123 -0
- package/src/components/command/Command.stories.tsx +207 -0
- package/src/components/context-menu/ContextMenu.stories.tsx +220 -0
- package/src/components/dialog/Dialog.stories.tsx +157 -0
- package/src/components/dropdown-menu/DropdownMenu.stories.tsx +225 -0
- package/src/components/form/Form.stories.tsx +413 -0
- package/src/components/hover-card/HoverCard.stories.tsx +148 -0
- package/src/components/input-otp/InputOTP.stories.tsx +255 -0
- package/src/components/label/Label.stories.tsx +68 -0
- package/src/components/menubar/Menubar.stories.tsx +278 -0
- package/src/components/navigation-menu/NavigationMenu.stories.tsx +202 -0
- package/src/components/popover/Popover.stories.tsx +199 -0
- package/src/components/progress/Progress.stories.tsx +104 -0
- package/src/components/radio-group/RadioGroup.stories.tsx +138 -0
- package/src/components/scroll-area/ScrollArea.stories.tsx +153 -0
- package/src/components/select/Select.stories.tsx +146 -0
- package/src/components/separator/Separator.stories.tsx +117 -0
- package/src/components/sheet/Sheet.stories.tsx +195 -0
- package/src/components/skeleton/Skeleton.stories.tsx +114 -0
- package/src/components/slider/Slider.stories.tsx +157 -0
- package/src/components/switch/Switch.stories.tsx +114 -0
- package/src/components/table/Table.stories.tsx +153 -0
- package/src/components/tabs/Tabs.stories.tsx +155 -0
- package/src/components/textarea/Textarea.stories.tsx +116 -0
- package/src/components/toast/Toast.stories.tsx +160 -0
- package/src/components/toggle/Toggle.stories.tsx +125 -0
- package/src/components/tooltip/Tooltip.stories.tsx +133 -0
- package/src/components/typography/Typography.stories.tsx +207 -0
- package/src/components/waka-3d-pie-chart/Waka3DPieChart.stories.tsx +308 -0
- package/src/components/waka-achievement-unlock/WakaAchievementUnlock.stories.tsx +353 -0
- package/src/components/waka-artifact-list/WakaArtifactList.stories.tsx +258 -0
- package/src/components/waka-autocomplete/WakaAutocomplete.stories.tsx +224 -0
- package/src/components/waka-badge-showcase/WakaBadgeShowcase.stories.tsx +269 -0
- package/src/components/waka-barcode/WakaBarcode.stories.tsx +227 -0
- package/src/components/waka-bottom-sheet/WakaBottomSheet.stories.tsx +408 -0
- package/src/components/waka-breadcrumb/WakaBreadcrumb.stories.tsx +237 -0
- package/src/components/waka-build-matrix/WakaBuildMatrix.stories.tsx +328 -0
- package/src/components/waka-carousel/WakaCarousel.stories.tsx +296 -0
- package/src/components/waka-charts/WakaCharts.stories.tsx +519 -0
- package/src/components/waka-color-picker/WakaColorPicker.stories.tsx +200 -0
- package/src/components/waka-combobox/WakaCombobox.stories.tsx +250 -0
- package/src/components/waka-container-list/WakaContainerList.stories.tsx +315 -0
- package/src/components/waka-contribution-graph/WakaContributionGraph.stories.tsx +354 -0
- package/src/components/waka-cost-breakdown/WakaCostBreakdown.stories.tsx +348 -0
- package/src/components/waka-daily-reward/WakaDailyReward.stories.tsx +365 -0
- package/src/components/waka-database-card/WakaDatabaseCard.stories.tsx +306 -0
- package/src/components/waka-date-range-picker/WakaDateRangePicker.stories.tsx +339 -0
- package/src/components/waka-datetime-picker/WakaDateTimePicker.stories.tsx +317 -0
- package/src/components/waka-deployment-lane/WakaDeploymentLane.stories.tsx +292 -0
- package/src/components/waka-dock/WakaDock.stories.tsx +332 -0
- package/src/components/waka-drawer/WakaDrawer.stories.tsx +437 -0
- package/src/components/waka-env-var-editor/WakaEnvVarEditor.stories.tsx +263 -0
- package/src/components/waka-error-shake/WakaErrorShake.stories.tsx +410 -0
- package/src/components/waka-file-upload/WakaFileUpload.stories.tsx +239 -0
- package/src/components/waka-flow-diagram/WakaFlowDiagram.stories.tsx +365 -0
- package/src/components/waka-funnel-chart/WakaFunnelChart.stories.tsx +281 -0
- package/src/components/waka-glow-card/WakaGlowCard.stories.tsx +274 -0
- package/src/components/waka-haptic-button/WakaHapticButton.stories.tsx +349 -0
- package/src/components/waka-health-pulse/WakaHealthPulse.stories.tsx +293 -0
- package/src/components/waka-heatmap/WakaHeatmap.stories.tsx +376 -0
- package/src/components/waka-image/WakaImage.stories.tsx +255 -0
- package/src/components/waka-incident-timeline/WakaIncidentTimeline.stories.tsx +300 -0
- package/src/components/waka-kanban/WakaKanban.stories.tsx +399 -0
- package/src/components/waka-kubernetes-overview/WakaKubernetesOverview.stories.tsx +281 -0
- package/src/components/waka-leaderboard/WakaLeaderboard.stories.tsx +300 -0
- package/src/components/waka-level-progress/WakaLevelProgress.stories.tsx +313 -0
- package/src/components/waka-loading-orbit/WakaLoadingOrbit.stories.tsx +413 -0
- package/src/components/waka-log-viewer/WakaLogViewer.stories.tsx +312 -0
- package/src/components/waka-loot-box/WakaLootBox.stories.tsx +374 -0
- package/src/components/waka-metric-sparkline/WakaMetricSparkline.stories.tsx +312 -0
- package/src/components/waka-migration-list/WakaMigrationList.stories.tsx +289 -0
- package/src/components/waka-modal/WakaModal.stories.tsx +434 -0
- package/src/components/waka-morph-button/WakaMorphButton.stories.tsx +405 -0
- package/src/components/waka-network-topology/WakaNetworkTopology.stories.tsx +364 -0
- package/src/components/waka-notifications/WakaNotifications.stories.tsx +290 -0
- package/src/components/waka-number-input/WakaNumberInput.stories.tsx +282 -0
- package/src/components/waka-pagination/WakaPagination.stories.tsx +328 -0
- package/src/components/waka-password-strength/WakaPasswordStrength.stories.tsx +318 -0
- package/src/components/waka-pipeline-view/WakaPipelineView.stories.tsx +386 -0
- package/src/components/waka-player-card/WakaPlayerCard.stories.tsx +333 -0
- package/src/components/waka-pod-card/WakaPodCard.stories.tsx +435 -0
- package/src/components/waka-qrcode/WakaQRCode.stories.tsx +232 -0
- package/src/components/waka-query-explain/WakaQueryExplain.stories.tsx +407 -0
- package/src/components/waka-quest-card/WakaQuestCard.stories.tsx +394 -0
- package/src/components/waka-quota-bar/WakaQuotaBar.stories.tsx +435 -0
- package/src/components/waka-radar-score/WakaRadarScore.stories.tsx +372 -0
- package/src/components/waka-resource-gauge/WakaResourceGauge.stories.tsx +366 -0
- package/src/components/waka-rich-text-editor/WakaRichTextEditor.stories.tsx +238 -0
- package/src/components/waka-sankey-diagram/WakaSankeyDiagram.stories.tsx +389 -0
- package/src/components/waka-scratch-card/WakaScratchCard.stories.tsx +388 -0
- package/src/components/waka-secret-card/WakaSecretCard.stories.tsx +314 -0
- package/src/components/waka-segmented-control/WakaSegmentedControl.stories.tsx +309 -0
- package/src/components/waka-server-rack/WakaServerRack.stories.tsx +382 -0
- package/src/components/waka-service-graph/WakaServiceGraph.stories.tsx +262 -0
- package/src/components/waka-skeleton-wave/WakaSkeletonWave.stories.tsx +321 -0
- package/src/components/waka-skill-tree/WakaSkillTree.stories.tsx +308 -0
- package/src/components/waka-spin-wheel/WakaSpinWheel.stories.tsx +368 -0
- package/src/components/waka-spinner/WakaSpinner.stories.tsx +156 -0
- package/src/components/waka-stat/WakaStat.stories.tsx +334 -0
- package/src/components/waka-status-matrix/WakaStatusMatrix.stories.tsx +331 -0
- package/src/components/waka-stepper/WakaStepper.stories.tsx +468 -0
- package/src/components/waka-streak-counter/WakaStreakCounter.stories.tsx +235 -0
- package/src/components/waka-success-explosion/WakaSuccessExplosion.stories.tsx +389 -0
- package/src/components/waka-tabs-morph/WakaTabsMorph.stories.tsx +471 -0
- package/src/components/waka-terminal-output/WakaTerminalOutput.stories.tsx +351 -0
- package/src/components/waka-test-report/WakaTestReport.stories.tsx +322 -0
- package/src/components/waka-tilt-card/WakaTiltCard.stories.tsx +300 -0
- package/src/components/waka-time-picker/WakaTimePicker.stories.tsx +227 -0
- package/src/components/waka-timeline/WakaTimeline.stories.tsx +383 -0
- package/src/components/waka-tournament-bracket/WakaTournamentBracket.stories.tsx +375 -0
- package/src/components/waka-trace-viewer/WakaTraceViewer.stories.tsx +445 -0
- package/src/components/waka-tree/WakaTree.stories.tsx +359 -0
- package/src/components/waka-treemap-chart/WakaTreemapChart.stories.tsx +378 -0
- package/src/components/waka-typewriter/WakaTypewriter.stories.tsx +366 -0
- package/src/components/waka-versus-card/WakaVersusCard.stories.tsx +530 -0
- package/src/components/waka-video/WakaVideo.stories.tsx +203 -0
- package/src/components/waka-virtual-list/WakaVirtualList.stories.tsx +273 -0
- package/src/components/waka-xp-bar/WakaXPBar.stories.tsx +305 -0
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { WakaDashboard, defaultDashboardStats } from './index'
|
|
3
|
+
import type { DashboardStatConfig, DashboardChartConfig, DashboardTableConfig, DashboardActivityItem, DashboardQuickAction } from './index'
|
|
4
|
+
import * as React from 'react'
|
|
5
|
+
import { Plus, Download, Users, DollarSign, ShoppingCart, Activity } from 'lucide-react'
|
|
6
|
+
|
|
7
|
+
const MockLink = ({ href, children, ...props }: any) => (
|
|
8
|
+
<a href={href} {...props} onClick={(e) => e.preventDefault()}>
|
|
9
|
+
{children}
|
|
10
|
+
</a>
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
const meta: Meta<typeof WakaDashboard> = {
|
|
14
|
+
title: 'Blocks/Dashboard',
|
|
15
|
+
component: WakaDashboard,
|
|
16
|
+
parameters: {
|
|
17
|
+
layout: 'fullscreen',
|
|
18
|
+
docs: {
|
|
19
|
+
description: {
|
|
20
|
+
component:
|
|
21
|
+
'A comprehensive dashboard component with stats, charts, tables, activity feed, and quick actions. Supports period filtering and refresh.',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
tags: ['autodocs'],
|
|
26
|
+
argTypes: {
|
|
27
|
+
statsLayout: {
|
|
28
|
+
control: 'select',
|
|
29
|
+
options: ['row', 'grid'],
|
|
30
|
+
},
|
|
31
|
+
statsColumns: {
|
|
32
|
+
control: 'select',
|
|
33
|
+
options: [2, 3, 4],
|
|
34
|
+
},
|
|
35
|
+
showHeader: {
|
|
36
|
+
control: 'boolean',
|
|
37
|
+
},
|
|
38
|
+
loading: {
|
|
39
|
+
control: 'boolean',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default meta
|
|
45
|
+
type Story = StoryObj<typeof WakaDashboard>
|
|
46
|
+
|
|
47
|
+
// Mock chart component
|
|
48
|
+
const MockChart = ({ height = 200, title }: { height?: number; title: string }) => (
|
|
49
|
+
<div
|
|
50
|
+
className="bg-muted/30 rounded-lg flex items-center justify-center"
|
|
51
|
+
style={{ height }}
|
|
52
|
+
>
|
|
53
|
+
<span className="text-muted-foreground text-sm">{title}</span>
|
|
54
|
+
</div>
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
// Mock table component
|
|
58
|
+
const MockTable = () => (
|
|
59
|
+
<div className="space-y-2">
|
|
60
|
+
{[1, 2, 3, 4, 5].map((i) => (
|
|
61
|
+
<div key={i} className="flex justify-between py-2 border-b last:border-0">
|
|
62
|
+
<span className="text-sm">Item {i}</span>
|
|
63
|
+
<span className="text-sm text-muted-foreground">Value {i * 100}</span>
|
|
64
|
+
</div>
|
|
65
|
+
))}
|
|
66
|
+
</div>
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
export const Default: Story = {
|
|
70
|
+
render: () => (
|
|
71
|
+
<div className="p-6">
|
|
72
|
+
<WakaDashboard
|
|
73
|
+
title="Tableau de bord"
|
|
74
|
+
description="Vue d'ensemble de votre activité"
|
|
75
|
+
stats={defaultDashboardStats}
|
|
76
|
+
period="month"
|
|
77
|
+
onPeriodChange={(period) => console.log('Period:', period)}
|
|
78
|
+
onRefresh={() => console.log('Refresh')}
|
|
79
|
+
LinkComponent={MockLink}
|
|
80
|
+
/>
|
|
81
|
+
</div>
|
|
82
|
+
),
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const WithCharts: Story = {
|
|
86
|
+
render: () => {
|
|
87
|
+
const charts: DashboardChartConfig[] = [
|
|
88
|
+
{
|
|
89
|
+
id: 'revenue-chart',
|
|
90
|
+
title: 'Revenus',
|
|
91
|
+
description: 'Évolution des revenus sur la période',
|
|
92
|
+
chart: <MockChart title="Line Chart - Revenus" />,
|
|
93
|
+
actions: [
|
|
94
|
+
{ label: 'Exporter', onClick: () => console.log('Export') },
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: 'users-chart',
|
|
99
|
+
title: 'Utilisateurs',
|
|
100
|
+
description: 'Nouveaux utilisateurs par jour',
|
|
101
|
+
chart: <MockChart title="Bar Chart - Utilisateurs" />,
|
|
102
|
+
actions: [
|
|
103
|
+
{ label: 'Voir détails', onClick: () => console.log('Details') },
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<div className="p-6">
|
|
110
|
+
<WakaDashboard
|
|
111
|
+
title="Dashboard avec graphiques"
|
|
112
|
+
stats={defaultDashboardStats}
|
|
113
|
+
charts={charts}
|
|
114
|
+
period="month"
|
|
115
|
+
onPeriodChange={(period) => console.log('Period:', period)}
|
|
116
|
+
LinkComponent={MockLink}
|
|
117
|
+
/>
|
|
118
|
+
</div>
|
|
119
|
+
)
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const WithTables: Story = {
|
|
124
|
+
render: () => {
|
|
125
|
+
const tables: DashboardTableConfig[] = [
|
|
126
|
+
{
|
|
127
|
+
id: 'recent-orders',
|
|
128
|
+
title: 'Commandes récentes',
|
|
129
|
+
description: 'Les 5 dernières commandes',
|
|
130
|
+
table: <MockTable />,
|
|
131
|
+
actions: [
|
|
132
|
+
{ label: 'Voir tout', href: '/orders' },
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<div className="p-6">
|
|
139
|
+
<WakaDashboard
|
|
140
|
+
title="Dashboard avec tableau"
|
|
141
|
+
stats={defaultDashboardStats}
|
|
142
|
+
tables={tables}
|
|
143
|
+
period="month"
|
|
144
|
+
onPeriodChange={(period) => console.log('Period:', period)}
|
|
145
|
+
LinkComponent={MockLink}
|
|
146
|
+
/>
|
|
147
|
+
</div>
|
|
148
|
+
)
|
|
149
|
+
},
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export const WithActivity: Story = {
|
|
153
|
+
render: () => {
|
|
154
|
+
const activities: DashboardActivityItem[] = [
|
|
155
|
+
{
|
|
156
|
+
id: '1',
|
|
157
|
+
title: 'Nouvelle commande #1234',
|
|
158
|
+
description: 'Jean Dupont a passé une commande de €150',
|
|
159
|
+
timestamp: new Date(Date.now() - 1000 * 60 * 5),
|
|
160
|
+
type: 'success',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
id: '2',
|
|
164
|
+
title: 'Nouvel utilisateur',
|
|
165
|
+
description: 'Marie Martin s\'est inscrite',
|
|
166
|
+
timestamp: new Date(Date.now() - 1000 * 60 * 30),
|
|
167
|
+
type: 'info',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: '3',
|
|
171
|
+
title: 'Paiement échoué',
|
|
172
|
+
description: 'Le paiement de la commande #1233 a échoué',
|
|
173
|
+
timestamp: new Date(Date.now() - 1000 * 60 * 60 * 2),
|
|
174
|
+
type: 'error',
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: '4',
|
|
178
|
+
title: 'Stock faible',
|
|
179
|
+
description: 'Le produit "Widget Pro" est presque en rupture',
|
|
180
|
+
timestamp: new Date(Date.now() - 1000 * 60 * 60 * 5),
|
|
181
|
+
type: 'warning',
|
|
182
|
+
},
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
return (
|
|
186
|
+
<div className="p-6">
|
|
187
|
+
<WakaDashboard
|
|
188
|
+
title="Dashboard avec activité"
|
|
189
|
+
stats={defaultDashboardStats}
|
|
190
|
+
activities={activities}
|
|
191
|
+
period="month"
|
|
192
|
+
onPeriodChange={(period) => console.log('Period:', period)}
|
|
193
|
+
LinkComponent={MockLink}
|
|
194
|
+
/>
|
|
195
|
+
</div>
|
|
196
|
+
)
|
|
197
|
+
},
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export const WithQuickActions: Story = {
|
|
201
|
+
render: () => {
|
|
202
|
+
const quickActions: DashboardQuickAction[] = [
|
|
203
|
+
{
|
|
204
|
+
id: 'add-product',
|
|
205
|
+
label: 'Ajouter produit',
|
|
206
|
+
icon: <Plus className="h-4 w-4" />,
|
|
207
|
+
onClick: () => console.log('Add product'),
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
id: 'export',
|
|
211
|
+
label: 'Exporter',
|
|
212
|
+
icon: <Download className="h-4 w-4" />,
|
|
213
|
+
variant: 'outline',
|
|
214
|
+
onClick: () => console.log('Export'),
|
|
215
|
+
},
|
|
216
|
+
]
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<div className="p-6">
|
|
220
|
+
<WakaDashboard
|
|
221
|
+
title="Dashboard avec actions rapides"
|
|
222
|
+
stats={defaultDashboardStats}
|
|
223
|
+
quickActions={quickActions}
|
|
224
|
+
period="month"
|
|
225
|
+
onPeriodChange={(period) => console.log('Period:', period)}
|
|
226
|
+
onRefresh={() => console.log('Refresh')}
|
|
227
|
+
LinkComponent={MockLink}
|
|
228
|
+
/>
|
|
229
|
+
</div>
|
|
230
|
+
)
|
|
231
|
+
},
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export const Complete: Story = {
|
|
235
|
+
render: () => {
|
|
236
|
+
const charts: DashboardChartConfig[] = [
|
|
237
|
+
{
|
|
238
|
+
id: 'revenue-chart',
|
|
239
|
+
title: 'Revenus',
|
|
240
|
+
description: 'Évolution des revenus',
|
|
241
|
+
chart: <MockChart title="Line Chart" height={250} />,
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
id: 'orders-chart',
|
|
245
|
+
title: 'Commandes',
|
|
246
|
+
description: 'Commandes par catégorie',
|
|
247
|
+
chart: <MockChart title="Pie Chart" height={250} />,
|
|
248
|
+
},
|
|
249
|
+
]
|
|
250
|
+
|
|
251
|
+
const tables: DashboardTableConfig[] = [
|
|
252
|
+
{
|
|
253
|
+
id: 'top-products',
|
|
254
|
+
title: 'Produits populaires',
|
|
255
|
+
description: 'Les plus vendus ce mois',
|
|
256
|
+
table: <MockTable />,
|
|
257
|
+
actions: [{ label: 'Voir tout', href: '/products' }],
|
|
258
|
+
},
|
|
259
|
+
]
|
|
260
|
+
|
|
261
|
+
const activities: DashboardActivityItem[] = [
|
|
262
|
+
{
|
|
263
|
+
id: '1',
|
|
264
|
+
title: 'Commande #1234 expédiée',
|
|
265
|
+
timestamp: new Date(Date.now() - 1000 * 60 * 10),
|
|
266
|
+
type: 'success',
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
id: '2',
|
|
270
|
+
title: 'Nouveau client enregistré',
|
|
271
|
+
timestamp: new Date(Date.now() - 1000 * 60 * 45),
|
|
272
|
+
type: 'info',
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
id: '3',
|
|
276
|
+
title: 'Stock mis à jour',
|
|
277
|
+
timestamp: new Date(Date.now() - 1000 * 60 * 120),
|
|
278
|
+
type: 'info',
|
|
279
|
+
},
|
|
280
|
+
]
|
|
281
|
+
|
|
282
|
+
const quickActions: DashboardQuickAction[] = [
|
|
283
|
+
{
|
|
284
|
+
id: 'new-order',
|
|
285
|
+
label: 'Nouvelle commande',
|
|
286
|
+
icon: <Plus className="h-4 w-4" />,
|
|
287
|
+
href: '/orders/new',
|
|
288
|
+
},
|
|
289
|
+
]
|
|
290
|
+
|
|
291
|
+
return (
|
|
292
|
+
<div className="p-6">
|
|
293
|
+
<WakaDashboard
|
|
294
|
+
title="Dashboard complet"
|
|
295
|
+
description="Vue d'ensemble de votre activité commerciale"
|
|
296
|
+
stats={defaultDashboardStats}
|
|
297
|
+
charts={charts}
|
|
298
|
+
tables={tables}
|
|
299
|
+
activities={activities}
|
|
300
|
+
quickActions={quickActions}
|
|
301
|
+
period="month"
|
|
302
|
+
onPeriodChange={(period) => console.log('Period:', period)}
|
|
303
|
+
onRefresh={() => console.log('Refresh')}
|
|
304
|
+
LinkComponent={MockLink}
|
|
305
|
+
/>
|
|
306
|
+
</div>
|
|
307
|
+
)
|
|
308
|
+
},
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export const StatsOnly: Story = {
|
|
312
|
+
render: () => (
|
|
313
|
+
<div className="p-6">
|
|
314
|
+
<WakaDashboard
|
|
315
|
+
title="Statistiques"
|
|
316
|
+
stats={defaultDashboardStats}
|
|
317
|
+
showHeader
|
|
318
|
+
LinkComponent={MockLink}
|
|
319
|
+
/>
|
|
320
|
+
</div>
|
|
321
|
+
),
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export const GridStats: Story = {
|
|
325
|
+
render: () => (
|
|
326
|
+
<div className="p-6">
|
|
327
|
+
<WakaDashboard
|
|
328
|
+
title="Stats en grille"
|
|
329
|
+
stats={defaultDashboardStats}
|
|
330
|
+
statsLayout="grid"
|
|
331
|
+
statsColumns={4}
|
|
332
|
+
LinkComponent={MockLink}
|
|
333
|
+
/>
|
|
334
|
+
</div>
|
|
335
|
+
),
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export const TwoColumnStats: Story = {
|
|
339
|
+
render: () => (
|
|
340
|
+
<div className="p-6">
|
|
341
|
+
<WakaDashboard
|
|
342
|
+
title="Stats 2 colonnes"
|
|
343
|
+
stats={defaultDashboardStats.slice(0, 2)}
|
|
344
|
+
statsLayout="grid"
|
|
345
|
+
statsColumns={2}
|
|
346
|
+
LinkComponent={MockLink}
|
|
347
|
+
/>
|
|
348
|
+
</div>
|
|
349
|
+
),
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export const Loading: Story = {
|
|
353
|
+
render: () => (
|
|
354
|
+
<div className="p-6">
|
|
355
|
+
<WakaDashboard
|
|
356
|
+
title="Chargement..."
|
|
357
|
+
stats={defaultDashboardStats}
|
|
358
|
+
loading
|
|
359
|
+
period="month"
|
|
360
|
+
onPeriodChange={(period) => console.log('Period:', period)}
|
|
361
|
+
onRefresh={() => console.log('Refresh')}
|
|
362
|
+
LinkComponent={MockLink}
|
|
363
|
+
/>
|
|
364
|
+
</div>
|
|
365
|
+
),
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export const NoHeader: Story = {
|
|
369
|
+
render: () => (
|
|
370
|
+
<div className="p-6">
|
|
371
|
+
<WakaDashboard
|
|
372
|
+
stats={defaultDashboardStats}
|
|
373
|
+
showHeader={false}
|
|
374
|
+
LinkComponent={MockLink}
|
|
375
|
+
/>
|
|
376
|
+
</div>
|
|
377
|
+
),
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export const CustomStats: Story = {
|
|
381
|
+
render: () => {
|
|
382
|
+
const customStats: DashboardStatConfig[] = [
|
|
383
|
+
{
|
|
384
|
+
id: 'visitors',
|
|
385
|
+
label: 'Visiteurs',
|
|
386
|
+
value: '12,345',
|
|
387
|
+
trend: 'up',
|
|
388
|
+
trendValue: '+15%',
|
|
389
|
+
trendText: 'vs semaine dernière',
|
|
390
|
+
icon: <Users className="h-5 w-5" />,
|
|
391
|
+
color: 'blue',
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
id: 'revenue',
|
|
395
|
+
label: 'Revenus',
|
|
396
|
+
value: '€89,432',
|
|
397
|
+
trend: 'up',
|
|
398
|
+
trendValue: '+8.2%',
|
|
399
|
+
icon: <DollarSign className="h-5 w-5" />,
|
|
400
|
+
color: 'success',
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
id: 'orders',
|
|
404
|
+
label: 'Commandes',
|
|
405
|
+
value: '432',
|
|
406
|
+
trend: 'down',
|
|
407
|
+
trendValue: '-3%',
|
|
408
|
+
icon: <ShoppingCart className="h-5 w-5" />,
|
|
409
|
+
color: 'warning',
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
id: 'conversion',
|
|
413
|
+
label: 'Taux de conversion',
|
|
414
|
+
value: '3.5%',
|
|
415
|
+
trend: 'neutral',
|
|
416
|
+
icon: <Activity className="h-5 w-5" />,
|
|
417
|
+
color: 'purple',
|
|
418
|
+
},
|
|
419
|
+
]
|
|
420
|
+
|
|
421
|
+
return (
|
|
422
|
+
<div className="p-6">
|
|
423
|
+
<WakaDashboard
|
|
424
|
+
title="Dashboard personnalisé"
|
|
425
|
+
stats={customStats}
|
|
426
|
+
period="week"
|
|
427
|
+
onPeriodChange={(period) => console.log('Period:', period)}
|
|
428
|
+
LinkComponent={MockLink}
|
|
429
|
+
/>
|
|
430
|
+
</div>
|
|
431
|
+
)
|
|
432
|
+
},
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export const Interactive: Story = {
|
|
436
|
+
render: () => {
|
|
437
|
+
const [period, setPeriod] = React.useState('month')
|
|
438
|
+
const [loading, setLoading] = React.useState(false)
|
|
439
|
+
|
|
440
|
+
const handleRefresh = () => {
|
|
441
|
+
setLoading(true)
|
|
442
|
+
setTimeout(() => setLoading(false), 1500)
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return (
|
|
446
|
+
<div className="p-6">
|
|
447
|
+
<WakaDashboard
|
|
448
|
+
title="Dashboard interactif"
|
|
449
|
+
description={`Période sélectionnée: ${period}`}
|
|
450
|
+
stats={defaultDashboardStats}
|
|
451
|
+
period={period}
|
|
452
|
+
onPeriodChange={setPeriod}
|
|
453
|
+
onRefresh={handleRefresh}
|
|
454
|
+
loading={loading}
|
|
455
|
+
LinkComponent={MockLink}
|
|
456
|
+
/>
|
|
457
|
+
</div>
|
|
458
|
+
)
|
|
459
|
+
},
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
export const EcommerceDashboard: Story = {
|
|
463
|
+
render: () => {
|
|
464
|
+
const ecommerceStats: DashboardStatConfig[] = [
|
|
465
|
+
{
|
|
466
|
+
id: 'sales',
|
|
467
|
+
label: 'Ventes du jour',
|
|
468
|
+
value: '€3,421',
|
|
469
|
+
trend: 'up',
|
|
470
|
+
trendValue: '+12%',
|
|
471
|
+
icon: <DollarSign className="h-5 w-5" />,
|
|
472
|
+
color: 'success',
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
id: 'orders',
|
|
476
|
+
label: 'Commandes',
|
|
477
|
+
value: '48',
|
|
478
|
+
trend: 'up',
|
|
479
|
+
trendValue: '+5',
|
|
480
|
+
icon: <ShoppingCart className="h-5 w-5" />,
|
|
481
|
+
color: 'blue',
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
id: 'customers',
|
|
485
|
+
label: 'Nouveaux clients',
|
|
486
|
+
value: '12',
|
|
487
|
+
trend: 'down',
|
|
488
|
+
trendValue: '-2',
|
|
489
|
+
icon: <Users className="h-5 w-5" />,
|
|
490
|
+
color: 'purple',
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
id: 'aov',
|
|
494
|
+
label: 'Panier moyen',
|
|
495
|
+
value: '€71.27',
|
|
496
|
+
trend: 'up',
|
|
497
|
+
trendValue: '+€5.30',
|
|
498
|
+
icon: <Activity className="h-5 w-5" />,
|
|
499
|
+
color: 'primary',
|
|
500
|
+
},
|
|
501
|
+
]
|
|
502
|
+
|
|
503
|
+
const charts: DashboardChartConfig[] = [
|
|
504
|
+
{
|
|
505
|
+
id: 'sales-chart',
|
|
506
|
+
title: 'Ventes',
|
|
507
|
+
description: 'Ventes des 7 derniers jours',
|
|
508
|
+
chart: <MockChart title="Sales Chart" height={300} />,
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
id: 'categories',
|
|
512
|
+
title: 'Par catégorie',
|
|
513
|
+
description: 'Répartition des ventes',
|
|
514
|
+
chart: <MockChart title="Category Pie Chart" height={300} />,
|
|
515
|
+
},
|
|
516
|
+
]
|
|
517
|
+
|
|
518
|
+
return (
|
|
519
|
+
<div className="min-h-screen bg-muted/30">
|
|
520
|
+
<header className="bg-background border-b px-6 py-4">
|
|
521
|
+
<div className="flex items-center justify-between">
|
|
522
|
+
<span className="font-bold text-xl">MyShop Admin</span>
|
|
523
|
+
<nav className="flex gap-4 text-sm">
|
|
524
|
+
<a href="#" className="text-foreground font-medium">Dashboard</a>
|
|
525
|
+
<a href="#" className="text-muted-foreground hover:text-foreground">Produits</a>
|
|
526
|
+
<a href="#" className="text-muted-foreground hover:text-foreground">Commandes</a>
|
|
527
|
+
<a href="#" className="text-muted-foreground hover:text-foreground">Clients</a>
|
|
528
|
+
</nav>
|
|
529
|
+
</div>
|
|
530
|
+
</header>
|
|
531
|
+
<main className="p-6">
|
|
532
|
+
<WakaDashboard
|
|
533
|
+
title="Tableau de bord"
|
|
534
|
+
description="Bienvenue ! Voici un aperçu de votre boutique."
|
|
535
|
+
stats={ecommerceStats}
|
|
536
|
+
charts={charts}
|
|
537
|
+
period="today"
|
|
538
|
+
periods={[
|
|
539
|
+
{ value: 'today', label: "Aujourd'hui" },
|
|
540
|
+
{ value: 'week', label: 'Cette semaine' },
|
|
541
|
+
{ value: 'month', label: 'Ce mois' },
|
|
542
|
+
]}
|
|
543
|
+
onPeriodChange={(period) => console.log('Period:', period)}
|
|
544
|
+
onRefresh={() => console.log('Refresh')}
|
|
545
|
+
quickActions={[
|
|
546
|
+
{
|
|
547
|
+
id: 'add-product',
|
|
548
|
+
label: 'Ajouter produit',
|
|
549
|
+
icon: <Plus className="h-4 w-4" />,
|
|
550
|
+
href: '/products/new',
|
|
551
|
+
},
|
|
552
|
+
]}
|
|
553
|
+
LinkComponent={MockLink}
|
|
554
|
+
/>
|
|
555
|
+
</main>
|
|
556
|
+
</div>
|
|
557
|
+
)
|
|
558
|
+
},
|
|
559
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react"
|
|
4
4
|
import { cn } from "../../utils"
|
|
5
|
+
import type { LinkComponentProps } from "../../types/link"
|
|
5
6
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../../components/card"
|
|
6
7
|
import { Button } from "../../components/button"
|
|
7
8
|
import { Badge } from "../../components/badge"
|
|
@@ -119,6 +120,22 @@ export interface WakaDashboardProps {
|
|
|
119
120
|
statsColumns?: 2 | 3 | 4
|
|
120
121
|
/** Classes CSS additionnelles */
|
|
121
122
|
className?: string
|
|
123
|
+
/** Composant de lien personnalisé (ex: next/link) pour navigation SPA */
|
|
124
|
+
LinkComponent?: React.ComponentType<LinkComponentProps>
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ============================================
|
|
128
|
+
// CONTEXT
|
|
129
|
+
// ============================================
|
|
130
|
+
|
|
131
|
+
interface DashboardContextValue {
|
|
132
|
+
LinkComponent?: React.ComponentType<LinkComponentProps>
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const DashboardContext = React.createContext<DashboardContextValue>({})
|
|
136
|
+
|
|
137
|
+
function useDashboardContext() {
|
|
138
|
+
return React.useContext(DashboardContext)
|
|
122
139
|
}
|
|
123
140
|
|
|
124
141
|
// ============================================
|
|
@@ -196,27 +213,37 @@ function DashboardHeader({
|
|
|
196
213
|
)}
|
|
197
214
|
|
|
198
215
|
{/* Actions rapides */}
|
|
199
|
-
{quickActions?.map((action) =>
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
216
|
+
{quickActions?.map((action) => {
|
|
217
|
+
const { LinkComponent } = useDashboardContext()
|
|
218
|
+
return (
|
|
219
|
+
<Button
|
|
220
|
+
key={action.id}
|
|
221
|
+
variant={action.variant || "default"}
|
|
222
|
+
size="sm"
|
|
223
|
+
onClick={action.onClick}
|
|
224
|
+
asChild={!!action.href}
|
|
225
|
+
>
|
|
226
|
+
{action.href ? (
|
|
227
|
+
LinkComponent ? (
|
|
228
|
+
<LinkComponent href={action.href}>
|
|
229
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
230
|
+
{action.label}
|
|
231
|
+
</LinkComponent>
|
|
232
|
+
) : (
|
|
233
|
+
<a href={action.href}>
|
|
234
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
235
|
+
{action.label}
|
|
236
|
+
</a>
|
|
237
|
+
)
|
|
238
|
+
) : (
|
|
239
|
+
<>
|
|
240
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
241
|
+
{action.label}
|
|
242
|
+
</>
|
|
243
|
+
)}
|
|
244
|
+
</Button>
|
|
245
|
+
)
|
|
246
|
+
})}
|
|
220
247
|
</div>
|
|
221
248
|
</div>
|
|
222
249
|
)
|
|
@@ -296,6 +323,8 @@ interface DashboardTableCardProps {
|
|
|
296
323
|
}
|
|
297
324
|
|
|
298
325
|
function DashboardTableCard({ config }: DashboardTableCardProps) {
|
|
326
|
+
const { LinkComponent } = useDashboardContext()
|
|
327
|
+
|
|
299
328
|
return (
|
|
300
329
|
<Card>
|
|
301
330
|
<CardHeader className="flex flex-row items-center justify-between pb-2">
|
|
@@ -316,10 +345,17 @@ function DashboardTableCard({ config }: DashboardTableCardProps) {
|
|
|
316
345
|
asChild={!!action.href}
|
|
317
346
|
>
|
|
318
347
|
{action.href ? (
|
|
319
|
-
|
|
320
|
-
{action.
|
|
321
|
-
|
|
322
|
-
|
|
348
|
+
LinkComponent ? (
|
|
349
|
+
<LinkComponent href={action.href}>
|
|
350
|
+
{action.label}
|
|
351
|
+
<ArrowUpRight className="ml-1 h-3 w-3" />
|
|
352
|
+
</LinkComponent>
|
|
353
|
+
) : (
|
|
354
|
+
<a href={action.href}>
|
|
355
|
+
{action.label}
|
|
356
|
+
<ArrowUpRight className="ml-1 h-3 w-3" />
|
|
357
|
+
</a>
|
|
358
|
+
)
|
|
323
359
|
) : (
|
|
324
360
|
action.label
|
|
325
361
|
)}
|
|
@@ -415,9 +451,13 @@ export function WakaDashboard({
|
|
|
415
451
|
statsLayout = "grid",
|
|
416
452
|
statsColumns = 4,
|
|
417
453
|
className,
|
|
454
|
+
LinkComponent,
|
|
418
455
|
}: WakaDashboardProps) {
|
|
456
|
+
const contextValue = React.useMemo(() => ({ LinkComponent }), [LinkComponent])
|
|
457
|
+
|
|
419
458
|
return (
|
|
420
|
-
<
|
|
459
|
+
<DashboardContext.Provider value={contextValue}>
|
|
460
|
+
<div className={cn("space-y-6", className)}>
|
|
421
461
|
{/* Header */}
|
|
422
462
|
{showHeader && (
|
|
423
463
|
<DashboardHeader
|
|
@@ -469,7 +509,8 @@ export function WakaDashboard({
|
|
|
469
509
|
</div>
|
|
470
510
|
)}
|
|
471
511
|
</div>
|
|
472
|
-
|
|
512
|
+
</div>
|
|
513
|
+
</DashboardContext.Provider>
|
|
473
514
|
)
|
|
474
515
|
}
|
|
475
516
|
|