@wakastellar/ui 2.4.0 → 3.1.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 (173) hide show
  1. package/dist/blocks/antivirus-dashboard/index.d.ts +44 -0
  2. package/dist/blocks/clamav-service-status/index.d.ts +35 -0
  3. package/dist/blocks/file-scan-uploader/index.d.ts +29 -0
  4. package/dist/blocks/index.d.ts +18 -9
  5. package/dist/blocks/quarantine-manager/index.d.ts +27 -0
  6. package/dist/blocks/scan-history-log/index.d.ts +28 -0
  7. package/dist/blocks/scan-policy-editor/index.d.ts +27 -0
  8. package/dist/blocks/scan-report-generator/index.d.ts +47 -0
  9. package/dist/blocks/signature-database-manager/index.d.ts +39 -0
  10. package/dist/blocks/threat-alert-banner/index.d.ts +26 -0
  11. package/dist/components/index.d.ts +4 -4
  12. package/dist/components/waka-signature-pad/index.d.ts +1 -1
  13. package/dist/exceljs.min-BcLLX0PC.js +29 -0
  14. package/dist/exceljs.min-KOayaaQ4.mjs +23013 -0
  15. package/dist/export.cjs.js +1 -1
  16. package/dist/export.d.ts +2 -2
  17. package/dist/export.es.js +1 -1
  18. package/dist/index.cjs.js +136 -136
  19. package/dist/index.es.js +29978 -27215
  20. package/dist/stories/Button.stories.d.ts +1 -1
  21. package/dist/stories/Header.stories.d.ts +1 -1
  22. package/dist/stories/Page.stories.d.ts +1 -1
  23. package/dist/useDataTableImport-COVnvslz.js +9 -0
  24. package/dist/useDataTableImport-DAlxBY8w.mjs +237 -0
  25. package/dist/utils/index.d.ts +1 -0
  26. package/dist/utils/logger.d.ts +9 -0
  27. package/package.json +6 -5
  28. package/src/blocks/antivirus-dashboard/AntivirusDashboard.stories.tsx +291 -0
  29. package/src/blocks/antivirus-dashboard/index.tsx +525 -0
  30. package/src/blocks/clamav-service-status/ClamAVServiceStatus.stories.tsx +195 -0
  31. package/src/blocks/clamav-service-status/index.tsx +370 -0
  32. package/src/blocks/file-scan-uploader/FileScanUploader.stories.tsx +257 -0
  33. package/src/blocks/file-scan-uploader/index.tsx +311 -0
  34. package/src/blocks/index.ts +163 -11
  35. package/src/blocks/quarantine-manager/QuarantineManager.stories.tsx +209 -0
  36. package/src/blocks/quarantine-manager/index.tsx +435 -0
  37. package/src/blocks/scan-history-log/ScanHistoryLog.stories.tsx +231 -0
  38. package/src/blocks/scan-history-log/index.tsx +406 -0
  39. package/src/blocks/scan-policy-editor/ScanPolicyEditor.stories.tsx +106 -0
  40. package/src/blocks/scan-policy-editor/index.tsx +418 -0
  41. package/src/blocks/scan-report-generator/ScanReportGenerator.stories.tsx +232 -0
  42. package/src/blocks/scan-report-generator/index.tsx +612 -0
  43. package/src/blocks/sidebar/index.tsx +2 -1
  44. package/src/blocks/signature-database-manager/SignatureDatabaseManager.stories.tsx +279 -0
  45. package/src/blocks/signature-database-manager/index.tsx +470 -0
  46. package/src/blocks/theme-creator-block/index.tsx +16 -2
  47. package/src/blocks/threat-alert-banner/ThreatAlertBanner.stories.tsx +152 -0
  48. package/src/blocks/threat-alert-banner/index.tsx +320 -0
  49. package/src/components/DataTable/DataTable.stories.tsx +203 -0
  50. package/src/components/DataTable/hooks/useDataTableExport.ts +38 -31
  51. package/src/components/DataTable/hooks/useDataTableImport.ts +31 -20
  52. package/src/components/error-boundary/ErrorBoundary.stories.tsx +125 -0
  53. package/src/components/index.ts +45 -4
  54. package/src/components/language-selector/LanguageSelector.stories.tsx +112 -0
  55. package/src/components/theme-selector/ThemeSelector.stories.tsx +77 -0
  56. package/src/components/toaster/Toaster.stories.tsx +67 -0
  57. package/src/components/waka-activity-feed/WakaActivityFeed.stories.tsx +116 -0
  58. package/src/components/waka-ad-banner/WakaAdBanner.stories.tsx +102 -0
  59. package/src/components/waka-ad-fallback/WakaAdFallback.stories.tsx +117 -0
  60. package/src/components/waka-ad-inline/WakaAdInline.stories.tsx +105 -0
  61. package/src/components/waka-ad-interstitial/WakaAdInterstitial.stories.tsx +92 -0
  62. package/src/components/waka-ad-placeholder/WakaAdPlaceholder.stories.tsx +89 -0
  63. package/src/components/waka-ad-provider/WakaAdProvider.stories.tsx +110 -0
  64. package/src/components/waka-ad-sidebar/WakaAdSidebar.stories.tsx +89 -0
  65. package/src/components/waka-ad-sidebar/index.tsx +3 -2
  66. package/src/components/waka-ad-sticky-footer/WakaAdStickyFooter.stories.tsx +88 -0
  67. package/src/components/waka-address-autocomplete/WakaAddressAutocomplete.stories.tsx +46 -0
  68. package/src/components/waka-admincrumb/WakaAdmincrumb.stories.tsx +166 -0
  69. package/src/components/waka-alert-panel/WakaAlertPanel.stories.tsx +45 -0
  70. package/src/components/waka-alert-stack/WakaAlertStack.stories.tsx +62 -0
  71. package/src/components/waka-allocation-matrix/WakaAllocationMatrix.stories.tsx +68 -0
  72. package/src/components/waka-approval-chain/WakaApprovalChain.stories.tsx +63 -0
  73. package/src/components/waka-audit-log/WakaAuditLog.stories.tsx +73 -0
  74. package/src/components/waka-autocomplete/WakaAutocomplete.stories.tsx +132 -172
  75. package/src/components/waka-biometric-prompt/WakaBiometricPrompt.stories.tsx +48 -0
  76. package/src/components/waka-breadcrumb/WakaBreadcrumb.stories.tsx +74 -191
  77. package/src/components/waka-breadcrumb-path/WakaBreadcrumbPath.stories.tsx +40 -0
  78. package/src/components/waka-budget-burn/WakaBudgetBurn.stories.tsx +86 -0
  79. package/src/components/waka-capacity-planner/WakaCapacityPlanner.stories.tsx +273 -0
  80. package/src/components/waka-cart-summary/WakaCartSummary.stories.tsx +176 -0
  81. package/src/components/waka-cart-summary/index.tsx +19 -10
  82. package/src/components/waka-challenge-timer/WakaChallengeTimer.stories.tsx +98 -0
  83. package/src/components/waka-chat-bubble/WakaChatBubble.stories.tsx +118 -0
  84. package/src/components/waka-checklist/WakaChecklist.stories.tsx +71 -0
  85. package/src/components/waka-checkout-stepper/WakaCheckoutStepper.stories.tsx +102 -0
  86. package/src/components/waka-cohort-table/WakaCohortTable.stories.tsx +56 -0
  87. package/src/components/waka-color-picker/WakaColorPicker.stories.tsx +99 -155
  88. package/src/components/waka-combo-counter/WakaComboCounter.stories.tsx +128 -0
  89. package/src/components/waka-command-bar/WakaCommandBar.stories.tsx +45 -0
  90. package/src/components/waka-compare-period/WakaComparePeriod.stories.tsx +76 -0
  91. package/src/components/waka-config-comparator/WakaConfigComparator.stories.tsx +143 -0
  92. package/src/components/waka-connection-matrix/WakaConnectionMatrix.stories.tsx +52 -0
  93. package/src/components/waka-content-recommendation/WakaContentRecommendation.stories.tsx +41 -0
  94. package/src/components/waka-coupon-input/WakaCouponInput.stories.tsx +126 -0
  95. package/src/components/waka-credit-card-input/WakaCreditCardInput.stories.tsx +120 -0
  96. package/src/components/waka-datetime-picker.form-integration/WakaDateTimePickerForm.stories.tsx +79 -0
  97. package/src/components/waka-dependency-tree/WakaDependencyTree.stories.tsx +72 -0
  98. package/src/components/waka-device-trust/WakaDeviceTrust.stories.tsx +109 -0
  99. package/src/components/waka-empty-state/WakaEmptyState.stories.tsx +87 -0
  100. package/src/components/waka-feature-announcement/WakaFeatureAnnouncement.stories.tsx +47 -0
  101. package/src/components/waka-feature-flag-row/WakaFeatureFlagRow.stories.tsx +188 -0
  102. package/src/components/waka-file-upload/WakaFileUpload.stories.tsx +118 -174
  103. package/src/components/waka-floating-nav/WakaFloatingNav.stories.tsx +53 -0
  104. package/src/components/waka-goal-progress/WakaGoalProgress.stories.tsx +137 -0
  105. package/src/components/waka-hotspot/WakaHotspot.stories.tsx +56 -0
  106. package/src/components/waka-invoice-preview/WakaInvoicePreview.stories.tsx +169 -0
  107. package/src/components/waka-kpi-dashboard/WakaKpiDashboard.stories.tsx +46 -0
  108. package/src/components/waka-level-progress/WakaLevelProgress.stories.tsx +94 -75
  109. package/src/components/waka-liquid-button/WakaLiquidButton.stories.tsx +45 -0
  110. package/src/components/waka-magic-link/WakaMagicLink.stories.tsx +61 -0
  111. package/src/components/waka-magnetic-button/WakaMagneticButton.stories.tsx +40 -0
  112. package/src/components/waka-mention-input/WakaMentionInput.stories.tsx +140 -0
  113. package/src/components/waka-milestone-road/WakaMilestoneRoad.stories.tsx +143 -0
  114. package/src/components/waka-orbital-menu/WakaOrbitalMenu.stories.tsx +54 -0
  115. package/src/components/waka-order-tracker/WakaOrderTracker.stories.tsx +163 -0
  116. package/src/components/waka-outstream-video/WakaOutstreamVideo.stories.tsx +94 -0
  117. package/src/components/waka-pagination/WakaPagination.stories.tsx +110 -280
  118. package/src/components/waka-password-strength/WakaPasswordStrength.stories.tsx +132 -268
  119. package/src/components/waka-payment-method-picker/WakaPaymentMethodPicker.stories.tsx +141 -0
  120. package/src/components/waka-permission-matrix/WakaPermissionMatrix.stories.tsx +124 -0
  121. package/src/components/waka-phone-input/WakaPhoneInput.stories.tsx +56 -0
  122. package/src/components/waka-points-popup/WakaPointsPopup.stories.tsx +96 -0
  123. package/src/components/waka-power-up/WakaPowerUp.stories.tsx +121 -0
  124. package/src/components/waka-presence-indicator/WakaPresenceIndicator.stories.tsx +49 -0
  125. package/src/components/waka-pricing-table/WakaPricingTable.stories.tsx +159 -0
  126. package/src/components/waka-product-card/WakaProductCard.stories.tsx +202 -0
  127. package/src/components/waka-progress-onboarding/WakaProgressOnboarding.stories.tsx +57 -0
  128. package/src/components/waka-pull-to-refresh/WakaPullToRefresh.stories.tsx +51 -0
  129. package/src/components/waka-rank-badge/WakaRankBadge.stories.tsx +108 -0
  130. package/src/components/waka-rating-input/WakaRatingInput.stories.tsx +51 -0
  131. package/src/components/waka-reaction-picker/WakaReactionPicker.stories.tsx +52 -0
  132. package/src/components/waka-region-map/WakaRegionMap.stories.tsx +181 -0
  133. package/src/components/waka-resource-pool/WakaResourcePool.stories.tsx +70 -0
  134. package/src/components/waka-rich-text-editor/WakaRichTextEditor.stories.tsx +108 -197
  135. package/src/components/waka-rollback-slider/WakaRollbackSlider.stories.tsx +41 -0
  136. package/src/components/waka-schedule-picker/WakaSchedulePicker.stories.tsx +64 -0
  137. package/src/components/waka-season-pass/WakaSeasonPass.stories.tsx +107 -0
  138. package/src/components/waka-security-scan-result/WakaSecurityScanResult.stories.tsx +146 -0
  139. package/src/components/waka-security-score/WakaSecurityScore.stories.tsx +63 -0
  140. package/src/components/waka-session-manager/WakaSessionManager.stories.tsx +68 -0
  141. package/src/components/waka-signature-pad/WakaSignaturePad.stories.tsx +159 -0
  142. package/src/components/waka-signature-pad/index.tsx +5 -3
  143. package/src/components/waka-sla-tracker/WakaSlaTracker.stories.tsx +65 -0
  144. package/src/components/waka-slider-range/WakaSliderRange.stories.tsx +66 -0
  145. package/src/components/waka-sponsored-badge/WakaSponsoredBadge.stories.tsx +60 -0
  146. package/src/components/waka-sponsored-card/WakaSponsoredCard.stories.tsx +64 -0
  147. package/src/components/waka-sponsored-feed/WakaSponsoredFeed.stories.tsx +58 -0
  148. package/src/components/waka-spotlight/WakaSpotlight.stories.tsx +53 -0
  149. package/src/components/waka-stats-hexagon/WakaStatsHexagon.stories.tsx +161 -0
  150. package/src/components/waka-stepper/WakaStepper.stories.tsx +137 -410
  151. package/src/components/waka-swipe-card/WakaSwipeCard.stories.tsx +51 -0
  152. package/src/components/waka-tag-input/WakaTagInput.stories.tsx +224 -0
  153. package/src/components/waka-team-banner/WakaTeamBanner.stories.tsx +50 -0
  154. package/src/components/waka-theme-creator/WakaThemeCreator.stories.tsx +58 -0
  155. package/src/components/waka-theme-manager/WakaThemeManager.stories.tsx +298 -0
  156. package/src/components/waka-theme-manager/index.tsx +6 -11
  157. package/src/components/waka-thread-view/WakaThreadView.stories.tsx +143 -0
  158. package/src/components/waka-timeline/WakaTimeline.stories.tsx +171 -324
  159. package/src/components/waka-tooltip-tour/WakaTooltipTour.stories.tsx +92 -0
  160. package/src/components/waka-tour-guide/WakaTourGuide.stories.tsx +89 -0
  161. package/src/components/waka-treemap-chart/WakaTreemapChart.stories.tsx +234 -129
  162. package/src/components/waka-treemap-chart/index.tsx +2 -2
  163. package/src/components/waka-two-factor-setup/WakaTwoFactorSetup.stories.tsx +142 -0
  164. package/src/components/waka-typing-indicator/WakaTypingIndicator.stories.tsx +134 -0
  165. package/src/components/waka-video-ad/WakaVideoAd.stories.tsx +138 -0
  166. package/src/components/waka-video-call/WakaVideoCall.stories.tsx +186 -0
  167. package/src/components/waka-video-overlay/WakaVideoOverlay.stories.tsx +100 -0
  168. package/src/components/waka-voice-message/WakaVoiceMessage.stories.tsx +190 -0
  169. package/src/components/waka-welcome-modal/WakaWelcomeModal.stories.tsx +87 -0
  170. package/src/components/waka-xp-bar/WakaXPBar.stories.tsx +29 -29
  171. package/dist/useDataTableImport-D8R2HQl6.mjs +0 -229
  172. package/dist/useDataTableImport-S_hhA5Wo.js +0 -9
  173. package/src/components/DataTable/README.md +0 -446
