@umituz/web-dashboard 5.0.1 → 6.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.
- package/package.json +19 -17
- package/src/domains/onboarding/calc/calc.test.ts +181 -0
- package/src/domains/onboarding/calc/card-stack-motion-curve.ts +33 -0
- package/src/domains/onboarding/calc/count-with-locale.ts +16 -0
- package/src/domains/onboarding/calc/duration-equal-split.ts +24 -0
- package/src/domains/onboarding/calc/elapsed-millis.ts +12 -0
- package/src/domains/onboarding/calc/index.ts +36 -0
- package/src/domains/onboarding/calc/progress-percentage.ts +37 -0
- package/src/domains/onboarding/calc/slider-value-bounds.ts +44 -0
- package/src/domains/onboarding/calc/step-index-clamp.ts +28 -0
- package/src/domains/onboarding/calc/swipe-gesture-curve.ts +67 -0
- package/src/domains/onboarding/components/OnboardingFlow.test.tsx +481 -0
- package/src/domains/onboarding/components/OnboardingFlow.tsx +361 -0
- package/src/domains/onboarding/components/OnboardingIntl.tsx +108 -0
- package/src/domains/onboarding/components/hooks/index.ts +7 -0
- package/src/domains/onboarding/components/hooks/useOnboardingAnalytics.test.tsx +74 -0
- package/src/domains/onboarding/components/hooks/useOnboardingAnalytics.ts +62 -0
- package/src/domains/onboarding/components/hooks/useOnboardingProgress.test.tsx +150 -0
- package/src/domains/onboarding/components/hooks/useOnboardingProgress.ts +260 -0
- package/src/domains/onboarding/components/hooks/usePermissionPriming.ts +52 -0
- package/src/domains/onboarding/components/hooks/useReducedMotion.ts +24 -0
- package/src/domains/onboarding/components/screens/AccountGateScreen.tsx +89 -0
- package/src/domains/onboarding/components/screens/AppDemoScreen.tsx +39 -0
- package/src/domains/onboarding/components/screens/ComparisonScreen.tsx +59 -0
- package/src/domains/onboarding/components/screens/GoalQuestionScreen.tsx +56 -0
- package/src/domains/onboarding/components/screens/PainPointsScreen.tsx +65 -0
- package/src/domains/onboarding/components/screens/PaywallScreen.tsx +138 -0
- package/src/domains/onboarding/components/screens/PermissionPrimingScreen.tsx +113 -0
- package/src/domains/onboarding/components/screens/PersonalizedSolutionScreen.tsx +53 -0
- package/src/domains/onboarding/components/screens/PreferencesScreen.tsx +194 -0
- package/src/domains/onboarding/components/screens/ProcessingScreen.tsx +79 -0
- package/src/domains/onboarding/components/screens/SocialProofScreen.tsx +116 -0
- package/src/domains/onboarding/components/screens/TinderCardsScreen.tsx +108 -0
- package/src/domains/onboarding/components/screens/ValueDeliveryScreen.tsx +85 -0
- package/src/domains/onboarding/components/screens/WelcomeScreen.tsx +52 -0
- package/src/domains/onboarding/components/screens/index.ts +28 -0
- package/src/domains/onboarding/components/shared/AnimationWrapper.tsx +73 -0
- package/src/domains/onboarding/components/shared/OnboardingErrorBoundary.tsx +81 -0
- package/src/domains/onboarding/components/shared/OptionCard.tsx +73 -0
- package/src/domains/onboarding/components/shared/PrimaryButton.tsx +58 -0
- package/src/domains/onboarding/components/shared/ProgressBar.tsx +51 -0
- package/src/domains/onboarding/components/shared/QuestionWrapper.tsx +36 -0
- package/src/domains/onboarding/components/shared/ScreenContainer.tsx +29 -0
- package/src/domains/onboarding/components/shared/SwipeCard.test.tsx +51 -0
- package/src/domains/onboarding/components/shared/SwipeCard.tsx +106 -0
- package/src/domains/onboarding/components/shared/index.ts +16 -0
- package/src/domains/onboarding/components/shared/renderBundledIcon.tsx +20 -0
- package/src/domains/onboarding/index.ts +182 -0
- package/src/domains/onboarding/onboarding.css +1 -0
- package/src/domains/onboarding/predicates/has-handler.ts +25 -0
- package/src/domains/onboarding/predicates/icon-name-resolves.ts +113 -0
- package/src/domains/onboarding/predicates/index.ts +26 -0
- package/src/domains/onboarding/predicates/permission-granted.ts +26 -0
- package/src/domains/onboarding/predicates/permission-supports.ts +66 -0
- package/src/domains/onboarding/predicates/predicates.test.ts +202 -0
- package/src/domains/onboarding/predicates/screen-emits-data.ts +17 -0
- package/src/domains/onboarding/predicates/storage-available.ts +22 -0
- package/src/domains/onboarding/templates/TemplateDemoFallback.tsx +112 -0
- package/src/domains/onboarding/templates/art-onboarding.ts +81 -0
- package/src/domains/onboarding/templates/health-onboarding.ts +97 -0
- package/src/domains/onboarding/templates/index.ts +6 -0
- package/src/domains/onboarding/templates/platform-onboarding.ts +210 -0
- package/src/domains/onboarding/templates/video-onboarding.ts +100 -0
- package/src/domains/onboarding/test/setup.ts +30 -0
- package/src/domains/onboarding/theme/cn.ts +10 -0
- package/src/domains/onboarding/theme/index.css +131 -0
- package/src/domains/onboarding/theme/index.ts +12 -0
- package/src/domains/onboarding/theme/tokens.ts +122 -0
- package/src/domains/onboarding/types/config.ts +68 -0
- package/src/domains/onboarding/types/index.ts +10 -0
- package/src/domains/onboarding/types/labels.ts +83 -0
- package/src/domains/onboarding/types/screens.ts +193 -0
- package/src/domains/onboarding/utils/analytics-dispatch.test.ts +93 -0
- package/src/domains/onboarding/utils/analytics-dispatch.ts +92 -0
- package/src/domains/onboarding/utils/default-storage-key.ts +2 -0
- package/src/domains/onboarding/utils/index.ts +13 -0
- package/src/domains/onboarding/utils/local-storage-bridge.test.ts +93 -0
- package/src/domains/onboarding/utils/local-storage-bridge.ts +104 -0
- package/src/domains/onboarding/utils/permission-bridge.test.ts +64 -0
- package/src/domains/onboarding/utils/permission-bridge.ts +95 -0
- package/src/domains/onboarding/validation/flow-structure-check.ts +28 -0
- package/src/domains/onboarding/validation/index.ts +9 -0
- package/src/domains/onboarding/validation/permission-status-check.ts +23 -0
- package/src/domains/onboarding/validation/screen-config-check.ts +105 -0
- package/src/domains/onboarding/validation/stored-progress-check.ts +68 -0
- package/src/domains/onboarding/validation/validation.test.ts +175 -0
- package/src/index.ts +0 -10
- package/src/styles/dashboard.contract.test.ts +1 -0
- package/src/styles/dashboard.css +0 -460
- package/src/domains/auth/components/AuthLayout.tsx +0 -99
- package/src/domains/auth/components/ForgotPasswordForm.tsx +0 -167
- package/src/domains/auth/components/LoginForm.tsx +0 -222
- package/src/domains/auth/components/RegisterForm.tsx +0 -281
- package/src/domains/auth/components/ResetPasswordForm.tsx +0 -173
- package/src/domains/auth/components/index.ts +0 -11
- package/src/domains/auth/components/shared/AuthErrorBanner.tsx +0 -25
- package/src/domains/auth/components/shared/EmailInput.tsx +0 -73
- package/src/domains/auth/components/shared/PasswordInput.tsx +0 -100
- package/src/domains/auth/components/shared/PasswordStrengthIndicator.tsx +0 -63
- package/src/domains/auth/components/shared/SocialLoginButtons.tsx +0 -44
- package/src/domains/auth/components/shared/SocialProviderIcons.tsx +0 -48
- package/src/domains/auth/components/shared/index.ts +0 -20
- package/src/domains/auth/hooks/index.ts +0 -8
- package/src/domains/auth/hooks/useAuth.ts +0 -230
- package/src/domains/auth/index.ts +0 -62
- package/src/domains/auth/types/auth.ts +0 -302
- package/src/domains/auth/types/index.ts +0 -25
- package/src/domains/auth/utils/auth.test.ts +0 -188
- package/src/domains/auth/utils/auth.ts +0 -221
- package/src/domains/auth/utils/i18nKeys.ts +0 -109
- package/src/domains/auth/utils/index.ts +0 -29
- package/src/domains/auth/utils/secureToken.ts +0 -33
- package/src/domains/auth/utils/validationKeys.ts +0 -23
- package/src/domains/session/DemoLogin.tsx +0 -42
- package/src/domains/session/OrgSwitcher.tsx +0 -102
- package/src/domains/session/SessionContext.tsx +0 -150
- package/src/domains/session/inMemoryAuthAdapter.ts +0 -53
- package/src/domains/session/index.ts +0 -18
- package/src/domains/session/types.ts +0 -47
- package/src/domains/session/utils/i18nKeys.ts +0 -12
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session context — user + active tenant state over an injected
|
|
3
|
-
* AuthAdapter. Restores the current user on mount, exposes
|
|
4
|
-
* login/logout/demoLogin, loads tenants for the user and keeps an
|
|
5
|
-
* `activeTenant` the OrgSwitcher drives via `switchTenant`.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
createContext,
|
|
10
|
-
useCallback,
|
|
11
|
-
useContext,
|
|
12
|
-
useEffect,
|
|
13
|
-
useMemo,
|
|
14
|
-
useState,
|
|
15
|
-
type ReactNode,
|
|
16
|
-
} from "react";
|
|
17
|
-
import type {
|
|
18
|
-
AuthAdapter,
|
|
19
|
-
LoginCredentials,
|
|
20
|
-
SessionStatus,
|
|
21
|
-
SessionUser,
|
|
22
|
-
Tenant,
|
|
23
|
-
} from "./types";
|
|
24
|
-
|
|
25
|
-
export interface SessionProviderProps {
|
|
26
|
-
adapter: AuthAdapter;
|
|
27
|
-
children: ReactNode;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
interface SessionContextValue {
|
|
31
|
-
user: SessionUser | null;
|
|
32
|
-
tenants: Tenant[];
|
|
33
|
-
activeTenant: Tenant | null;
|
|
34
|
-
status: SessionStatus;
|
|
35
|
-
login: (credentials: LoginCredentials) => Promise<SessionUser>;
|
|
36
|
-
logout: () => Promise<void>;
|
|
37
|
-
demoLogin: (userId: string) => Promise<SessionUser>;
|
|
38
|
-
switchTenant: (tenantId: string) => void;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const SessionContext = createContext<SessionContextValue | null>(null);
|
|
42
|
-
|
|
43
|
-
export const SessionProvider = ({ adapter, children }: SessionProviderProps) => {
|
|
44
|
-
const [user, setUser] = useState<SessionUser | null>(null);
|
|
45
|
-
const [tenants, setTenants] = useState<Tenant[]>([]);
|
|
46
|
-
const [activeTenantId, setActiveTenantId] = useState<string | null>(null);
|
|
47
|
-
const [status, setStatus] = useState<SessionStatus>("loading");
|
|
48
|
-
|
|
49
|
-
// Restore the session once on mount.
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
let cancelled = false;
|
|
52
|
-
adapter
|
|
53
|
-
.current()
|
|
54
|
-
.then((current) => {
|
|
55
|
-
if (cancelled) return;
|
|
56
|
-
setUser(current);
|
|
57
|
-
setStatus(current ? "authenticated" : "anonymous");
|
|
58
|
-
})
|
|
59
|
-
.catch(() => {
|
|
60
|
-
if (!cancelled) setStatus("anonymous");
|
|
61
|
-
});
|
|
62
|
-
return () => {
|
|
63
|
-
cancelled = true;
|
|
64
|
-
};
|
|
65
|
-
}, [adapter]);
|
|
66
|
-
|
|
67
|
-
// Load tenants whenever the authenticated user changes.
|
|
68
|
-
useEffect(() => {
|
|
69
|
-
if (!user || !adapter.listTenants) {
|
|
70
|
-
setTenants([]);
|
|
71
|
-
setActiveTenantId(null);
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
let cancelled = false;
|
|
75
|
-
adapter
|
|
76
|
-
.listTenants(user.id)
|
|
77
|
-
.then((list) => {
|
|
78
|
-
if (cancelled) return;
|
|
79
|
-
setTenants(list);
|
|
80
|
-
setActiveTenantId((prev) =>
|
|
81
|
-
prev && list.some((tenant) => tenant.id === prev) ? prev : (list[0]?.id ?? null),
|
|
82
|
-
);
|
|
83
|
-
})
|
|
84
|
-
.catch(() => {
|
|
85
|
-
if (!cancelled) setTenants([]);
|
|
86
|
-
});
|
|
87
|
-
return () => {
|
|
88
|
-
cancelled = true;
|
|
89
|
-
};
|
|
90
|
-
}, [adapter, user]);
|
|
91
|
-
|
|
92
|
-
const login = useCallback(
|
|
93
|
-
async (credentials: LoginCredentials) => {
|
|
94
|
-
const next = await adapter.login(credentials);
|
|
95
|
-
setUser(next);
|
|
96
|
-
setStatus("authenticated");
|
|
97
|
-
return next;
|
|
98
|
-
},
|
|
99
|
-
[adapter],
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
const logout = useCallback(async () => {
|
|
103
|
-
await adapter.logout();
|
|
104
|
-
setUser(null);
|
|
105
|
-
setStatus("anonymous");
|
|
106
|
-
}, [adapter]);
|
|
107
|
-
|
|
108
|
-
const demoLogin = useCallback(
|
|
109
|
-
async (userId: string) => {
|
|
110
|
-
if (!adapter.demoLogin) {
|
|
111
|
-
throw new Error("AuthAdapter does not support demoLogin");
|
|
112
|
-
}
|
|
113
|
-
const next = await adapter.demoLogin(userId);
|
|
114
|
-
setUser(next);
|
|
115
|
-
setStatus("authenticated");
|
|
116
|
-
return next;
|
|
117
|
-
},
|
|
118
|
-
[adapter],
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
const switchTenant = useCallback((tenantId: string) => {
|
|
122
|
-
setActiveTenantId(tenantId);
|
|
123
|
-
}, []);
|
|
124
|
-
|
|
125
|
-
const value = useMemo<SessionContextValue>(
|
|
126
|
-
() => ({
|
|
127
|
-
user,
|
|
128
|
-
tenants,
|
|
129
|
-
activeTenant: tenants.find((tenant) => tenant.id === activeTenantId) ?? null,
|
|
130
|
-
status,
|
|
131
|
-
login,
|
|
132
|
-
logout,
|
|
133
|
-
demoLogin,
|
|
134
|
-
switchTenant,
|
|
135
|
-
}),
|
|
136
|
-
[user, tenants, activeTenantId, status, login, logout, demoLogin, switchTenant],
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
return (
|
|
140
|
-
<SessionContext.Provider value={value}>{children}</SessionContext.Provider>
|
|
141
|
-
);
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
export const useSession = (): SessionContextValue => {
|
|
145
|
-
const context = useContext(SessionContext);
|
|
146
|
-
if (!context) {
|
|
147
|
-
throw new Error("useSession requires a <SessionProvider> ancestor");
|
|
148
|
-
}
|
|
149
|
-
return context;
|
|
150
|
-
};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* In-memory auth adapter — zero-dependency default for demos,
|
|
3
|
-
* Storybook-style setups and tests. Credentials are NOT checked
|
|
4
|
-
* (any password logs in); demo accounts log in by user id.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type {
|
|
8
|
-
AuthAdapter,
|
|
9
|
-
LoginCredentials,
|
|
10
|
-
SessionUser,
|
|
11
|
-
} from "./types";
|
|
12
|
-
|
|
13
|
-
export interface InMemoryAuthAdapterOptions {
|
|
14
|
-
/** Users available for login/demo. */
|
|
15
|
-
users: readonly SessionUser[];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const createInMemoryAuthAdapter = ({
|
|
19
|
-
users,
|
|
20
|
-
}: InMemoryAuthAdapterOptions): AuthAdapter => {
|
|
21
|
-
let currentUser: SessionUser | null = null;
|
|
22
|
-
|
|
23
|
-
const findByEmail = (email: string): SessionUser | undefined =>
|
|
24
|
-
users.find((user) => user.email === email);
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
async login({ email }: LoginCredentials): Promise<SessionUser> {
|
|
28
|
-
const user = findByEmail(email);
|
|
29
|
-
if (!user) {
|
|
30
|
-
throw new Error(`No user with email ${email}`);
|
|
31
|
-
}
|
|
32
|
-
currentUser = user;
|
|
33
|
-
return user;
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
async logout(): Promise<void> {
|
|
37
|
-
currentUser = null;
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
async current(): Promise<SessionUser | null> {
|
|
41
|
-
return currentUser;
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
async demoLogin(userId: string): Promise<SessionUser> {
|
|
45
|
-
const user = users.find((candidate) => candidate.id === userId);
|
|
46
|
-
if (!user) {
|
|
47
|
-
throw new Error(`No demo user with id ${userId}`);
|
|
48
|
-
}
|
|
49
|
-
currentUser = user;
|
|
50
|
-
return user;
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
SessionProvider,
|
|
3
|
-
useSession,
|
|
4
|
-
type SessionProviderProps,
|
|
5
|
-
} from "./SessionContext";
|
|
6
|
-
export { OrgSwitcher, type OrgSwitcherProps } from "./OrgSwitcher";
|
|
7
|
-
export { DemoLogin, type DemoLoginProps } from "./DemoLogin";
|
|
8
|
-
export { createInMemoryAuthAdapter, type InMemoryAuthAdapterOptions } from "./inMemoryAuthAdapter";
|
|
9
|
-
export {
|
|
10
|
-
SESSION_KEYS,
|
|
11
|
-
} from "./utils/i18nKeys";
|
|
12
|
-
export type {
|
|
13
|
-
AuthAdapter,
|
|
14
|
-
LoginCredentials,
|
|
15
|
-
SessionStatus,
|
|
16
|
-
SessionUser,
|
|
17
|
-
Tenant,
|
|
18
|
-
} from "./types";
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session model — the host-facing auth contract.
|
|
3
|
-
*
|
|
4
|
-
* The package performs no authentication itself; hosts adapt their
|
|
5
|
-
* provider (Firebase, Supabase, NEON-backed REST, mock...) to this
|
|
6
|
-
* interface and hand it to <SessionProvider>.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/** Authenticated user as the dashboard presents it. */
|
|
10
|
-
export interface SessionUser {
|
|
11
|
-
id: string;
|
|
12
|
-
name: string;
|
|
13
|
-
email: string;
|
|
14
|
-
/** Host role key — pairs with the permissions matrix. */
|
|
15
|
-
role: string;
|
|
16
|
-
avatarUrl?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** Tenant/organization the user may switch between. */
|
|
20
|
-
export interface Tenant {
|
|
21
|
-
id: string;
|
|
22
|
-
name: string;
|
|
23
|
-
/** Short initials for avatar-style rendering. */
|
|
24
|
-
initials?: string;
|
|
25
|
-
/** Optional plan badge (e.g. "starter" | "growth" | "enterprise"). */
|
|
26
|
-
plan?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface LoginCredentials {
|
|
30
|
-
email: string;
|
|
31
|
-
password: string;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Auth adapter seam. `login`/`logout`/`current` are required;
|
|
36
|
-
* `listTenants` and `demoLogin` power the multi-tenant switcher and
|
|
37
|
-
* one-click demo entry when the host supports them.
|
|
38
|
-
*/
|
|
39
|
-
export interface AuthAdapter {
|
|
40
|
-
login(credentials: LoginCredentials): Promise<SessionUser>;
|
|
41
|
-
logout(): Promise<void>;
|
|
42
|
-
current(): Promise<SessionUser | null>;
|
|
43
|
-
listTenants?(userId: string): Promise<Tenant[]>;
|
|
44
|
-
demoLogin?(userId: string): Promise<SessionUser>;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export type SessionStatus = "loading" | "authenticated" | "anonymous";
|