@umituz/web-dashboard 6.1.0 → 6.2.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 (135) hide show
  1. package/README.md +47 -73
  2. package/package.json +5 -9
  3. package/src/config/DashboardConfig.ts +19 -68
  4. package/src/domains/analytics/components/index.ts +0 -6
  5. package/src/domains/analytics/hooks/index.ts +0 -6
  6. package/src/domains/analytics/hooks/useAnalytics.ts +2 -20
  7. package/src/domains/analytics/index.ts +0 -10
  8. package/src/domains/analytics/services/AnalyticsEngineService.ts +7 -74
  9. package/src/domains/analytics/services/PerformanceService.ts +27 -138
  10. package/src/domains/analytics/services/index.ts +0 -4
  11. package/src/domains/analytics/types/analytics.ts +100 -270
  12. package/src/domains/analytics/types/index.ts +0 -6
  13. package/src/domains/analytics/utils/analytics.test.ts +2 -9
  14. package/src/domains/analytics/utils/analytics.ts +1 -22
  15. package/src/domains/analytics/utils/index.ts +0 -6
  16. package/src/domains/calendar/config.ts +0 -7
  17. package/src/domains/calendar/hooks/index.ts +0 -4
  18. package/src/domains/calendar/hooks/useCalendar.ts +7 -27
  19. package/src/domains/calendar/index.ts +0 -4
  20. package/src/domains/calendar/services/CalendarService.ts +0 -21
  21. package/src/domains/calendar/services/index.ts +0 -4
  22. package/src/domains/calendar/types/calendar.types.ts +9 -53
  23. package/src/domains/calendar/utils/contentItemMapper.test.ts +0 -4
  24. package/src/domains/calendar/utils/contentItemMapper.ts +0 -31
  25. package/src/domains/calendar/utils/index.ts +0 -26
  26. package/src/domains/layouts/components/index.ts +0 -4
  27. package/src/domains/layouts/hooks/dashboard.ts +0 -21
  28. package/src/domains/layouts/hooks/index.ts +0 -4
  29. package/src/domains/layouts/index.ts +0 -6
  30. package/src/domains/layouts/theme/default.ts +0 -12
  31. package/src/domains/layouts/theme/index.ts +0 -4
  32. package/src/domains/layouts/theme/presets.ts +0 -9
  33. package/src/domains/layouts/theme/utils.ts +0 -15
  34. package/src/domains/layouts/types/index.ts +0 -4
  35. package/src/domains/layouts/types/layout.ts +18 -56
  36. package/src/domains/layouts/types/notification.ts +4 -17
  37. package/src/domains/layouts/types/sidebar.ts +8 -28
  38. package/src/domains/layouts/types/theme.ts +23 -59
  39. package/src/domains/layouts/types/user.ts +9 -30
  40. package/src/domains/layouts/utils/dashboard.ts +4 -48
  41. package/src/domains/layouts/utils/index.ts +0 -4
  42. package/src/domains/modules/build.tsx +2 -16
  43. package/src/domains/modules/types.ts +8 -23
  44. package/src/domains/onboarding/calc/calc.test.ts +1 -9
  45. package/src/domains/onboarding/calc/card-stack-motion-curve.ts +0 -6
  46. package/src/domains/onboarding/calc/count-with-locale.ts +0 -8
  47. package/src/domains/onboarding/calc/duration-equal-split.ts +0 -12
  48. package/src/domains/onboarding/calc/elapsed-millis.ts +0 -6
  49. package/src/domains/onboarding/calc/progress-percentage.ts +1 -11
  50. package/src/domains/onboarding/calc/slider-value-bounds.ts +1 -11
  51. package/src/domains/onboarding/calc/step-index-clamp.ts +0 -9
  52. package/src/domains/onboarding/calc/swipe-gesture-curve.ts +0 -13
  53. package/src/domains/onboarding/components/{shared/AnimationWrapper.tsx → AnimationWrapper.tsx} +0 -4
  54. package/src/domains/onboarding/components/{shared/OnboardingErrorBoundary.tsx → OnboardingErrorBoundary.tsx} +7 -27
  55. package/src/domains/onboarding/components/OnboardingFlow.test.tsx +8 -30
  56. package/src/domains/onboarding/components/OnboardingFlow.tsx +13 -61
  57. package/src/domains/onboarding/components/OnboardingIntl.tsx +1 -11
  58. package/src/domains/onboarding/components/PrimaryButton.tsx +40 -0
  59. package/src/domains/onboarding/components/ProgressBar.tsx +32 -0
  60. package/src/domains/onboarding/components/QuestionWrapper.tsx +28 -0
  61. package/src/domains/onboarding/components/ScreenContainer.tsx +19 -0
  62. package/src/domains/onboarding/components/{shared/SwipeCard.test.tsx → SwipeCard.test.tsx} +1 -3
  63. package/src/domains/onboarding/components/{shared/SwipeCard.tsx → SwipeCard.tsx} +10 -28
  64. package/src/domains/onboarding/components/renderBundledIcon.tsx +7 -0
  65. package/src/domains/onboarding/components/screens/AccountGateScreen.tsx +7 -17
  66. package/src/domains/onboarding/components/screens/AppDemoScreen.tsx +4 -10
  67. package/src/domains/onboarding/components/screens/ComparisonScreen.tsx +12 -22
  68. package/src/domains/onboarding/components/screens/GoalQuestionScreen.tsx +9 -6
  69. package/src/domains/onboarding/components/screens/PainPointsScreen.tsx +10 -10
  70. package/src/domains/onboarding/components/screens/PaywallScreen.tsx +22 -38
  71. package/src/domains/onboarding/components/screens/PermissionPrimingScreen.tsx +14 -29
  72. package/src/domains/onboarding/components/screens/PersonalizedSolutionScreen.tsx +10 -23
  73. package/src/domains/onboarding/components/screens/PreferencesScreen.tsx +13 -27
  74. package/src/domains/onboarding/components/screens/ProcessingScreen.tsx +11 -27
  75. package/src/domains/onboarding/components/screens/SocialProofScreen.tsx +22 -51
  76. package/src/domains/onboarding/components/screens/TinderCardsScreen.tsx +13 -30
  77. package/src/domains/onboarding/components/screens/ValueDeliveryScreen.tsx +13 -29
  78. package/src/domains/onboarding/components/screens/WelcomeScreen.tsx +12 -32
  79. package/src/domains/onboarding/{components/hooks → hooks}/useOnboardingAnalytics.test.tsx +1 -1
  80. package/src/domains/onboarding/{components/hooks → hooks}/useOnboardingAnalytics.ts +3 -16
  81. package/src/domains/onboarding/{components/hooks → hooks}/useOnboardingProgress.test.tsx +2 -2
  82. package/src/domains/onboarding/{components/hooks → hooks}/useOnboardingProgress.ts +10 -21
  83. package/src/domains/onboarding/{components/hooks → hooks}/usePermissionPriming.ts +3 -10
  84. package/src/domains/onboarding/{components/hooks → hooks}/useReducedMotion.ts +0 -5
  85. package/src/domains/onboarding/index.ts +16 -45
  86. package/src/domains/onboarding/predicates/has-handler.ts +0 -4
  87. package/src/domains/onboarding/predicates/icon-name-resolves.ts +1 -17
  88. package/src/domains/onboarding/predicates/permission-granted.ts +0 -5
  89. package/src/domains/onboarding/predicates/permission-supports.ts +1 -11
  90. package/src/domains/onboarding/predicates/predicates.test.ts +6 -20
  91. package/src/domains/onboarding/predicates/screen-emits-data.ts +0 -4
  92. package/src/domains/onboarding/predicates/storage-available.ts +0 -8
  93. package/src/domains/onboarding/templates/TemplateDemoFallback.tsx +19 -39
  94. package/src/domains/onboarding/templates/art-onboarding.ts +1 -11
  95. package/src/domains/onboarding/templates/health-onboarding.ts +0 -5
  96. package/src/domains/onboarding/templates/platform-onboarding.ts +0 -9
  97. package/src/domains/onboarding/templates/video-onboarding.ts +0 -5
  98. package/src/domains/onboarding/test/setup.ts +1 -8
  99. package/src/domains/onboarding/types/config.ts +7 -18
  100. package/src/domains/onboarding/types/labels.ts +25 -59
  101. package/src/domains/onboarding/types/screens.ts +3 -11
  102. package/src/domains/onboarding/utils/analytics-dispatch.ts +2 -21
  103. package/src/domains/onboarding/utils/default-storage-key.ts +0 -1
  104. package/src/domains/onboarding/utils/index.ts +0 -1
  105. package/src/domains/onboarding/utils/local-storage-bridge.ts +1 -21
  106. package/src/domains/onboarding/utils/permission-bridge.ts +0 -8
  107. package/src/domains/onboarding/validation/flow-structure-check.ts +0 -6
  108. package/src/domains/onboarding/validation/permission-status-check.ts +0 -5
  109. package/src/domains/onboarding/validation/screen-config-check.ts +0 -5
  110. package/src/domains/onboarding/validation/stored-progress-check.ts +1 -10
  111. package/src/domains/onboarding/validation/validation.test.ts +1 -6
  112. package/src/domains/permissions/hasPermission.ts +0 -8
  113. package/src/domains/permissions/types.ts +0 -20
  114. package/src/domains/settings/components/index.ts +0 -4
  115. package/src/domains/settings/hooks/index.ts +0 -4
  116. package/src/domains/settings/hooks/useSettings.ts +1 -26
  117. package/src/domains/settings/index.ts +0 -6
  118. package/src/domains/settings/types/index.ts +0 -4
  119. package/src/domains/settings/types/settings.ts +23 -67
  120. package/src/domains/settings/utils/index.ts +0 -4
  121. package/src/domains/settings/utils/settings.ts +0 -45
  122. package/src/styles/dashboard.css +818 -1
  123. package/src/domains/onboarding/components/shared/OptionCard.tsx +0 -73
  124. package/src/domains/onboarding/components/shared/PrimaryButton.tsx +0 -58
  125. package/src/domains/onboarding/components/shared/ProgressBar.tsx +0 -51
  126. package/src/domains/onboarding/components/shared/QuestionWrapper.tsx +0 -36
  127. package/src/domains/onboarding/components/shared/ScreenContainer.tsx +0 -29
  128. package/src/domains/onboarding/components/shared/index.ts +0 -16
  129. package/src/domains/onboarding/components/shared/renderBundledIcon.tsx +0 -20
  130. package/src/domains/onboarding/onboarding.css +0 -1
  131. package/src/domains/onboarding/theme/cn.ts +0 -10
  132. package/src/domains/onboarding/theme/index.css +0 -131
  133. package/src/domains/onboarding/theme/index.ts +0 -12
  134. package/src/domains/onboarding/theme/tokens.ts +0 -122
  135. /package/src/domains/onboarding/{components/hooks → hooks}/index.ts +0 -0