@@ -0,0 +1,273 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+ import { WakaCapacityPlanner, type ResourceData, type ScalingRecommendation } from "./index"
3
+
4
+ const meta: Meta<typeof WakaCapacityPlanner> = {
5
+ title: "DevOps/WakaCapacityPlanner",
6
+ component: WakaCapacityPlanner,
7
+ parameters: { layout: "padded" },
8
+ tags: ["autodocs"],
9
+ argTypes: {
10
+ initialTimelineRange: { control: "select", options: ["1m", "3m", "6m", "12m"], description: "Plage temporelle initiale" },
11
+ showRecommendations: { control: "boolean", description: "Afficher les recommandations" },
12
+ showTimeline: { control: "boolean", description: "Afficher le slider de timeline" },
13
+ showProjectionChart: { control: "boolean", description: "Afficher le graphique de projection" },
14
+ animated: { control: "boolean", description: "Activer les animations" },
15
+ size: { control: "select", options: ["sm", "md", "lg"], description: "Taille du composant" },
16
+ },
17
+ }
18
+
19
+ export default meta
20
+ type Story = StoryObj<typeof WakaCapacityPlanner>
21
+
22
+ const resources: ResourceData[] = [
23
+ {
24
+ id: "cpu",
25
+ name: "CPU",
26
+ type: "cpu",
27
+ current: 65,
28
+ total: 100,
29
+ unit: "%",
30
+ growthRate: 5,
31
+ projections: { "1m": 70, "3m": 85, "6m": 95, "12m": 110 },
32
+ },
33
+ {
34
+ id: "memory",
35
+ name: "Memory",
36
+ type: "memory",
37
+ current: 78,
38
+ total: 128,
39
+ unit: "GB",
40
+ growthRate: 8,
41
+ projections: { "1m": 84, "3m": 95, "6m": 110, "12m": 130 },
42
+ },
43
+ {
44
+ id: "storage",
45
+ name: "Storage",
46
+ type: "storage",
47
+ current: 450,
48
+ total: 1000,
49
+ unit: "GB",
50
+ growthRate: 10,
51
+ projections: { "1m": 495, "3m": 600, "6m": 750, "12m": 950 },
52
+ },
53
+ {
54
+ id: "network",
55
+ name: "Network",
56
+ type: "network",
57
+ current: 200,
58
+ total: 1000,
59
+ unit: "Mbps",
60
+ growthRate: 3,
61
+ projections: { "1m": 210, "3m": 230, "6m": 260, "12m": 300 },
62
+ },
63
+ ]
64
+
65
+ const recommendations: ScalingRecommendation[] = [
66
+ {
67
+ id: "rec-1",
68
+ resourceId: "cpu",
69
+ type: "scale_up",
70
+ priority: "high",
71
+ title: "Upgrade CPU capacity",
72
+ description: "CPU utilization is projected to exceed 90% within 3 months.",
73
+ action: "Upgrade Now",
74
+ timeframe: "Within 3 months",
75
+ costImpact: "+$150/month",
76
+ },
77
+ {
78
+ id: "rec-2",
79
+ resourceId: "memory",
80
+ type: "scale_out",
81
+ priority: "medium",
82
+ title: "Add more memory nodes",
83
+ description: "Consider horizontal scaling to distribute memory load.",
84
+ action: "Plan Scaling",
85
+ timeframe: "Within 6 months",
86
+ costImpact: "+$200/month",
87
+ },
88
+ ]
89
+
90
+ export const Default: Story = {
91
+ args: {
92
+ resources,
93
+ recommendations,
94
+ initialTimelineRange: "3m",
95
+ showRecommendations: true,
96
+ showTimeline: true,
97
+ showProjectionChart: true,
98
+ animated: true,
99
+ size: "md",
100
+ },
101
+ render: (args) => (
102
+ <div className="max-w-4xl">
103
+ <WakaCapacityPlanner {...args} />
104
+ </div>
105
+ ),
106
+ }
107
+
108
+ export const CriticalCapacity: Story = {
109
+ args: {
110
+ resources: [
111
+ {
112
+ id: "cpu",
113
+ name: "CPU",
114
+ type: "cpu",
115
+ current: 92,
116
+ total: 100,
117
+ unit: "%",
118
+ growthRate: 3,
119
+ projections: { "1m": 95, "3m": 100, "6m": 110, "12m": 130 },
120
+ },
121
+ {
122
+ id: "memory",
123
+ name: "Memory",
124
+ type: "memory",
125
+ current: 120,
126
+ total: 128,
127
+ unit: "GB",
128
+ growthRate: 5,
129
+ projections: { "1m": 126, "3m": 135, "6m": 150, "12m": 175 },
130
+ },
131
+ ],
132
+ recommendations: [
133
+ {
134
+ id: "rec-urgent",
135
+ resourceId: "cpu",
136
+ type: "scale_up",
137
+ priority: "urgent",
138
+ title: "Immediate CPU upgrade required",
139
+ description: "CPU is critically overloaded and affecting performance.",
140
+ action: "Urgent Action",
141
+ timeframe: "Immediate",
142
+ costImpact: "+$300/month",
143
+ },
144
+ ],
145
+ showRecommendations: true,
146
+ initialTimelineRange: "1m",
147
+ },
148
+ render: (args) => (
149
+ <div className="max-w-4xl">
150
+ <WakaCapacityPlanner {...args} />
151
+ </div>
152
+ ),
153
+ }
154
+
155
+ export const HealthyCapacity: Story = {
156
+ args: {
157
+ resources: [
158
+ {
159
+ id: "cpu",
160
+ name: "CPU",
161
+ type: "cpu",
162
+ current: 35,
163
+ total: 100,
164
+ unit: "%",
165
+ growthRate: 2,
166
+ projections: { "1m": 37, "3m": 42, "6m": 48, "12m": 55 },
167
+ },
168
+ {
169
+ id: "memory",
170
+ name: "Memory",
171
+ type: "memory",
172
+ current: 40,
173
+ total: 128,
174
+ unit: "GB",
175
+ growthRate: 3,
176
+ projections: { "1m": 42, "3m": 47, "6m": 55, "12m": 65 },
177
+ },
178
+ {
179
+ id: "storage",
180
+ name: "Storage",
181
+ type: "storage",
182
+ current: 250,
183
+ total: 1000,
184
+ unit: "GB",
185
+ growthRate: 5,
186
+ projections: { "1m": 265, "3m": 300, "6m": 360, "12m": 450 },
187
+ },
188
+ ],
189
+ recommendations: [],
190
+ initialTimelineRange: "6m",
191
+ showRecommendations: true,
192
+ },
193
+ render: (args) => (
194
+ <div className="max-w-4xl">
195
+ <WakaCapacityPlanner {...args} />
196
+ </div>
197
+ ),
198
+ }
199
+
200
+ export const SmallSize: Story = {
201
+ args: {
202
+ resources: resources.slice(0, 2),
203
+ initialTimelineRange: "3m",
204
+ showRecommendations: false,
205
+ size: "sm",
206
+ },
207
+ render: (args) => (
208
+ <div className="max-w-2xl">
209
+ <WakaCapacityPlanner {...args} />
210
+ </div>
211
+ ),
212
+ }
213
+
214
+ export const LargeSize: Story = {
215
+ args: {
216
+ resources,
217
+ recommendations,
218
+ initialTimelineRange: "6m",
219
+ showRecommendations: true,
220
+ size: "lg",
221
+ },
222
+ render: (args) => (
223
+ <div className="max-w-5xl">
224
+ <WakaCapacityPlanner {...args} />
225
+ </div>
226
+ ),
227
+ }
228
+
229
+ export const NoAnimations: Story = {
230
+ args: {
231
+ resources,
232
+ initialTimelineRange: "3m",
233
+ animated: false,
234
+ showRecommendations: false,
235
+ },
236
+ render: (args) => (
237
+ <div className="max-w-4xl">
238
+ <WakaCapacityPlanner {...args} />
239
+ </div>
240
+ ),
241
+ }
242
+
243
+ export const TimelineOnly: Story = {
244
+ args: {
245
+ resources,
246
+ initialTimelineRange: "3m",
247
+ showTimeline: true,
248
+ showProjectionChart: false,
249
+ showRecommendations: false,
250
+ },
251
+ render: (args) => (
252
+ <div className="max-w-4xl">
253
+ <WakaCapacityPlanner {...args} />
254
+ </div>
255
+ ),
256
+ }
257
+
258
+ export const WithCallbacks: Story = {
259
+ args: {
260
+ resources,
261
+ recommendations,
262
+ initialTimelineRange: "3m",
263
+ showRecommendations: true,
264
+ onTimelineChange: (range) => console.log("Timeline changed:", range),
265
+ onResourceClick: (resource) => console.log("Resource clicked:", resource.name),
266
+ onRecommendationAction: (rec) => console.log("Action triggered:", rec.title),
267
+ },
268
+ render: (args) => (
269
+ <div className="max-w-4xl">
270
+ <WakaCapacityPlanner {...args} />
271
+ </div>
272
+ ),
273
+ }
@@ -0,0 +1,176 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+ import { WakaCartSummary, type CartItem } from "./index"
3
+ import { useState } from "react"
4
+
5
+ const meta: Meta<typeof WakaCartSummary> = {
6
+ title: "E-commerce/WakaCartSummary",
7
+ component: WakaCartSummary,
8
+ parameters: {
9
+ layout: "centered",
10
+ },
11
+ tags: ["autodocs"],
12
+ argTypes: {
13
+ showImages: {
14
+ control: "boolean",
15
+ description: "Afficher les images",
16
+ },
17
+ enableQuantityEdit: {
18
+ control: "boolean",
19
+ description: "Activer l'édition des quantités",
20
+ },
21
+ enableRemove: {
22
+ control: "boolean",
23
+ description: "Activer la suppression d'articles",
24
+ },
25
+ currency: {
26
+ control: "text",
27
+ description: "Code devise ISO 4217 (EUR, USD, etc.)",
28
+ },
29
+ taxRate: {
30
+ control: { type: "number", min: 0, max: 1, step: 0.01 },
31
+ description: "Taux de TVA (0.2 = 20%)",
32
+ },
33
+ shippingCost: {
34
+ control: "number",
35
+ description: "Frais de livraison",
36
+ },
37
+ },
38
+ }
39
+
40
+ export default meta
41
+ type Story = StoryObj<typeof WakaCartSummary>
42
+
43
+ const sampleItems: CartItem[] = [
44
+ {
45
+ id: "1",
46
+ name: "T-shirt Premium",
47
+ description: "Coton bio, Taille M",
48
+ image: "https://picsum.photos/seed/tshirt/100/100",
49
+ price: 29.99,
50
+ quantity: 2,
51
+ maxQuantity: 10,
52
+ },
53
+ {
54
+ id: "2",
55
+ name: "Pantalon Chino",
56
+ description: "Beige, Taille 42",
57
+ image: "https://picsum.photos/seed/pants/100/100",
58
+ price: 59.99,
59
+ quantity: 1,
60
+ maxQuantity: 5,
61
+ },
62
+ {
63
+ id: "3",
64
+ name: "Sneakers Classic",
65
+ description: "Blanc/Noir, Pointure 43",
66
+ image: "https://picsum.photos/seed/shoes/100/100",
67
+ price: 89.99,
68
+ quantity: 1,
69
+ maxQuantity: 3,
70
+ },
71
+ ]
72
+
73
+ export const Default: Story = {
74
+ args: {
75
+ items: sampleItems,
76
+ showImages: true,
77
+ enableQuantityEdit: true,
78
+ enableRemove: true,
79
+ currency: "EUR",
80
+ },
81
+ render: (args) => (
82
+ <div style={{ width: 400 }}>
83
+ <WakaCartSummary {...args} />
84
+ </div>
85
+ ),
86
+ }
87
+
88
+ export const WithoutImages: Story = {
89
+ args: {
90
+ items: sampleItems,
91
+ showImages: false,
92
+ enableQuantityEdit: true,
93
+ enableRemove: true,
94
+ currency: "EUR",
95
+ },
96
+ render: (args) => (
97
+ <div style={{ width: 400 }}>
98
+ <WakaCartSummary {...args} />
99
+ </div>
100
+ ),
101
+ }
102
+
103
+ export const ReadOnly: Story = {
104
+ args: {
105
+ items: sampleItems,
106
+ showImages: true,
107
+ enableQuantityEdit: false,
108
+ enableRemove: false,
109
+ currency: "EUR",
110
+ },
111
+ render: (args) => (
112
+ <div style={{ width: 400 }}>
113
+ <WakaCartSummary {...args} />
114
+ </div>
115
+ ),
116
+ }
117
+
118
+ export const SingleItem: Story = {
119
+ args: {
120
+ items: [sampleItems[0]],
121
+ showImages: true,
122
+ enableQuantityEdit: true,
123
+ currency: "EUR",
124
+ },
125
+ render: (args) => (
126
+ <div style={{ width: 400 }}>
127
+ <WakaCartSummary {...args} />
128
+ </div>
129
+ ),
130
+ }
131
+
132
+ export const EmptyCart: Story = {
133
+ args: {
134
+ items: [],
135
+ showImages: true,
136
+ currency: "EUR",
137
+ },
138
+ render: (args) => (
139
+ <div style={{ width: 400 }}>
140
+ <WakaCartSummary {...args} />
141
+ </div>
142
+ ),
143
+ }
144
+
145
+ export const USDCurrency: Story = {
146
+ args: {
147
+ items: sampleItems.map(item => ({ ...item, price: item.price * 1.1 })),
148
+ showImages: true,
149
+ enableQuantityEdit: true,
150
+ currency: "USD",
151
+ },
152
+ render: (args) => (
153
+ <div style={{ width: 400 }}>
154
+ <WakaCartSummary {...args} />
155
+ </div>
156
+ ),
157
+ }
158
+
159
+ export const WithTaxAndShipping: Story = {
160
+ args: {
161
+ items: sampleItems,
162
+ showImages: true,
163
+ enableQuantityEdit: true,
164
+ enableRemove: true,
165
+ currency: "EUR",
166
+ taxRate: 0.2,
167
+ shippingCost: 5.99,
168
+ freeShippingThreshold: 100,
169
+ },
170
+ render: (args) => (
171
+ <div style={{ width: 400 }}>
172
+ <WakaCartSummary {...args} />
173
+ </div>
174
+ ),
175
+ }
176
+
@@ -930,28 +930,35 @@ export function useCartSummary(
930
930
  // Add item
931
931
  const addItem = useCallback(
932
932
  (item: CartItem) => {
933
- setItems((prev) => {
934
- const existingIndex = prev.findIndex((i) => i.id === item.id)
933
+ setItemsState((prev: CartItem[]) => {
934
+ const existingIndex = prev.findIndex((i: CartItem) => i.id === item.id)
935
935
  if (existingIndex >= 0) {
936
936
  const updated = [...prev]
937
937
  updated[existingIndex] = {
938
938
  ...updated[existingIndex],
939
939
  quantity: updated[existingIndex].quantity + item.quantity,
940
940
  }
941
+ onCartChange?.(updated)
941
942
  return updated
942
943
  }
943
- return [...prev, item]
944
+ const newItems = [...prev, item]
945
+ onCartChange?.(newItems)
946
+ return newItems
944
947
  })
945
948
  },
946
- [setItems]
949
+ [onCartChange]
947
950
  )
948
951
 
949
952
  // Remove item
950
953
  const removeItem = useCallback(
951
954
  (itemId: string) => {
952
- setItems((prev) => prev.filter((i) => i.id !== itemId))
955
+ setItemsState((prev: CartItem[]) => {
956
+ const newItems = prev.filter((i: CartItem) => i.id !== itemId)
957
+ onCartChange?.(newItems)
958
+ return newItems
959
+ })
953
960
  },
954
- [setItems]
961
+ [onCartChange]
955
962
  )
956
963
 
957
964
  // Update quantity
@@ -962,13 +969,15 @@ export function useCartSummary(
962
969
  return
963
970
  }
964
971
 
965
- setItems((prev) =>
966
- prev.map((item) =>
972
+ setItemsState((prev: CartItem[]) => {
973
+ const newItems = prev.map((item: CartItem) =>
967
974
  item.id === itemId ? { ...item, quantity } : item
968
975
  )
969
- )
976
+ onCartChange?.(newItems)
977
+ return newItems
978
+ })
970
979
  },
971
- [setItems, removeItem]
980
+ [removeItem, onCartChange]
972
981
  )
973
982
 
974
983
  // Clear cart
@@ -0,0 +1,98 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+ import { WakaChallengeTimer, Challenge } from "./index"
3
+
4
+ const createChallenge = (hoursRemaining: number, category: Challenge["category"] = "daily"): Challenge => ({
5
+ id: "challenge-1",
6
+ name: "Complete 5 Tasks",
7
+ description: "Finish 5 tasks to earn bonus XP",
8
+ endTime: new Date(Date.now() + hoursRemaining * 60 * 60 * 1000),
9
+ category,
10
+ tasks: [
11
+ { id: "t1", text: "Complete a quiz", completed: true },
12
+ { id: "t2", text: "Invite a friend", completed: true },
13
+ { id: "t3", text: "Reach level 10", completed: false, current: 7, target: 10 },
14
+ { id: "t4", text: "Earn 100 XP", completed: false, current: 45, target: 100 },
15
+ { id: "t5", text: "Play for 30 minutes", completed: false },
16
+ ],
17
+ rewards: [
18
+ { type: "xp", label: "XP", value: 500 },
19
+ { type: "badge", label: "Badge", value: "Speed Demon" },
20
+ ],
21
+ })
22
+
23
+ const meta: Meta<typeof WakaChallengeTimer> = {
24
+ title: "Components/Gamification/WakaChallengeTimer",
25
+ component: WakaChallengeTimer,
26
+ parameters: {
27
+ layout: "centered",
28
+ },
29
+ tags: ["autodocs"],
30
+ argTypes: {
31
+ size: {
32
+ control: "select",
33
+ options: ["compact", "default", "large"],
34
+ description: "Size variant",
35
+ },
36
+ isPaused: {
37
+ control: "boolean",
38
+ description: "Whether timer is paused",
39
+ },
40
+ urgentThreshold: {
41
+ control: "number",
42
+ description: "Seconds threshold for urgent mode",
43
+ },
44
+ },
45
+ }
46
+
47
+ export default meta
48
+ type Story = StoryObj<typeof WakaChallengeTimer>
49
+
50
+ export const Default: Story = {
51
+ args: {
52
+ challenge: createChallenge(24),
53
+ size: "default",
54
+ },
55
+ render: (args) => <WakaChallengeTimer {...args} />,
56
+ }
57
+
58
+ export const Compact: Story = {
59
+ args: {
60
+ challenge: createChallenge(12, "weekly"),
61
+ size: "compact",
62
+ },
63
+ render: (args) => <WakaChallengeTimer {...args} />,
64
+ }
65
+
66
+ export const Large: Story = {
67
+ args: {
68
+ challenge: createChallenge(48, "event"),
69
+ size: "large",
70
+ },
71
+ render: (args) => (
72
+ <div className="w-[500px]">
73
+ <WakaChallengeTimer {...args} />
74
+ </div>
75
+ ),
76
+ }
77
+
78
+ export const Urgent: Story = {
79
+ args: {
80
+ challenge: createChallenge(0.5), // 30 minutes
81
+ size: "default",
82
+ urgentThreshold: 3600,
83
+ },
84
+ render: (args) => <WakaChallengeTimer {...args} />,
85
+ }
86
+
87
+ export const Personal: Story = {
88
+ args: {
89
+ challenge: {
90
+ ...createChallenge(2, "personal"),
91
+ isPersonal: true,
92
+ },
93
+ size: "default",
94
+ isPaused: false,
95
+ },
96
+ render: (args) => <WakaChallengeTimer {...args} />,
97
+ }
98
+