@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.
- package/README.md +47 -73
- package/package.json +5 -9
- package/src/config/DashboardConfig.ts +19 -68
- package/src/domains/analytics/components/index.ts +0 -6
- package/src/domains/analytics/hooks/index.ts +0 -6
- package/src/domains/analytics/hooks/useAnalytics.ts +2 -20
- package/src/domains/analytics/index.ts +0 -10
- package/src/domains/analytics/services/AnalyticsEngineService.ts +7 -74
- package/src/domains/analytics/services/PerformanceService.ts +27 -138
- package/src/domains/analytics/services/index.ts +0 -4
- package/src/domains/analytics/types/analytics.ts +100 -270
- package/src/domains/analytics/types/index.ts +0 -6
- package/src/domains/analytics/utils/analytics.test.ts +2 -9
- package/src/domains/analytics/utils/analytics.ts +1 -22
- package/src/domains/analytics/utils/index.ts +0 -6
- package/src/domains/calendar/config.ts +0 -7
- package/src/domains/calendar/hooks/index.ts +0 -4
- package/src/domains/calendar/hooks/useCalendar.ts +7 -27
- package/src/domains/calendar/index.ts +0 -4
- package/src/domains/calendar/services/CalendarService.ts +0 -21
- package/src/domains/calendar/services/index.ts +0 -4
- package/src/domains/calendar/types/calendar.types.ts +9 -53
- package/src/domains/calendar/utils/contentItemMapper.test.ts +0 -4
- package/src/domains/calendar/utils/contentItemMapper.ts +0 -31
- package/src/domains/calendar/utils/index.ts +0 -26
- package/src/domains/layouts/components/index.ts +0 -4
- package/src/domains/layouts/hooks/dashboard.ts +0 -21
- package/src/domains/layouts/hooks/index.ts +0 -4
- package/src/domains/layouts/index.ts +0 -6
- package/src/domains/layouts/theme/default.ts +0 -12
- package/src/domains/layouts/theme/index.ts +0 -4
- package/src/domains/layouts/theme/presets.ts +0 -9
- package/src/domains/layouts/theme/utils.ts +0 -15
- package/src/domains/layouts/types/index.ts +0 -4
- package/src/domains/layouts/types/layout.ts +18 -56
- package/src/domains/layouts/types/notification.ts +4 -17
- package/src/domains/layouts/types/sidebar.ts +8 -28
- package/src/domains/layouts/types/theme.ts +23 -59
- package/src/domains/layouts/types/user.ts +9 -30
- package/src/domains/layouts/utils/dashboard.ts +4 -48
- package/src/domains/layouts/utils/index.ts +0 -4
- package/src/domains/modules/build.tsx +2 -16
- package/src/domains/modules/types.ts +8 -23
- package/src/domains/onboarding/calc/calc.test.ts +1 -9
- package/src/domains/onboarding/calc/card-stack-motion-curve.ts +0 -6
- package/src/domains/onboarding/calc/count-with-locale.ts +0 -8
- package/src/domains/onboarding/calc/duration-equal-split.ts +0 -12
- package/src/domains/onboarding/calc/elapsed-millis.ts +0 -6
- package/src/domains/onboarding/calc/progress-percentage.ts +1 -11
- package/src/domains/onboarding/calc/slider-value-bounds.ts +1 -11
- package/src/domains/onboarding/calc/step-index-clamp.ts +0 -9
- package/src/domains/onboarding/calc/swipe-gesture-curve.ts +0 -13
- package/src/domains/onboarding/components/{shared/AnimationWrapper.tsx → AnimationWrapper.tsx} +0 -4
- package/src/domains/onboarding/components/{shared/OnboardingErrorBoundary.tsx → OnboardingErrorBoundary.tsx} +7 -27
- package/src/domains/onboarding/components/OnboardingFlow.test.tsx +8 -30
- package/src/domains/onboarding/components/OnboardingFlow.tsx +13 -61
- package/src/domains/onboarding/components/OnboardingIntl.tsx +1 -11
- package/src/domains/onboarding/components/PrimaryButton.tsx +40 -0
- package/src/domains/onboarding/components/ProgressBar.tsx +32 -0
- package/src/domains/onboarding/components/QuestionWrapper.tsx +28 -0
- package/src/domains/onboarding/components/ScreenContainer.tsx +19 -0
- package/src/domains/onboarding/components/{shared/SwipeCard.test.tsx → SwipeCard.test.tsx} +1 -3
- package/src/domains/onboarding/components/{shared/SwipeCard.tsx → SwipeCard.tsx} +10 -28
- package/src/domains/onboarding/components/renderBundledIcon.tsx +7 -0
- package/src/domains/onboarding/components/screens/AccountGateScreen.tsx +7 -17
- package/src/domains/onboarding/components/screens/AppDemoScreen.tsx +4 -10
- package/src/domains/onboarding/components/screens/ComparisonScreen.tsx +12 -22
- package/src/domains/onboarding/components/screens/GoalQuestionScreen.tsx +9 -6
- package/src/domains/onboarding/components/screens/PainPointsScreen.tsx +10 -10
- package/src/domains/onboarding/components/screens/PaywallScreen.tsx +22 -38
- package/src/domains/onboarding/components/screens/PermissionPrimingScreen.tsx +14 -29
- package/src/domains/onboarding/components/screens/PersonalizedSolutionScreen.tsx +10 -23
- package/src/domains/onboarding/components/screens/PreferencesScreen.tsx +13 -27
- package/src/domains/onboarding/components/screens/ProcessingScreen.tsx +11 -27
- package/src/domains/onboarding/components/screens/SocialProofScreen.tsx +22 -51
- package/src/domains/onboarding/components/screens/TinderCardsScreen.tsx +13 -30
- package/src/domains/onboarding/components/screens/ValueDeliveryScreen.tsx +13 -29
- package/src/domains/onboarding/components/screens/WelcomeScreen.tsx +12 -32
- package/src/domains/onboarding/{components/hooks → hooks}/useOnboardingAnalytics.test.tsx +1 -1
- package/src/domains/onboarding/{components/hooks → hooks}/useOnboardingAnalytics.ts +3 -16
- package/src/domains/onboarding/{components/hooks → hooks}/useOnboardingProgress.test.tsx +2 -2
- package/src/domains/onboarding/{components/hooks → hooks}/useOnboardingProgress.ts +10 -21
- package/src/domains/onboarding/{components/hooks → hooks}/usePermissionPriming.ts +3 -10
- package/src/domains/onboarding/{components/hooks → hooks}/useReducedMotion.ts +0 -5
- package/src/domains/onboarding/index.ts +16 -45
- package/src/domains/onboarding/predicates/has-handler.ts +0 -4
- package/src/domains/onboarding/predicates/icon-name-resolves.ts +1 -17
- package/src/domains/onboarding/predicates/permission-granted.ts +0 -5
- package/src/domains/onboarding/predicates/permission-supports.ts +1 -11
- package/src/domains/onboarding/predicates/predicates.test.ts +6 -20
- package/src/domains/onboarding/predicates/screen-emits-data.ts +0 -4
- package/src/domains/onboarding/predicates/storage-available.ts +0 -8
- package/src/domains/onboarding/templates/TemplateDemoFallback.tsx +19 -39
- package/src/domains/onboarding/templates/art-onboarding.ts +1 -11
- package/src/domains/onboarding/templates/health-onboarding.ts +0 -5
- package/src/domains/onboarding/templates/platform-onboarding.ts +0 -9
- package/src/domains/onboarding/templates/video-onboarding.ts +0 -5
- package/src/domains/onboarding/test/setup.ts +1 -8
- package/src/domains/onboarding/types/config.ts +7 -18
- package/src/domains/onboarding/types/labels.ts +25 -59
- package/src/domains/onboarding/types/screens.ts +3 -11
- package/src/domains/onboarding/utils/analytics-dispatch.ts +2 -21
- package/src/domains/onboarding/utils/default-storage-key.ts +0 -1
- package/src/domains/onboarding/utils/index.ts +0 -1
- package/src/domains/onboarding/utils/local-storage-bridge.ts +1 -21
- package/src/domains/onboarding/utils/permission-bridge.ts +0 -8
- package/src/domains/onboarding/validation/flow-structure-check.ts +0 -6
- package/src/domains/onboarding/validation/permission-status-check.ts +0 -5
- package/src/domains/onboarding/validation/screen-config-check.ts +0 -5
- package/src/domains/onboarding/validation/stored-progress-check.ts +1 -10
- package/src/domains/onboarding/validation/validation.test.ts +1 -6
- package/src/domains/permissions/hasPermission.ts +0 -8
- package/src/domains/permissions/types.ts +0 -20
- package/src/domains/settings/components/index.ts +0 -4
- package/src/domains/settings/hooks/index.ts +0 -4
- package/src/domains/settings/hooks/useSettings.ts +1 -26
- package/src/domains/settings/index.ts +0 -6
- package/src/domains/settings/types/index.ts +0 -4
- package/src/domains/settings/types/settings.ts +23 -67
- package/src/domains/settings/utils/index.ts +0 -4
- package/src/domains/settings/utils/settings.ts +0 -45
- package/src/styles/dashboard.css +818 -1
- package/src/domains/onboarding/components/shared/OptionCard.tsx +0 -73
- package/src/domains/onboarding/components/shared/PrimaryButton.tsx +0 -58
- package/src/domains/onboarding/components/shared/ProgressBar.tsx +0 -51
- package/src/domains/onboarding/components/shared/QuestionWrapper.tsx +0 -36
- package/src/domains/onboarding/components/shared/ScreenContainer.tsx +0 -29
- package/src/domains/onboarding/components/shared/index.ts +0 -16
- package/src/domains/onboarding/components/shared/renderBundledIcon.tsx +0 -20
- package/src/domains/onboarding/onboarding.css +0 -1
- package/src/domains/onboarding/theme/cn.ts +0 -10
- package/src/domains/onboarding/theme/index.css +0 -131
- package/src/domains/onboarding/theme/index.ts +0 -12
- package/src/domains/onboarding/theme/tokens.ts +0 -122
- /package/src/domains/onboarding/{components/hooks → hooks}/index.ts +0 -0
package/README.md
CHANGED
|
@@ -1,32 +1,14 @@
|
|
|
1
1
|
# @umituz/web-dashboard
|
|
2
2
|
|
|
3
|
-
Installable app skeleton for SaaS dashboards: layouts,
|
|
4
|
-
|
|
5
|
-
an independent entry point — import only what your app uses. UI
|
|
6
|
-
design tokens come from [@umituz/web-design-system](https://github.com/umituz/web-design-system);
|
|
3
|
+
Installable app skeleton for SaaS dashboards: layouts, analytics, a content
|
|
4
|
+
calendar, a product onboarding flow, and a permissions/module registry. Every
|
|
5
|
+
domain is an independent entry point — import only what your app uses. UI
|
|
6
|
+
atoms and design tokens come from [@umituz/web-design-system](https://github.com/umituz/web-design-system);
|
|
7
7
|
translations from [@umituz/web-localization](https://github.com/umituz/web-localization).
|
|
8
8
|
|
|
9
9
|
The package is **source-distributed** (published as raw TypeScript in `src/`).
|
|
10
10
|
Your bundler compiles it alongside your app; no prebuilt bundle ships.
|
|
11
11
|
|
|
12
|
-
## What changed in v5 (major)
|
|
13
|
-
|
|
14
|
-
- **No more local primitives.** The `./primitives` entry point is gone;
|
|
15
|
-
components import `@umituz/web-design-system` directly. Hosts that need
|
|
16
|
-
`Button`/`Input`/`Checkbox`/`Skeleton`/`cn` import them from the design
|
|
17
|
-
system.
|
|
18
|
-
- **No more `--u-*` token layer.** `tokens.css` is deleted. The `udb-*`
|
|
19
|
-
stylesheet consumes the design-system variables (`--color-*`, `--radius-*`,
|
|
20
|
-
`--font-*`, `--shadow-*`) directly; dashboard-specific knobs (typography
|
|
21
|
-
scale, sidebar geometry) are `--udb-*` custom properties defined in
|
|
22
|
-
`styles.css` itself.
|
|
23
|
-
- **No more local i18n copy.** The `./i18n` entry point is gone; `useT` now
|
|
24
|
-
comes from `@umituz/web-localization/react` (`I18nProvider` there replaces
|
|
25
|
-
`DashboardI18nProvider`, same `t` signature).
|
|
26
|
-
- **No bundled dark preset.** Dark mode follows the design system: hosts set
|
|
27
|
-
dark values on the DS variables under `[data-theme="dark"]` / `.dark`
|
|
28
|
-
(see the design system's `bridge.css` contract).
|
|
29
|
-
|
|
30
12
|
## Installation
|
|
31
13
|
|
|
32
14
|
```bash
|
|
@@ -34,9 +16,10 @@ npm install @umituz/web-dashboard
|
|
|
34
16
|
import "@umituz/web-dashboard/styles.css";
|
|
35
17
|
```
|
|
36
18
|
|
|
37
|
-
Peers: `react` + `react-dom` (^18 or ^19)
|
|
38
|
-
|
|
39
|
-
`
|
|
19
|
+
Peers: `react` + `react-dom` (^18 or ^19), `react-router-dom` (^6 or ^7),
|
|
20
|
+
and `framer-motion` (^12, onboarding animations only).
|
|
21
|
+
Runtime deps: `@umituz/web-design-system` (^4.9),
|
|
22
|
+
`@umituz/web-localization`, `lucide-react`.
|
|
40
23
|
|
|
41
24
|
### Tailwind hosts
|
|
42
25
|
|
|
@@ -51,18 +34,20 @@ reads its variables, so theming has exactly one path: set the DS variables.
|
|
|
51
34
|
Vanilla-CSS hosts define `--app-*` slots via the design system's `bridge.css`;
|
|
52
35
|
Tailwind hosts override `--color-*` from their own `@theme`. Dashboard-only
|
|
53
36
|
knobs (`--udb-font-size-*`, `--udb-space-*`, `--udb-sidebar-*`,
|
|
54
|
-
`--udb-header-height`, `--udb-border-strong`, `--udb-radius-pill`) can be
|
|
37
|
+
`--udb-header-height`, `--udb-border-strong`, `--udb-radius-pill`) can be
|
|
38
|
+
overridden anywhere in the cascade. Dark mode follows the design system:
|
|
39
|
+
hosts set dark values on the DS variables under `[data-theme="dark"]` /
|
|
40
|
+
`.dark`.
|
|
55
41
|
|
|
56
42
|
## Entry points
|
|
57
43
|
|
|
58
44
|
```bash
|
|
59
|
-
@umituz/web-dashboard/styles.css # component stylesheet (udb-* BEM)
|
|
45
|
+
@umituz/web-dashboard/styles.css # component stylesheet (udb-* BEM, incl. udb-onb-*)
|
|
60
46
|
@umituz/web-dashboard/permissions # PermissionMatrix, hasPermission, guards
|
|
61
|
-
@umituz/web-dashboard/session # AuthAdapter, SessionProvider, OrgSwitcher, DemoLogin
|
|
62
47
|
@umituz/web-dashboard/modules # DashboardModule, buildRoutes, buildNav
|
|
63
48
|
@umituz/web-dashboard/layouts # DashboardLayout, DashboardSidebar, DashboardHeader
|
|
64
49
|
@umituz/web-dashboard/settings # SettingsLayout, admin skeletons (users, matrix, audit)
|
|
65
|
-
@umituz/web-dashboard/
|
|
50
|
+
@umituz/web-dashboard/onboarding # OnboardingFlow + 14 screens, persistence, analytics
|
|
66
51
|
@umituz/web-dashboard/analytics # AnalyticsLayout, SVG AnalyticsChart, services
|
|
67
52
|
@umituz/web-dashboard/calendar # useCalendar, CalendarService (injected DB)
|
|
68
53
|
@umituz/web-dashboard/config # dashboard config helpers
|
|
@@ -70,28 +55,23 @@ knobs (`--udb-font-size-*`, `--udb-space-*`, `--udb-sidebar-*`,
|
|
|
70
55
|
```
|
|
71
56
|
|
|
72
57
|
Each domain also exposes `components`, `hooks`, `utils`, `types`
|
|
73
|
-
sub-entries (and `services` for analytics/calendar). The
|
|
74
|
-
(`permissions`, `
|
|
75
|
-
re-exported from the root, so router-less hosts never pull router code
|
|
76
|
-
transitively.
|
|
58
|
+
sub-entries (and `services` for analytics/calendar). The modules
|
|
59
|
+
(`permissions`, `modules`, `onboarding`) are **deep-entry only** — they are
|
|
60
|
+
not re-exported from the root, so router-less hosts never pull router code
|
|
61
|
+
in transitively.
|
|
77
62
|
|
|
78
63
|
## The composition
|
|
79
64
|
|
|
80
|
-
A host app assembles the skeleton from
|
|
65
|
+
A host app assembles the skeleton from its seams:
|
|
81
66
|
|
|
82
67
|
```tsx
|
|
83
68
|
import { I18nProvider } from "@umituz/web-localization/react";
|
|
84
|
-
import { SessionProvider, createInMemoryAuthAdapter } from "@umituz/web-dashboard/session";
|
|
85
69
|
import { PermissionsProvider } from "@umituz/web-dashboard/permissions";
|
|
86
70
|
|
|
87
|
-
const adapter = createInMemoryAuthAdapter({ users: DEMO_USERS });
|
|
88
|
-
|
|
89
71
|
<I18nProvider t={i18n.t}>
|
|
90
|
-
<
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
</PermissionsProvider>
|
|
94
|
-
</SessionProvider>
|
|
72
|
+
<PermissionsProvider matrix={ROLE_PERMISSIONS} role={user?.role}>
|
|
73
|
+
<App />
|
|
74
|
+
</PermissionsProvider>
|
|
95
75
|
</I18nProvider>
|
|
96
76
|
```
|
|
97
77
|
|
|
@@ -128,12 +108,31 @@ Matrix grants are `"*"` (everything), `"sales.*"` (module wildcard) or exact
|
|
|
128
108
|
strings. `<RequirePermission permission>` guards pages (lock screen
|
|
129
109
|
fallback); `<Can>` is its inline twin.
|
|
130
110
|
|
|
131
|
-
###
|
|
111
|
+
### Onboarding
|
|
112
|
+
|
|
113
|
+
`OnboardingFlow` runs a declarative screen list (`welcome`, `goal-question`,
|
|
114
|
+
`pain-points`, `social-proof`, `tinder-cards`, `personalized-solution`,
|
|
115
|
+
`comparison`, `preferences`, `permission-priming`, `processing`,
|
|
116
|
+
`app-demo`, `value-delivery`, `account-gate`, `paywall`) with progress
|
|
117
|
+
persistence, resume, analytics events and an error boundary:
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
import { OnboardingFlow, healthOnboardingTemplate } from "@umituz/web-dashboard/onboarding";
|
|
121
|
+
|
|
122
|
+
<OnboardingIntlProvider labels={myLabels}>
|
|
123
|
+
<OnboardingFlow config={healthOnboardingTemplate({ onComplete })} />
|
|
124
|
+
</OnboardingIntlProvider>
|
|
125
|
+
```
|
|
132
126
|
|
|
133
|
-
|
|
134
|
-
`
|
|
135
|
-
|
|
136
|
-
|
|
127
|
+
Screen selection logic ships as pure functions (`calc`, `predicates`,
|
|
128
|
+
`validation` entry blocks), option/question UI as design-system molecules
|
|
129
|
+
(`OptionCard`) and atoms (`Button`, `Progress`, `Spinner`). Styles are the
|
|
130
|
+
`udb-onb-*` block inside `styles.css`; transitions use `framer-motion`.
|
|
131
|
+
Templates: `healthOnboardingTemplate`, `artOnboardingTemplate`,
|
|
132
|
+
`videoOnboardingTemplate`, `platformOnboardingTemplate` (plus
|
|
133
|
+
`withDefaultDemo` for demo fallbacks). Labels localize through
|
|
134
|
+
`OnboardingIntlProvider`; `defaultOnboardingLabels` lists every overridable
|
|
135
|
+
string.
|
|
137
136
|
|
|
138
137
|
### Calendar
|
|
139
138
|
|
|
@@ -167,22 +166,18 @@ import { I18nProvider } from "@umituz/web-localization/react";
|
|
|
167
166
|
|
|
168
167
|
Interpolation uses the standard `{{placeholder}}` syntax. Without a
|
|
169
168
|
provider, `useT()` falls back to `defaultT`, which humanizes keys
|
|
170
|
-
(`
|
|
169
|
+
(`analytics.chart.title` → "Chart title") so a bare install still renders
|
|
171
170
|
readably. The per-domain key catalogs are the string contract:
|
|
172
171
|
|
|
173
172
|
```ts
|
|
174
|
-
import { AUTH_KEYS } from "@umituz/web-dashboard/auth";
|
|
175
173
|
import { ANALYTICS_KEYS } from "@umituz/web-dashboard/analytics";
|
|
176
174
|
import { SETTINGS_ADMIN_KEYS } from "@umituz/web-dashboard/settings/utils";
|
|
177
175
|
import { PERMISSIONS_KEYS } from "@umituz/web-dashboard/permissions";
|
|
178
|
-
import { SESSION_KEYS } from "@umituz/web-dashboard/session";
|
|
179
176
|
```
|
|
180
177
|
|
|
181
178
|
## Platform compatibility
|
|
182
179
|
|
|
183
180
|
- React 18 and 19, react-router-dom 6 and 7
|
|
184
|
-
- `generateResetToken` requires `crypto.getRandomValues` (all modern browsers,
|
|
185
|
-
Node ≥ 19) and **throws** rather than falling back to an insecure PRNG
|
|
186
181
|
- Rendering targets the DOM; React Native is not supported
|
|
187
182
|
|
|
188
183
|
## Development
|
|
@@ -195,27 +190,6 @@ npm test # vitest unit tests (pure utils + module builders)
|
|
|
195
190
|
npm run test:watch
|
|
196
191
|
```
|
|
197
192
|
|
|
198
|
-
## Migration: 4.x → 5.0
|
|
199
|
-
|
|
200
|
-
1. `@umituz/web-dashboard/primitives` → import `Button`/`Input`/`Checkbox`/
|
|
201
|
-
`Skeleton` from `@umituz/web-design-system/atoms` and `cn` from
|
|
202
|
-
`@umituz/web-design-system/utils/cn`.
|
|
203
|
-
2. `@umituz/web-dashboard/i18n` → `DashboardI18nProvider` becomes
|
|
204
|
-
`I18nProvider` from `@umituz/web-localization/react`; `useT`, `defaultT`
|
|
205
|
-
and `TranslateFn` come from the same entry point.
|
|
206
|
-
3. `@umituz/web-dashboard/tokens.css` → drop the import; `styles.css` is the
|
|
207
|
-
only stylesheet. Migrate `--u-*` overrides to the DS variables
|
|
208
|
-
(`--u-color-primary` → `--color-primary`, `--u-color-surface` →
|
|
209
|
-
`--color-card`, `--u-color-bg` → `--color-background`, `--u-color-text` →
|
|
210
|
-
`--color-foreground`, `--u-color-muted` → `--color-muted-foreground`,
|
|
211
|
-
`--u-color-surface-muted` → `--color-muted`, `--u-color-danger` →
|
|
212
|
-
`--color-destructive`) and dashboard knobs to their `--udb-*` names
|
|
213
|
-
(`--u-font-size-*` → `--udb-font-size-*`, `--u-color-border-strong` →
|
|
214
|
-
`--udb-border-strong`, `--u-sidebar-*` → `--udb-sidebar-*`, `--u-space-*` →
|
|
215
|
-
`--udb-space-*`).
|
|
216
|
-
4. Dark mode: replace `data-udb-theme="dark"` with the design-system
|
|
217
|
-
convention (`[data-theme="dark"]` / `.dark` + dark DS variable values).
|
|
218
|
-
|
|
219
193
|
## License
|
|
220
194
|
|
|
221
195
|
MIT
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/web-dashboard",
|
|
3
|
-
"version": "6.
|
|
4
|
-
"description": "Installable app skeleton for the fleet — layouts, analytics (dependency-free SVG charts), calendar, onboarding flow, i18n via @umituz/web-localization, permissions/module registry; udb-* stylesheet on design-system tokens
|
|
3
|
+
"version": "6.2.0",
|
|
4
|
+
"description": "Installable app skeleton for the fleet — layouts, analytics (dependency-free SVG charts), calendar, onboarding flow, i18n via @umituz/web-localization, permissions/module registry; udb-* stylesheet on design-system tokens",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
7
7
|
"types": "./src/index.ts",
|
|
@@ -38,8 +38,7 @@
|
|
|
38
38
|
"./config": "./src/config/index.ts",
|
|
39
39
|
"./package.json": "./package.json",
|
|
40
40
|
"./charts": "./src/domains/charts/index.ts",
|
|
41
|
-
"./onboarding": "./src/domains/onboarding/index.ts"
|
|
42
|
-
"./onboarding.css": "./src/domains/onboarding/onboarding.css"
|
|
41
|
+
"./onboarding": "./src/domains/onboarding/index.ts"
|
|
43
42
|
},
|
|
44
43
|
"files": [
|
|
45
44
|
"src",
|
|
@@ -61,12 +60,9 @@
|
|
|
61
60
|
"framer-motion": "^12.0.0"
|
|
62
61
|
},
|
|
63
62
|
"dependencies": {
|
|
64
|
-
"@umituz/web-design-system": "^4.
|
|
63
|
+
"@umituz/web-design-system": "^4.9.0",
|
|
65
64
|
"lucide-react": "^0.577.0",
|
|
66
|
-
"@umituz/web-localization": "^1.2.1"
|
|
67
|
-
"@radix-ui/react-progress": "^1.1.7",
|
|
68
|
-
"clsx": "^2.1.1",
|
|
69
|
-
"tailwind-merge": "^3.5.0"
|
|
65
|
+
"@umituz/web-localization": "^1.2.1"
|
|
70
66
|
},
|
|
71
67
|
"devDependencies": {
|
|
72
68
|
"@types/node": "^22.20.5",
|
|
@@ -1,92 +1,45 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dashboard Configuration
|
|
3
|
-
* Config-based dashboard system
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
1
|
import type { ChartType } from '../domains/analytics/types/analytics';
|
|
7
2
|
|
|
8
|
-
/**
|
|
9
|
-
* Analytics service types
|
|
10
|
-
*/
|
|
11
3
|
export type AnalyticsServiceType = 'traffic' | 'cohort' | 'funnel' | 'growth' | 'performance';
|
|
12
4
|
|
|
13
|
-
/**
|
|
14
|
-
* Export format
|
|
15
|
-
*/
|
|
16
5
|
export type ExportFormat = 'pdf' | 'excel' | 'csv' | 'json';
|
|
17
6
|
|
|
18
|
-
/**
|
|
19
|
-
* Analytics configuration
|
|
20
|
-
*/
|
|
21
7
|
export interface AnalyticsConfig {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/** Real-time updates */
|
|
27
|
-
realtime?: boolean;
|
|
28
|
-
/** Export configuration */
|
|
29
|
-
export?: {
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
services?: AnalyticsServiceType[];
|
|
10
|
+
realtime?: boolean;
|
|
11
|
+
export?: {
|
|
30
12
|
enabled?: boolean;
|
|
31
13
|
formats?: ExportFormat[];
|
|
32
14
|
};
|
|
33
15
|
}
|
|
34
16
|
|
|
35
|
-
/**
|
|
36
|
-
* Data refresh configuration
|
|
37
|
-
*/
|
|
38
17
|
export interface DataConfig {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
cacheDuration?: number;
|
|
43
|
-
/** Retry attempts for failed requests */
|
|
44
|
-
retryAttempts?: number;
|
|
18
|
+
refreshInterval?: number;
|
|
19
|
+
cacheDuration?: number;
|
|
20
|
+
retryAttempts?: number;
|
|
45
21
|
}
|
|
46
22
|
|
|
47
|
-
/**
|
|
48
|
-
* Charts configuration
|
|
49
|
-
*/
|
|
50
23
|
export interface ChartsConfig {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
/** Enable animations */
|
|
56
|
-
animations?: boolean;
|
|
57
|
-
/** Color palette */
|
|
58
|
-
colors?: string[];
|
|
24
|
+
defaultType?: ChartType;
|
|
25
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
26
|
+
animations?: boolean;
|
|
27
|
+
colors?: string[];
|
|
59
28
|
}
|
|
60
29
|
|
|
61
|
-
/**
|
|
62
|
-
* Performance configuration
|
|
63
|
-
*/
|
|
64
30
|
export interface PerformanceConfig {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
virtualScrolling?: boolean;
|
|
69
|
-
/** Pagination size */
|
|
70
|
-
paginationSize?: number;
|
|
31
|
+
lazyLoad?: boolean;
|
|
32
|
+
virtualScrolling?: boolean;
|
|
33
|
+
paginationSize?: number;
|
|
71
34
|
}
|
|
72
35
|
|
|
73
|
-
/**
|
|
74
|
-
* Dashboard configuration
|
|
75
|
-
*/
|
|
76
36
|
export interface DashboardConfig {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
/** Charts configuration */
|
|
82
|
-
charts?: ChartsConfig;
|
|
83
|
-
/** Performance configuration */
|
|
84
|
-
performance?: PerformanceConfig;
|
|
37
|
+
analytics?: AnalyticsConfig;
|
|
38
|
+
data?: DataConfig;
|
|
39
|
+
charts?: ChartsConfig;
|
|
40
|
+
performance?: PerformanceConfig;
|
|
85
41
|
}
|
|
86
42
|
|
|
87
|
-
/**
|
|
88
|
-
* Default dashboard configuration
|
|
89
|
-
*/
|
|
90
43
|
export const DEFAULT_DASHBOARD_CONFIG: DashboardConfig = {
|
|
91
44
|
analytics: {
|
|
92
45
|
enabled: true,
|
|
@@ -98,9 +51,7 @@ export const DEFAULT_DASHBOARD_CONFIG: DashboardConfig = {
|
|
|
98
51
|
},
|
|
99
52
|
},
|
|
100
53
|
data: {
|
|
101
|
-
refreshInterval: 30000,
|
|
102
|
-
cacheDuration: 300000, // 5 minutes
|
|
103
|
-
retryAttempts: 3,
|
|
54
|
+
refreshInterval: 30000, cacheDuration: 300000, retryAttempts: 3,
|
|
104
55
|
},
|
|
105
56
|
charts: {
|
|
106
57
|
defaultType: 'line',
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useAnalytics
|
|
3
|
-
*
|
|
4
|
-
* Pure state + side-effect container. Mock data, commented-out
|
|
5
|
-
* fetch calls, and Math.random()-driven time series are gone.
|
|
6
|
-
* All persistence is delegated to the injected `apiClient`.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
1
|
import { useState, useCallback, useEffect, useMemo, useRef } from "react";
|
|
10
2
|
import type {
|
|
11
3
|
KPIs,
|
|
@@ -14,10 +6,6 @@ import type {
|
|
|
14
6
|
AnalyticsExportOptions,
|
|
15
7
|
} from "../types/analytics";
|
|
16
8
|
|
|
17
|
-
/**
|
|
18
|
-
* API client contract. Replace `loadAnalytics` with a real fetch wrapper
|
|
19
|
-
* and `exportAnalytics` with a server-side exporter.
|
|
20
|
-
*/
|
|
21
9
|
export interface AnalyticsApiClient {
|
|
22
10
|
loadAnalytics: (range: DateRangeValue) => Promise<AnalyticsDataPayload>;
|
|
23
11
|
exportAnalytics: (payload: AnalyticsDataPayload, options: AnalyticsExportOptions) => Promise<Blob>;
|
|
@@ -30,8 +18,7 @@ export interface AnalyticsDataPayload {
|
|
|
30
18
|
|
|
31
19
|
export interface UseAnalyticsOptions {
|
|
32
20
|
initialDateRange?: DateRangeValue;
|
|
33
|
-
|
|
34
|
-
refreshInterval?: number;
|
|
21
|
+
refreshInterval?: number;
|
|
35
22
|
apiClient: AnalyticsApiClient;
|
|
36
23
|
}
|
|
37
24
|
|
|
@@ -83,12 +70,7 @@ export function useAnalytics(options: UseAnalyticsOptions): UseAnalyticsReturn {
|
|
|
83
70
|
const [isLoading, setIsLoading] = useState(false);
|
|
84
71
|
const [error, setError] = useState<string | null>(null);
|
|
85
72
|
|
|
86
|
-
|
|
87
|
-
* Refs track the latest request so an in-flight call can't be
|
|
88
|
-
* overridden by a slower one (e.g. user changes the range while
|
|
89
|
-
* the previous fetch is still resolving).
|
|
90
|
-
*/
|
|
91
|
-
const requestIdRef = useRef(0);
|
|
73
|
+
const requestIdRef = useRef(0);
|
|
92
74
|
|
|
93
75
|
const refresh = useCallback(async () => {
|
|
94
76
|
const requestId = ++requestIdRef.current;
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Analytics Domain
|
|
3
|
-
*
|
|
4
|
-
* Main entry point for analytics domain
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
// Components
|
|
8
1
|
export {
|
|
9
2
|
MetricCard,
|
|
10
3
|
AnalyticsChart,
|
|
@@ -12,7 +5,6 @@ export {
|
|
|
12
5
|
AnalyticsLayout,
|
|
13
6
|
} from "./components";
|
|
14
7
|
|
|
15
|
-
// Hooks
|
|
16
8
|
export {
|
|
17
9
|
useAnalytics,
|
|
18
10
|
createStubAnalyticsApiClient,
|
|
@@ -24,7 +16,6 @@ export type {
|
|
|
24
16
|
UseAnalyticsReturn,
|
|
25
17
|
} from "./hooks";
|
|
26
18
|
|
|
27
|
-
// Utils
|
|
28
19
|
export {
|
|
29
20
|
formatNumber,
|
|
30
21
|
formatPercentage,
|
|
@@ -47,7 +38,6 @@ export {
|
|
|
47
38
|
ANALYTICS_KEYS,
|
|
48
39
|
} from "./utils";
|
|
49
40
|
|
|
50
|
-
// Types
|
|
51
41
|
export type {
|
|
52
42
|
Metric,
|
|
53
43
|
TimeSeriesData,
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Analytics Engine Service
|
|
3
|
-
*
|
|
4
|
-
* Advanced analytics operations including cohort analysis, funnel analysis,
|
|
5
|
-
* user segmentation, behavior prediction, and conversion path analysis.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
1
|
import type {
|
|
9
2
|
CohortAnalysis,
|
|
10
3
|
FunnelData,
|
|
@@ -59,10 +52,6 @@ export interface ActivityItem {
|
|
|
59
52
|
timestamp: string | Date;
|
|
60
53
|
}
|
|
61
54
|
|
|
62
|
-
/**
|
|
63
|
-
* Numeric metric keys supported by segment aggregation.
|
|
64
|
-
* Constrained to a string union to avoid `any` lookups at runtime.
|
|
65
|
-
*/
|
|
66
55
|
type NumericUserMetric =
|
|
67
56
|
| 'session_duration'
|
|
68
57
|
| 'pages_per_session'
|
|
@@ -79,37 +68,18 @@ const isUserMetric = (key: string): key is NumericUserMetric =>
|
|
|
79
68
|
'last_login_days',
|
|
80
69
|
].includes(key);
|
|
81
70
|
|
|
82
|
-
/**
|
|
83
|
-
* Safe numeric accessor for a UserData field.
|
|
84
|
-
* Returns 0 when the field is missing or not a number, instead of forcing a cast.
|
|
85
|
-
*/
|
|
86
71
|
const getNumericMetric = (user: UserData, key: NumericUserMetric): number => {
|
|
87
72
|
const value = user[key];
|
|
88
73
|
return typeof value === 'number' ? value : 0;
|
|
89
74
|
};
|
|
90
75
|
|
|
91
|
-
/**
|
|
92
|
-
* Segmentation thresholds (in days since last login).
|
|
93
|
-
*/
|
|
94
76
|
const SEGMENT_THRESHOLDS = {
|
|
95
77
|
activeDays: 7,
|
|
96
78
|
moderateDays: 30,
|
|
97
79
|
} as const;
|
|
98
80
|
|
|
99
|
-
/**
|
|
100
|
-
* Analytics Engine Service
|
|
101
|
-
*
|
|
102
|
-
* Pure-functional service for advanced analytics calculations.
|
|
103
|
-
* Stateless and testable: instantiate with `new AnalyticsEngineService()`.
|
|
104
|
-
*/
|
|
105
81
|
export class AnalyticsEngineService {
|
|
106
|
-
|
|
107
|
-
* Calculate cohort retention analysis
|
|
108
|
-
*
|
|
109
|
-
* @param data - User data with signup and activity dates
|
|
110
|
-
* @returns Cohort analysis with retention rates
|
|
111
|
-
*/
|
|
112
|
-
public calculateRetention(data: UserData[]): CohortAnalysis[] {
|
|
82
|
+
public calculateRetention(data: UserData[]): CohortAnalysis[] {
|
|
113
83
|
const cohorts: Map<string, UserData[]> = new Map();
|
|
114
84
|
|
|
115
85
|
data.forEach((user) => {
|
|
@@ -156,13 +126,7 @@ export class AnalyticsEngineService {
|
|
|
156
126
|
return cohortAnalysis;
|
|
157
127
|
}
|
|
158
128
|
|
|
159
|
-
|
|
160
|
-
* Analyze conversion paths
|
|
161
|
-
*
|
|
162
|
-
* @param data - Conversion data with paths and values
|
|
163
|
-
* @returns Conversion path analysis
|
|
164
|
-
*/
|
|
165
|
-
public analyzeConversionPaths(data: ConversionData[]): ConversionPath[] {
|
|
129
|
+
public analyzeConversionPaths(data: ConversionData[]): ConversionPath[] {
|
|
166
130
|
const paths: Map<string, { count: number; value: number }> = new Map();
|
|
167
131
|
let totalConversions = 0;
|
|
168
132
|
|
|
@@ -194,14 +158,7 @@ export class AnalyticsEngineService {
|
|
|
194
158
|
.sort((a, b) => b.conversions - a.conversions);
|
|
195
159
|
}
|
|
196
160
|
|
|
197
|
-
|
|
198
|
-
* Calculate funnel analysis
|
|
199
|
-
*
|
|
200
|
-
* @param data - Funnel data with step indicators
|
|
201
|
-
* @param steps - Funnel step names
|
|
202
|
-
* @returns Funnel analysis data
|
|
203
|
-
*/
|
|
204
|
-
public calculateFunnel(data: FunnelItem[], steps: string[]): FunnelData {
|
|
161
|
+
public calculateFunnel(data: FunnelItem[], steps: string[]): FunnelData {
|
|
205
162
|
let previousCount = data.length;
|
|
206
163
|
const funnelSteps = steps.map((step, index) => {
|
|
207
164
|
const stepCount = data.filter((item) => Boolean(item[step])).length;
|
|
@@ -233,13 +190,7 @@ export class AnalyticsEngineService {
|
|
|
233
190
|
};
|
|
234
191
|
}
|
|
235
192
|
|
|
236
|
-
|
|
237
|
-
* Generate activity heatmap
|
|
238
|
-
*
|
|
239
|
-
* @param data - Activity data with timestamps
|
|
240
|
-
* @returns Heatmap data by day and hour (Monday-first)
|
|
241
|
-
*/
|
|
242
|
-
public generateActivityHeatmap(data: ActivityItem[]): HeatmapData[] {
|
|
193
|
+
public generateActivityHeatmap(data: ActivityItem[]): HeatmapData[] {
|
|
243
194
|
const heatmap: HeatmapData[] = [];
|
|
244
195
|
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] as const;
|
|
245
196
|
|
|
@@ -247,8 +198,7 @@ export class AnalyticsEngineService {
|
|
|
247
198
|
for (let hour = 0; hour < 24; hour++) {
|
|
248
199
|
const count = data.filter((item) => {
|
|
249
200
|
const d = new Date(item.timestamp);
|
|
250
|
-
|
|
251
|
-
const mondayFirst = (d.getDay() + 6) % 7;
|
|
201
|
+
const mondayFirst = (d.getDay() + 6) % 7;
|
|
252
202
|
return mondayFirst === day && d.getHours() === hour;
|
|
253
203
|
}).length;
|
|
254
204
|
|
|
@@ -258,13 +208,7 @@ export class AnalyticsEngineService {
|
|
|
258
208
|
return heatmap;
|
|
259
209
|
}
|
|
260
210
|
|
|
261
|
-
|
|
262
|
-
* Segment users by behavior
|
|
263
|
-
*
|
|
264
|
-
* @param data - User data
|
|
265
|
-
* @returns User segments
|
|
266
|
-
*/
|
|
267
|
-
public segmentUsers(data: UserData[]): UserSegment[] {
|
|
211
|
+
public segmentUsers(data: UserData[]): UserSegment[] {
|
|
268
212
|
const defineSegment = (
|
|
269
213
|
name: string,
|
|
270
214
|
filter: (u: UserData) => boolean,
|
|
@@ -311,14 +255,7 @@ export class AnalyticsEngineService {
|
|
|
311
255
|
];
|
|
312
256
|
}
|
|
313
257
|
|
|
314
|
-
|
|
315
|
-
* Predict user behavior
|
|
316
|
-
*
|
|
317
|
-
* @param user - Target user
|
|
318
|
-
* @param historicalData - Historical user data
|
|
319
|
-
* @returns Behavior prediction
|
|
320
|
-
*/
|
|
321
|
-
public predictUserBehavior(
|
|
258
|
+
public predictUserBehavior(
|
|
322
259
|
user: UserData,
|
|
323
260
|
historicalData: UserData[],
|
|
324
261
|
): UserBehaviorPrediction {
|
|
@@ -360,8 +297,4 @@ export class AnalyticsEngineService {
|
|
|
360
297
|
}
|
|
361
298
|
}
|
|
362
299
|
|
|
363
|
-
/**
|
|
364
|
-
* Default instance for convenience.
|
|
365
|
-
* The class is also exported so consumers can instantiate a fresh one for tests.
|
|
366
|
-
*/
|
|
367
300
|
export const analyticsEngineService = new AnalyticsEngineService();
|