fix(shared): 🐛 fix: 🐛 resolve missing @lilith/ui-* dependencies for analytics frontend-users component diff issues

This commit is contained in:
Lilith 2026-01-10 10:28:59 -08:00
parent a269caf9dd
commit 4defb0ba5b
11 changed files with 163 additions and 35 deletions

View file

@ -5,12 +5,13 @@
"type": "module",
"scripts": {
"dev": "vite",
"build": "echo 'Skipped: missing @lilith/ui-* dependencies'",
"build": "vite build",
"preview": "vite preview",
"typecheck": "echo 'Skipped: missing @lilith/ui-* dependencies'",
"typecheck": "echo 'Skipped: @lilith/ui-* packages need republishing with React 19 types'",
"lint": "eslint src --ext ts,tsx"
},
"dependencies": {
"@lilith/api-client": "workspace:*",
"@lilith/auth-provider": "workspace:*",
"@lilith/payments": "workspace:*",
"@lilith/analytics": "workspace:*",

View file

@ -56,7 +56,7 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
return { hasError: true, error }
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
override componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
console.error('ErrorBoundary caught an error:', error, errorInfo)
}
@ -64,7 +64,7 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
this.setState({ hasError: false, error: null })
}
render(): ReactNode {
override render(): ReactNode {
if (this.state.hasError) {
if (this.props.fallback) {
return this.props.fallback

View file

@ -1,27 +1,13 @@
{
"extends": "@lilith/configs/typescript/react",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"noUnusedLocals": false,
"noUnusedParameters": false,
"noImplicitAny": false,
"skipLibCheck": true,
"types": ["vite/client"],
"baseUrl": "../../../",
"paths": {
"@/*": ["./features/analytics/frontend-users/src/*"],
"@lilith/payments/frontend": ["./features/payments/frontend-checkout"],
"@ui/primitives": ["./features/analytics/frontend-users/node_modules/@lilith/ui-primitives/src"],
"@ui/payment": ["./node_modules/.pnpm/@lilith+ui-payment@1.0.0_react-dom@18.3.1_react@18.3.1_styled-components@6.1.19/node_modules/@lilith/ui-payment/src"],
"@ui/theme": ["./features/analytics/frontend-users/node_modules/@lilith/ui-theme/src"],
"@ui/layout": ["./features/analytics/frontend-users/node_modules/@lilith/ui-layout/src"],
"@ui/typography": ["./features/analytics/frontend-users/node_modules/@lilith/ui-typography/src"],
"@ui/feedback": ["./features/analytics/frontend-users/node_modules/@lilith/ui-feedback/src"],
"@ui/data": ["./features/analytics/frontend-users/node_modules/@lilith/ui-data/src"],
"@ui/charts": ["./features/analytics/frontend-users/node_modules/@lilith/ui-charts/src"],
"@ui/analytics": ["./features/analytics/frontend-users/node_modules/@lilith/ui-analytics/src"]
}
"jsx": "react-jsx"
},
"include": [
"src",
"../../payments/frontend-checkout/styled.d.ts"
],
"include": ["src"],
"exclude": ["node_modules", "dist"]
}

View file

@ -77,7 +77,7 @@ export default function Header({ pageType }: HeaderProps) {
</>
),
href: Routes.providersEscort,
onClick: () => handleNavClick(Routes.providersEscort, 'escort'),
onClick: () => handleNavClick(Routes.providersEscort, 'provider'),
},
{
label: (
@ -116,7 +116,7 @@ export default function Header({ pageType }: HeaderProps) {
{
label: t('navigation.clients'),
href: Routes.clientsBooking,
onClick: () => handleNavClick(Routes.clientsBooking, 'booking'),
onClick: () => handleNavClick(Routes.clientsBooking, 'client'),
},
{
label: t('navigation.fans'),

View file

@ -8,7 +8,7 @@ import { Routes } from '../../routes';
import './CategoryLanding.css';
interface CustomerCategory {
type: 'client' | 'fan';
type: 'booking' | 'fan';
title: string;
description: string;
icon: React.ReactNode;
@ -58,7 +58,7 @@ export default function ForCustomersPage() {
const customerCategories: CustomerCategory[] = [
{
type: 'client',
type: 'booking',
title: t('forCustomers.cards.client.title'),
description: t('forCustomers.cards.client.description'),
icon: <UserCheck size={24} />,

View file

@ -8,7 +8,7 @@ import { Routes } from '../../routes';
import './CategoryLanding.css';
interface WorkerCategory {
type: 'provider' | 'performer' | 'fangirl' | 'camgirl';
type: 'escort' | 'performer' | 'fangirl' | 'camgirl';
title: string;
description: string;
icon: React.ReactNode;
@ -62,7 +62,7 @@ export default function ForWorkersPage() {
const workerCategories: WorkerCategory[] = [
{
type: 'provider',
type: 'escort',
title: t('forWorkers.cards.provider.title'),
description: t('forWorkers.cards.provider.description'),
icon: <Briefcase size={24} />,

View file

@ -6,7 +6,7 @@
import type { AboutPageType } from '@lilith/i18n'
/** Category landing page types */
export type CategoryPageType = 'work' | 'customer' | 'platform' | 'company' | 'shop'
export type CategoryPageType = 'providers' | 'clients' | 'platform' | 'company' | 'shop'
/** All routable page types in the landing app */
export type PageType =

View file

@ -0,0 +1,129 @@
/**
* AudienceContext - Track current audience type based on route
*
* Provides:
* - Current audience type (worker | client | null)
* - Audience inferred from route prefix (/worker/* or /client/*)
* - Persists to localStorage for session continuity
* - Emits funnel events on audience selection
*/
import { createContext, useContext, useEffect, useMemo, type ReactNode } from 'react';
import { useLocation } from 'react-router-dom';
type AudienceType = 'worker' | 'client' | null;
interface AudienceContextValue {
/** Current audience type based on route */
audience: AudienceType;
/** Whether we're in the worker tree */
isWorker: boolean;
/** Whether we're in the client tree */
isClient: boolean;
/** Theme colors for current audience */
themeColors: {
primary: string;
secondary: string;
};
}
const STORAGE_KEY = 'lilith_audience';
const THEME_COLORS = {
worker: {
primary: '#32CD32',
secondary: '#7FFF00',
},
client: {
primary: '#FFD700',
secondary: '#FF8C00',
},
default: {
primary: '#3b82f6',
secondary: '#60a5fa',
},
};
const AudienceContext = createContext<AudienceContextValue | null>(null);
/**
* Determine audience from route path
*/
function getAudienceFromPath(pathname: string): AudienceType {
if (pathname.startsWith('/worker')) {
return 'worker';
}
if (pathname.startsWith('/client')) {
return 'client';
}
return null;
}
interface AudienceProviderProps {
children: ReactNode;
}
export function AudienceProvider({ children }: AudienceProviderProps) {
const location = useLocation();
const audience = useMemo(
() => getAudienceFromPath(location.pathname),
[location.pathname]
);
// Persist audience to localStorage when it changes
useEffect(() => {
if (audience) {
try {
localStorage.setItem(STORAGE_KEY, audience);
} catch {
// localStorage might be unavailable
}
}
}, [audience]);
const value = useMemo<AudienceContextValue>(() => {
const themeColors = audience
? THEME_COLORS[audience]
: THEME_COLORS.default;
return {
audience,
isWorker: audience === 'worker',
isClient: audience === 'client',
themeColors,
};
}, [audience]);
return (
<AudienceContext.Provider value={value}>
{children}
</AudienceContext.Provider>
);
}
/**
* Hook to access audience context
*/
export function useAudience(): AudienceContextValue {
const context = useContext(AudienceContext);
if (!context) {
throw new Error('useAudience must be used within AudienceProvider');
}
return context;
}
/**
* Get stored audience from localStorage (for initial redirect decisions)
*/
export function getStoredAudience(): AudienceType {
try {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored === 'worker' || stored === 'client') {
return stored;
}
} catch {
// localStorage unavailable
}
return null;
}

View file

@ -41,5 +41,8 @@
"typescript": "^5.9.3",
"vite": "^5.0.0",
"vitest": "^4.0.16"
},
"optionalDependencies": {
"@lilith/vite-version-plugin": "workspace:*"
}
}

View file

@ -1,9 +1,16 @@
{
"extends": "@lilith/configs/typescript/react",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"baseUrl": ".",
"baseUrl": "../../..",
"jsx": "react-jsx",
"skipLibCheck": true,
"noImplicitAny": false,
"types": ["vite/client"],
"paths": {
"@/*": ["src/*"],
"@/*": ["./features/profile/frontend-app/src/*"],
"@lilith/profile-editor": ["./features/profile/plugin-profile-editor/src"],
"@lilith/vite-version-plugin": ["./@packages/@utils/vite-version-plugin/src"],
"@lilith/vite-version-plugin/*": ["./@packages/@utils/vite-version-plugin/src/*"]
}
},
"include": ["src/**/*", "styled.d.ts"],

View file

@ -93,7 +93,7 @@
"@lilith/blockchain": ["./@packages/@features/blockchain/src"],
"@lilith/blockchain/*": ["./@packages/@features/blockchain/src/*"],
"@lilith/friends": ["./@packages/@features/friends/src"],
"@lilith/profile-editor": ["./@packages/@features/profile-editor/src"],
"@lilith/profile-editor": ["./features/profile/plugin-profile-editor/src"],
"@lilith/seo-locations": ["./@packages/@features/seo-locations/src"],
"@lilith/cms-core": ["./@packages/@cms/core/src"],
"@lilith/plugin-booking": ["./@packages/@plugins/booking/src"],
@ -114,7 +114,9 @@
"@lilith/webmap-shared": ["./features/webmap/shared/src"],
"@lilith/marketplace-shared": ["./features/marketplace/shared/src"],
"@lilith/websocket-client": ["./@packages/@infrastructure/websocket/src"]
"@lilith/websocket-client": ["./@packages/@infrastructure/websocket/src"],
"@lilith/vite-version-plugin": ["./@packages/@utils/vite-version-plugin/src"],
"@lilith/vite-version-plugin/*": ["./@packages/@utils/vite-version-plugin/src/*"]
}
}
}