@@ -1,132 +1,66 @@
1
- /**
2
- * Analytics Types
3
- *
4
- * Type definitions for analytics system
5
- */
6
-
7
1
  import type { ComponentType } from "react";
8
2
 
9
- /**
10
- * Metric card data
11
- */
12
3
  export interface Metric {
13
- /** Unique identifier */
14
- id: string;
15
- /** Metric name */
16
- name: string;
17
- /** Current value */
18
- value: number;
19
- /** Previous period value */
20
- previousValue?: number;
21
- /** Unit (%, $, etc.) */
22
- unit?: string;
23
- /** Trend direction */
24
- trend?: "up" | "down" | "stable";
25
- /** Icon component */
26
- icon?: ComponentType<{ className?: string }>;
4
+ id: string;
5
+ name: string;
6
+ value: number;
7
+ previousValue?: number;
8
+ unit?: string;
9
+ trend?: "up" | "down" | "stable";
10
+ icon?: ComponentType<{ className?: string }>;
27
11
  }
28
12
 
29
- /**
30
- * Time series data point
31
- */
32
13
  export interface TimeSeriesData {
33
- /** Date/label */
34
- date: string;
35
- /** Metric values */
36
- [key: string]: string | number;
14
+ date: string;
15
+ [key: string]: string | number;
37
16
  }
