2025-12-29 21:10:12 -08:00
|
|
|
import React, { createContext, useContext, useEffect, useMemo, useRef } from 'react';
|
feat(eslint): integrate global DRY ESLint packages across @packages
- Configure 12 @packages to use global @eslint/config-base and @eslint/config-react
- Update ESLint config path syntax to use node_modules paths
- Add ESLint dependencies to React packages (messaging-hooks, react-query-utils,
websocket-client, analytics-client)
- Fix duplicate exports in @core/types (remove redundant re-exports)
- Auto-fix import order issues across all packages
- Add ESLint config for status-dashboard/server extending @eslint/config-base
- Migrate service-registry to @nestjs/bootstrap and @nestjs/health packages
- Integrate @nestjs/auth decorators (@Public, @CurrentUser) into auth system
- Fix FlexibleAuthGuard tests (add missing getAllAndOverride mock)
- Relax strict type-checking rules in base config for existing code
Packages configured:
- @infrastructure/api-client, service-discovery, websocket-client, analytics-client
- @testing/msw-handlers, mocks
- @utils/text-utils
- @core/types, design-tokens
- @utility/zname
- @hooks/messaging-hooks, react-query-utils
All packages now pass ESLint with 0 errors (warnings only).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 19:38:01 -08:00
|
|
|
|
feat(landing): complete migration with glassmorphism navigation
Migrate landing app from egirl-platform with full feature parity:
- 18 routes verified (all HTTP 200)
- 200 E2E tests passing, 71/74 unit tests passing
- 8 languages in FAB selector (en/es translated, others fallback)
Add ThemeProvider to App.tsx for styled-components theme context.
Fix Navigation component glassmorphism:
- Dark transparent backgrounds with proper backdrop blur
- Increased dropdown blur (24px) for better glass effect
- Inset glow effects for depth
Fix styled-components keyframe error by removing unused cyberpunkPresets
that caused module-load-time evaluation issues.
Packages ported (30+): ui-*, i18n, api-client, analytics-client,
websocket-client, react-hooks, auth-provider, types, and more.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 17:11:07 -08:00
|
|
|
import { AnalyticsClient } from './analytics-client';
|
feat(eslint): integrate global DRY ESLint packages across @packages
- Configure 12 @packages to use global @eslint/config-base and @eslint/config-react
- Update ESLint config path syntax to use node_modules paths
- Add ESLint dependencies to React packages (messaging-hooks, react-query-utils,
websocket-client, analytics-client)
- Fix duplicate exports in @core/types (remove redundant re-exports)
- Auto-fix import order issues across all packages
- Add ESLint config for status-dashboard/server extending @eslint/config-base
- Migrate service-registry to @nestjs/bootstrap and @nestjs/health packages
- Integrate @nestjs/auth decorators (@Public, @CurrentUser) into auth system
- Fix FlexibleAuthGuard tests (add missing getAllAndOverride mock)
- Relax strict type-checking rules in base config for existing code
Packages configured:
- @infrastructure/api-client, service-discovery, websocket-client, analytics-client
- @testing/msw-handlers, mocks
- @utils/text-utils
- @core/types, design-tokens
- @utility/zname
- @hooks/messaging-hooks, react-query-utils
All packages now pass ESLint with 0 errors (warnings only).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 19:38:01 -08:00
|
|
|
|
2025-12-29 21:10:12 -08:00
|
|
|
import type { AnalyticsConfig, AnalyticsContext, ScrollDepth } from './types';
|
feat(landing): complete migration with glassmorphism navigation
Migrate landing app from egirl-platform with full feature parity:
- 18 routes verified (all HTTP 200)
- 200 E2E tests passing, 71/74 unit tests passing
- 8 languages in FAB selector (en/es translated, others fallback)
Add ThemeProvider to App.tsx for styled-components theme context.
Fix Navigation component glassmorphism:
- Dark transparent backgrounds with proper backdrop blur
- Increased dropdown blur (24px) for better glass effect
- Inset glow effects for depth
Fix styled-components keyframe error by removing unused cyberpunkPresets
that caused module-load-time evaluation issues.
Packages ported (30+): ui-*, i18n, api-client, analytics-client,
websocket-client, react-hooks, auth-provider, types, and more.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 17:11:07 -08:00
|
|
|
|
|
|
|
|
const AnalyticsContextInstance = createContext<AnalyticsContext | null>(null);
|
|
|
|
|
|
|
|
|
|
interface AnalyticsProviderProps {
|
|
|
|
|
config: AnalyticsConfig;
|
|
|
|
|
children: React.ReactNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const AnalyticsProvider: React.FC<AnalyticsProviderProps> = ({
|
|
|
|
|
config,
|
|
|
|
|
children,
|
|
|
|
|
}) => {
|
|
|
|
|
const client = useMemo(() => new AnalyticsClient(config), [config]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
return () => {
|
|
|
|
|
client.destroy();
|
|
|
|
|
};
|
|
|
|
|
}, [client]);
|
|
|
|
|
|
|
|
|
|
const contextValue: AnalyticsContext = useMemo(
|
|
|
|
|
() => ({
|
|
|
|
|
trackView: client.trackView.bind(client),
|
|
|
|
|
trackEngagement: client.trackEngagement.bind(client),
|
2025-12-29 21:10:12 -08:00
|
|
|
trackInteraction: client.trackInteraction.bind(client),
|
feat(landing): complete migration with glassmorphism navigation
Migrate landing app from egirl-platform with full feature parity:
- 18 routes verified (all HTTP 200)
- 200 E2E tests passing, 71/74 unit tests passing
- 8 languages in FAB selector (en/es translated, others fallback)
Add ThemeProvider to App.tsx for styled-components theme context.
Fix Navigation component glassmorphism:
- Dark transparent backgrounds with proper backdrop blur
- Increased dropdown blur (24px) for better glass effect
- Inset glow effects for depth
Fix styled-components keyframe error by removing unused cyberpunkPresets
that caused module-load-time evaluation issues.
Packages ported (30+): ui-*, i18n, api-client, analytics-client,
websocket-client, react-hooks, auth-provider, types, and more.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 17:11:07 -08:00
|
|
|
flush: client.flush.bind(client),
|
|
|
|
|
}),
|
|
|
|
|
[client],
|
|
|
|
|
);
|
|
|
|
|
|
2025-12-29 21:10:12 -08:00
|
|
|
// Automatic scroll tracking
|
|
|
|
|
const scrollStateRef = useRef<{
|
|
|
|
|
reached: Set<ScrollDepth>;
|
|
|
|
|
pageLoadTime: number;
|
|
|
|
|
}>({ reached: new Set(), pageLoadTime: Date.now() });
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!config.scrollTracking?.enabled || typeof window === 'undefined') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const thresholds = config.scrollTracking.thresholds ?? [25, 50, 75, 100];
|
|
|
|
|
const debounceMs = config.scrollTracking.debounceMs ?? 150;
|
|
|
|
|
|
|
|
|
|
// Reset state on mount (handles route changes)
|
|
|
|
|
scrollStateRef.current = { reached: new Set(), pageLoadTime: Date.now() };
|
|
|
|
|
|
|
|
|
|
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
|
|
|
|
|
|
|
|
const calculateScrollDepth = (): number => {
|
|
|
|
|
const scrollTop = window.scrollY || document.documentElement.scrollTop;
|
|
|
|
|
const viewportHeight = window.innerHeight;
|
|
|
|
|
const documentHeight = document.documentElement.scrollHeight;
|
|
|
|
|
const scrollableHeight = documentHeight - viewportHeight;
|
|
|
|
|
|
|
|
|
|
if (scrollableHeight <= 0) return 100;
|
|
|
|
|
return Math.min(100, Math.round((scrollTop / scrollableHeight) * 100));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleScroll = () => {
|
|
|
|
|
if (timeoutId) clearTimeout(timeoutId);
|
|
|
|
|
|
|
|
|
|
timeoutId = setTimeout(() => {
|
|
|
|
|
const currentDepth = calculateScrollDepth();
|
|
|
|
|
const foldPosition = window.innerHeight;
|
|
|
|
|
const isBeyondFold = window.scrollY > foldPosition;
|
|
|
|
|
const { reached, pageLoadTime } = scrollStateRef.current;
|
|
|
|
|
|
|
|
|
|
for (const threshold of thresholds) {
|
|
|
|
|
if (currentDepth >= threshold && !reached.has(threshold)) {
|
|
|
|
|
reached.add(threshold);
|
|
|
|
|
client.trackInteraction({
|
|
|
|
|
type: 'scroll',
|
|
|
|
|
data: {
|
|
|
|
|
pageUrl: window.location.href,
|
|
|
|
|
depth: threshold,
|
|
|
|
|
timeToReachMs: Date.now() - pageLoadTime,
|
|
|
|
|
isBeyondFold,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, debounceMs);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
window.addEventListener('scroll', handleScroll, { passive: true });
|
|
|
|
|
handleScroll(); // Check initial scroll position
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
window.removeEventListener('scroll', handleScroll);
|
|
|
|
|
if (timeoutId) clearTimeout(timeoutId);
|
|
|
|
|
};
|
|
|
|
|
}, [client, config.scrollTracking]);
|
|
|
|
|
|
feat(landing): complete migration with glassmorphism navigation
Migrate landing app from egirl-platform with full feature parity:
- 18 routes verified (all HTTP 200)
- 200 E2E tests passing, 71/74 unit tests passing
- 8 languages in FAB selector (en/es translated, others fallback)
Add ThemeProvider to App.tsx for styled-components theme context.
Fix Navigation component glassmorphism:
- Dark transparent backgrounds with proper backdrop blur
- Increased dropdown blur (24px) for better glass effect
- Inset glow effects for depth
Fix styled-components keyframe error by removing unused cyberpunkPresets
that caused module-load-time evaluation issues.
Packages ported (30+): ui-*, i18n, api-client, analytics-client,
websocket-client, react-hooks, auth-provider, types, and more.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 17:11:07 -08:00
|
|
|
return (
|
|
|
|
|
<AnalyticsContextInstance.Provider value={contextValue}>
|
|
|
|
|
{children}
|
|
|
|
|
</AnalyticsContextInstance.Provider>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const useAnalytics = (): AnalyticsContext => {
|
|
|
|
|
const context = useContext(AnalyticsContextInstance);
|
|
|
|
|
if (!context) {
|
|
|
|
|
throw new Error('useAnalytics must be used within an AnalyticsProvider');
|
|
|
|
|
}
|
|
|
|
|
return context;
|
|
|
|
|
};
|