38
17
 
39
- /**
40
- * Chart data point
41
- */
42
18
  export interface ChartData {
43
- /** X-axis label */
44
- label: string;
45
- /** Y-axis value */
46
- value: number;
47
- /** Additional data */
48
- [key: string]: string | number | boolean;
19
+ label: string;
20
+ value: number;
21
+ [key: string]: string | number | boolean;
49
22
  }
50
23
 
51
- /**
52
- * Funnel step
53
- */
54
24
  export interface FunnelStep {
55
- /** Step name */
56
- name: string;
57
- /** User count at this step */
58
- count: number;
59
- /** Conversion rate to this step */
60
- conversionRate: number;
61
- /** Drop-off rate from previous step */
62
- dropOffRate: number;
63
- /** Average time spent at step */
64
- averageTime?: number;
25
+ name: string;
26
+ count: number;
27
+ conversionRate: number;
28
+ dropOffRate: number;
29
+ averageTime?: number;
65
30
  }
66
31
 
67
- /**
68
- * Funnel data
69
- */
70
32
  export interface FunnelData {
71
- /** Funnel title */
72
- title: string;
73
- /** Funnel steps */
74
- steps: FunnelStep[];
75
- /** Total starting users */
76
- totalUsers: number;
77
- /** Final conversion rate */
78
- finalConversion: number;
33
+ title: string;
34
+ steps: FunnelStep[];
35
+ totalUsers: number;
36
+ finalConversion: number;
79
37
  }
80
38
 
81
- /**
82
- * Cohort analysis data
83
- */
84
39
  export interface CohortAnalysis {
85
- /** Cohort identifier */
86
- cohort: string;
87
- /** Cohort size */
88
- size: number;
89
- /** Retention rates over time */
90
- retention: number[];
91
- /** Average retention rate */
92
- averageRetention: number;
40
+ cohort: string;
41
+ size: number;
42
+ retention: number[];
43
+ averageRetention: number;
93
44
  }
94
45
 
95
- /**
96
- * User segment
97
- */
98
46
  export interface UserSegment {
99
- /** Segment name */
100
- name: string;
101
- /** User count */
102
- count: number;
103
- /** Percentage of total users */
104
- percentage: number;
105
- /** Segment characteristics */
106
- characteristics: string[];
107
- /** Behavioral metrics */
108
- behavior: {
47
+ name: string;
48
+ count: number;
49
+ percentage: number;
50
+ characteristics: string[];
51
+ behavior: {
109
52
  avgSessionDuration: number;
110
53
  pagesPerSession: number;
111
54
  bounceRate: number;
112
55
  };
113
56
  }
114
57
 
115
- /**
116
- * KPI data with comparison
117
- */
118
58
  export interface KPIData {
119
- /** Current period value */
120
- current: number;
121
- /** Previous period value */
122
- previous: number;
123
- /** Growth rate percentage */
124
- growth: number;
59
+ current: number;
60
+ previous: number;
61
+ growth: number;
125
62
  }
126
63
 
127
- /**
128
- * KPIs container
129
- */
130
64
  export interface KPIs {
131
65
  downloads: KPIData;
132
66
  engagement: KPIData;
@@ -135,9 +69,6 @@ export interface KPIs {
135
69
  retention: KPIData;
136
70
  }
137
71
 
138
- /**
139
- * Chart types
140
- */
141
72
  export type ChartType =
142
73
  | "line"
143
74
  | "bar"
@@ -149,202 +80,101 @@ export type ChartType =
149
80
  | "metric"
150
81
  | "table";
151
82
 
152
- /**
153
- * Chart configuration
154
- */
155
83
  export interface ChartConfig {
156
- /** Stable identifier — used as React key, also for telemetry */
157
- id: string;
158
- /** Chart type */
159
- type: ChartType;
160
- /** Chart title */
161
- title?: string;
162
- /** Chart description */
163
- description?: string;
164
- /** Data */
165
- data: TimeSeriesData[] | ChartData[] | Metric[];
166
- /** X-axis key */
167
- xAxisKey?: string;
168
- /** Y-axis keys */
169
- yAxisKeys?: string[];
170
- /** Color scheme (CSS variable names, e.g. "hsl(var(--primary))") */
171
- colors?: string[];
172
- /** Show legend */
173
- showLegend?: boolean;
174
- /** Show grid */
175
- showGrid?: boolean;
176
- /** Show tooltip */
177
- showTooltip?: boolean;
178
- /** Chart height */
179
- height?: number | string;
180
- /** Chart aspect ratio */
181
- aspectRatio?: string;
84
+ id: string;
85
+ type: ChartType;
86
+ title?: string;
87
+ description?: string;
88
+ data: TimeSeriesData[] | ChartData[] | Metric[];
89
+ xAxisKey?: string;
90
+ yAxisKeys?: string[];
91
+ colors?: string[];
92
+ showLegend?: boolean;
93
+ showGrid?: boolean;
94
+ showTooltip?: boolean;
95
+ height?: number | string;
96
+ aspectRatio?: string;
182
97
  }
183
98
 
184
- /**
185
- * Supported analytics period tokens.
186
- * Typed union to prevent stringly-typed comparison elsewhere.
187
- */
188
99
  export type AnalyticsPeriod = '7d' | '30d' | '90d' | '1y' | (string & {});
189
100
 
190
- /**
191
- * Metric card props
192
- */
193
101
  export interface MetricCardProps {
194
- /** Metric data */
195
- metric: Metric;
196
- /** Card size variant */
197
- size?: "sm" | "md" | "lg";
198
- /** Show trend indicator */
199
- showTrend?: boolean;
200
- /** Show icon */
201
- showIcon?: boolean;
202
- /** Custom class name */
203
- className?: string;
204
- /** On click handler */
205
- onClick?: () => void;
102
+ metric: Metric;
103
+ size?: "sm" | "md" | "lg";
104
+ showTrend?: boolean;
105
+ showIcon?: boolean;
106
+ className?: string;
107
+ onClick?: () => void;
206
108
  }
207
109
 
208
- /**
209
- * Analytics card props
210
- */
211
110
  export interface AnalyticsCardProps {
212
- /** Card title */
213
- title?: string;
214
- /** Card description */
215
- description?: string;
216
- /** Chart configuration */
217
- chart?: ChartConfig;
218
- /** Metrics to display */
219
- metrics?: Metric[];
220
- /** Card size */
221
- size?: "sm" | "md" | "lg" | "full";
222
- /** Loading state */
223
- loading?: boolean;
224
- /** Error message */
225
- error?: string;
226
- /** Custom class name */
227
- className?: string;
228
- /** Children content */
229
- children?: React.ReactNode;
111
+ title?: string;
112
+ description?: string;
113
+ chart?: ChartConfig;
114
+ metrics?: Metric[];
115
+ size?: "sm" | "md" | "lg" | "full";
116
+ loading?: boolean;
117
+ error?: string;
118
+ className?: string;
119
+ children?: React.ReactNode;
230
120
  }
231
121
 
232
- /**
233
- * Analytics layout props
234
- */
235
122
  export interface AnalyticsLayoutProps {
236
- /** Analytics configuration */
237
- config?: AnalyticsConfig;
238
- /** Page title */
239
- title?: string;
240
- /** Page description */
241
- description?: string;
242
- /** Metrics data */
243
- metrics?: Metric[];
244
- /** Loading state */
245
- loading?: boolean;
246
- /** Current period */
247
- period?: AnalyticsPeriod;
248
- /** Period change handler */
249
- onPeriodChange?: (period: AnalyticsPeriod) => void;
250
- /** Date range selector */
251
- showDateRange?: boolean;
252
- /** Refresh button */
253
- showRefresh?: boolean;
254
- /** Export button */
255
- showExport?: boolean;
256
- /** Charts configuration */
257
- charts?: ChartConfig[];
258
- /** Refresh handler — required when showRefresh is true */
259
- onRefresh?: () => void;
260
- /** Export handler — required when showExport is true */
261
- onExport?: () => void;
262
- /** Custom header content */
263
- headerContent?: React.ReactNode;
264
- /** Children content */
265
- children?: React.ReactNode;
123
+ config?: AnalyticsConfig;
124
+ title?: string;
125
+ description?: string;
126
+ metrics?: Metric[];
127
+ loading?: boolean;
128
+ period?: AnalyticsPeriod;
129
+ onPeriodChange?: (period: AnalyticsPeriod) => void;
130
+ showDateRange?: boolean;
131
+ showRefresh?: boolean;
132
+ showExport?: boolean;
133
+ charts?: ChartConfig[];
134
+ onRefresh?: () => void;
135
+ onExport?: () => void;
136
+ headerContent?: React.ReactNode;
137
+ children?: React.ReactNode;
266
138
  }
267
139
 
268
- /**
269
- * Date range preset
270
- */
271
140
  export interface DateRangePreset {
272
- /** Preset label */
273
- label: string;
274
- /** Preset value */
275
- value: string;
276
- /** Number of days */
277
- days: number;
278
- /** Range start (ISO yyyy-mm-dd), resolved at creation time */
279
- from?: string;
280
- /** Range end (ISO yyyy-mm-dd), resolved at creation time */
281
- to?: string;
141
+ label: string;
142
+ value: string;
143
+ days: number;
144
+ from?: string;
145
+ to?: string;
282
146
  }
283
147
 
284
- /**
285
- * Date range value
286
- */
287
148
  export interface DateRangeValue {
288
- /** Start date */
289
- from: string;
290
- /** End date */
291
- to: string;
292
- /** Preset label */
293
- preset?: string;
149
+ from: string;
150
+ to: string;
151
+ preset?: string;
294
152
  }
295
153
 
296
- /**
297
- * Export format
298
- */
299
154
  export type ExportFormat = "csv" | "json" | "xlsx" | "pdf";
300
155
 
301
- /**
302
- * Analytics export options
303
- */
304
156
  export interface AnalyticsExportOptions {
305
- /** Export format */
306
- format: ExportFormat;
307
- /** Include charts */
308
- includeCharts?: boolean;
309
- /** Include metrics */
310
- includeMetrics?: boolean;
311
- /** Date range */
312
- dateRange?: DateRangeValue;
313
- /** Filename */
314
- filename?: string;
157
+ format: ExportFormat;
158
+ includeCharts?: boolean;
159
+ includeMetrics?: boolean;
160
+ dateRange?: DateRangeValue;
161
+ filename?: string;
315
162
  }
316
163
 
317
- /**
318
- * Analytics configuration
319
- */
320
164
  export interface AnalyticsConfig {
321
- /** Brand/application name */
322
- brandName: string;
323
- /** Default period selection */
324
- defaultPeriod?: string;
325
- /** Available period options */
326
- availablePeriods?: string[];
327
- /** Show export button */
328
- showExport?: boolean;
329
- /** Show refresh button */
330
- showRefresh?: boolean;
331
- /** Enable real-time updates */
332
- enableRealTime?: boolean;
333
- /** Metrics configuration */
334
- metrics?: MetricConfig[];
165
+ brandName: string;
166
+ defaultPeriod?: string;
167
+ availablePeriods?: string[];
168
+ showExport?: boolean;
169
+ showRefresh?: boolean;
170
+ enableRealTime?: boolean;
171
+ metrics?: MetricConfig[];
335
172
  }
336
173
 
337
- /**
338
- * Metric configuration
339
- */
340
174
  export interface MetricConfig {
341
- /** Metric identifier */
342
- id: string;
343
- /** Metric name */
344
- name: string;
345
- /** Unit type */
346
- unit?: string;
347
- /** Icon identifier */
348
- icon?: string;
175
+ id: string;
176
+ name: string;
177
+ unit?: string;
178
+ icon?: string;
349
179
  }
350
180
 
@@ -1,9 +1,3 @@
1
- /**
2
- * Analytics Types
3
- *
4
- * Export all analytics-related types
5
- */
6
-
7
1
  export type {
8
2
  Metric,
9
3
  TimeSeriesData,
@@ -1,7 +1,3 @@
1
- /**
2
- * Tests for pure analytics utility functions.
3
- */
4
-
5
1
  import { describe, it, expect } from "vitest";
6
2
  import {
7
3
  formatNumber,
@@ -53,9 +49,7 @@ describe("formatCurrency", () => {
53
49
  });
54
50
 
55
51
  it("honors the locale parameter", () => {
56
- // Signature is (value, currency, decimals, locale); the assertions
57
- // expect 2 decimal places, which "en-US"/"de-DE" format as ,50 / ,50.
58
- expect(formatCurrency(1234.5, "USD", 2, "en-US")).toBe("$1,234.50");
52
+ expect(formatCurrency(1234.5, "USD", 2, "en-US")).toBe("$1,234.50");
59
53
  expect(formatCurrency(1234.5, "EUR", 2, "de-DE")).toContain("1.234,50");
60
54
  });
61
55
  });
@@ -128,8 +122,7 @@ describe("detectOutliers", () => {
128
122
  });
129
123
 
130
124
  it("returns indices of values beyond 2 standard deviations", () => {
131
- // mean ≈ 16.7, population stdev ≈ 14.9 → only 50 exceeds 2σ.
132
- expect(detectOutliers([10, 10, 10, 10, 10, 50])).toEqual([5]);
125
+ expect(detectOutliers([10, 10, 10, 10, 10, 50])).toEqual([5]);
133
126
  });
134
127
 
135
128
  it("returns no indices for a uniform series", () => {
@@ -1,20 +1,7 @@
1
- /**
2
- * Analytics Utilities
3
- *
4
- * Helper functions for analytics operations
5
- */
6
-
7
1
  import type { TimeSeriesData } from "../types/analytics";
8
2
 
9
3
  import type { Metric, KPIData, DateRangePreset } from "../types/analytics";
10
4
 
11
- /**
12
- * Format number with K/M/B suffixes
13
- *
14
- * @param num - Number to format
15
- * @param decimals - Number of decimal places (default: 1)
16
- * @returns Formatted string
17
- */
18
5
  export function formatNumber(num: number, decimals: number = 1): string {
19
6
  if (num >= 1_000_000_000) {
20
7
  return (num / 1_000_000_000).toFixed(decimals) + "B";
@@ -25,17 +12,9 @@ export function formatNumber(num: number, decimals: number = 1): string {
25
12
  if (num >= 1_000) {
26
13
  return (num / 1_000).toFixed(decimals) + "K";
27
14
  }
28
- // Whole numbers stay whole ("999", not "999.0")
29
- return Number.isInteger(num) ? num.toString() : num.toFixed(decimals);
15
+ return Number.isInteger(num) ? num.toString() : num.toFixed(decimals);
30
16
  }
31
17
 
32
- /**
33
- * Format percentage
34
- *
35
- * @param value - Value to format as percentage
36
- * @param decimals - Number of decimal places (default: 1)
37
- * @returns Formatted string with % suffix
38
- */
39
18
  export function formatPercentage(value: number, decimals: number = 1): string {
40
19
  return `${value.toFixed(decimals)}%`;
41
20
  }
@@ -1,9 +1,3 @@
1
- /**
2
- * Analytics Utilities
3
- *
4
- * Export all analytics utilities
5
- */
6
-
7
1
  export {
8
2
  formatNumber,
9
3
  formatPercentage,
@@ -1,12 +1,5 @@
1
- /**
2
- * Calendar Configuration
3
- */
4
-
5
1
  import type { CalendarConfig } from './types/calendar.types';
6
2
 
7
- /**
8
- * Default calendar configuration
9
- */
10
3
  export const DEFAULT_CALENDAR_CONFIG: CalendarConfig = {
11
4
  defaultView: 'month',
12
5
  showWeekends: true,
@@ -1,5 +1 @@
1
- /**
2
- * Calendar Hooks Index
3
- */
4
-
5
1
  export * from './useCalendar';
@@ -1,12 +1,3 @@
1
- /**
2
- * useCalendar
3
- *
4
- * React hook for the calendar domain. Delegates persistence
5
- * to the injected `CalendarService`, guards refreshes with a
6
- * request id so a stale response can never overwrite a newer one,
7
- * and returns a clean discriminated CRUD contract.
8
- */
9
-
10
1
  import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
11
2
  import type {
12
3
  CalendarConfig,
@@ -20,14 +11,10 @@ import type { ICalendarService } from '../types/calendar.types';
20
11
  type CalendarView = 'month' | 'week' | 'day' | 'timeline';
21
12
 
22
13
  export interface UseCalendarOptions {
23
- /** Calendar configuration overrides */
24
- config?: Partial<CalendarConfig>;
25
- /** User ID (required to fetch items) */
26
- userId: string;
27
- /** Error callback — receives the original Error */
28
- onError?: (error: Error) => void;
29
- /** Override the default service (useful for tests) */
30
- service?: ICalendarService;
14
+ config?: Partial<CalendarConfig>;
15
+ userId: string;
16
+ onError?: (error: Error) => void;
17
+ service?: ICalendarService;
31
18
  }
32
19
 
33
20
  export interface UseCalendarReturn {
@@ -77,17 +64,12 @@ export function useCalendar(options: UseCalendarOptions): UseCalendarReturn {
77
64
  const [selectedDate, setSelectedDate] = useState(() => new Date());
78
65
  const [filter, setFilterState] = useState<CalendarFilter>({});
79
66
 
80
- // Keep the latest onError in a ref so refresh identity stays stable
81
- // when consumers pass a fresh closure each render.
82
- const onErrorRef = useRef(onError);
67
+ const onErrorRef = useRef(onError);
83
68
  useEffect(() => {
84
69
  onErrorRef.current = onError;
85
70
  }, [onError]);
86
71
 
87
- // Guards against out-of-order responses: only the most recent
88
- // refresh may commit state (e.g. user changes the filter while a
89
- // previous fetch is still resolving).
90
- const requestIdRef = useRef(0);
72
+ const requestIdRef = useRef(0);
91
73
 
92
74
  const refresh = useCallback(async () => {
93
75
  if (!userId) {
@@ -178,9 +160,7 @@ export function useCalendar(options: UseCalendarOptions): UseCalendarReturn {
178
160
  setFilterState((prev) => ({ ...prev, ...updates }));
179
161
  }, []);
180
162
 
181
- // Single source of truth for filtering (shared with the service layer)
182
- // so client-side refiltering can never drift from server-side semantics.
183
- const filteredItems = useMemo(
163
+ const filteredItems = useMemo(
184
164
  () => applyCalendarFilter(items, filter),
185
165
  [items, filter],
186
166
  );
@@ -1,7 +1,3 @@
1
- /**
2
- * Calendar Domain Index
3
- */
4
-
5
1
  export * from './types/calendar.types';
6
2
  export * from './config';
7
3
  export * from './services';
@@ -1,13 +1,3 @@
1
- /**
2
- * Calendar Service
3
- *
4
- * Camp-agnostic calendar service for managing content items.
5
- * Persistence is injected via the `ICalendarDatabase` seam — the
6
- * package ships no Firebase (or any other) backend. Use
7
- * `createInMemoryCalendarDatabase()` for demos and tests, or adapt
8
- * your own backend to the interface.
9
- */
10
-
11
1
  import type {
12
2
  ContentItem,
13
3
  CalendarFilter,
@@ -16,10 +6,6 @@ import type {
16
6
  ICalendarService,
17
7
  } from '../types/calendar.types';
18
8
 
19
- /**
20
- * Database interface for calendar operations
21
- * Implementations can provide different backends
22
- */
23
9
  export interface ICalendarDatabase {
24
10
  getItems(userId: string): Promise<ContentItem[]>;
25
11
  getItemById(id: string): Promise<ContentItem | null>;
@@ -28,9 +14,6 @@ export interface ICalendarDatabase {
28
14
  deleteItem(id: string): Promise<void>;
29
15
  }
30
16
 
31
- /**
32
- * Resolve scheduled_at to ISO string regardless of source type
33
- */
34
17
  const resolveScheduledAt = (value: string | Date | undefined): string => {
35
18
  if (value === undefined) {
36
19
  throw new Error('scheduled_at is required to create or update a content item');
@@ -39,10 +22,6 @@ const resolveScheduledAt = (value: string | Date | undefined): string => {
39
22
  return value.toISOString();
40
23
  };
41
24
 
42
- /**
43
- * In-memory calendar database — zero-dependency default for demos
44
- * and tests. Data lives per-instance for the lifetime of the page.
45
- */
46
25
  export const createInMemoryCalendarDatabase = (): ICalendarDatabase => {
47
26
  const items = new Map<string, ContentItem>();
48
27
 
@@ -1,5 +1 @@
1
- /**
2
- * Calendar Services Index
3
- */
4
-
5
1
  export * from './CalendarService';