spb/vquant Public MIT
VibeQuant — AI-powered institutional-grade financial intelligence platform.
TypeScript 84.3%
Python 11.7%
JavaScript 1.6%
CSS 1.5%
HTML 0.7%
1/*2 * =============================================================================3 * VibeQuant (vquant) — AI-Powered Financial Intelligence Platform4 * -----------------------------------------------------------------------------5 * File: client/src/hooks/useAnalytics.ts6 *7 * Author: Simon-Pierre Boucher8 * Contact: contact@spboucher.ai9 * Website: https://www.spboucher.ai10 * Demo: https://www.vquant.ai11 * License: MIT (see LICENSE)12 *13 * Copyright © 2026 Simon-Pierre Boucher. All rights reserved.14 * =============================================================================15 */1617import { useEffect, useRef, useState } from 'react';1819/**20 * Hook to send heartbeat to analytics server21 * Tracks user activity and current generation status22 */23export function useAnalytics(status: 'idle' | 'generating' | 'error', currentQuery?: string) {24 const sessionIdRef = useRef<string>(getOrCreateSessionId());25 const lastStatusRef = useRef<string>(status);2627 useEffect(() => {28 const sendHeartbeat = async () => {29 try {30 await fetch('/api/analytics/heartbeat', {31 method: 'POST',32 headers: {33 'Content-Type': 'application/json',34 },35 body: JSON.stringify({36 sessionId: sessionIdRef.current,37 status,38 currentQuery: currentQuery || null,39 userId: null, // TODO: Get from auth context if logged in40 }),41 });42 } catch (error) {43 console.error('Failed to send heartbeat:', error);44 }45 };4647 // Send heartbeat immediately when status changes48 if (status !== lastStatusRef.current) {49 sendHeartbeat();50 lastStatusRef.current = status;51 }5253 // Send heartbeat every 30 seconds while generating54 if (status === 'generating') {55 const interval = setInterval(sendHeartbeat, 30000);56 return () => clearInterval(interval);57 }58 }, [status, currentQuery]);5960 return {61 sessionId: sessionIdRef.current,62 };63}6465/**66 * Get or create a unique session ID for this browser session67 */68function getOrCreateSessionId(): string {69 const key = 'vibequant_session_id';70 let sessionId = sessionStorage.getItem(key);7172 if (!sessionId) {73 sessionId = `session_${Date.now()}_${Math.random().toString(36).substring(7)}`;74 sessionStorage.setItem(key, sessionId);75 }7677 return sessionId;78}7980/**81 * Hook to fetch real-time analytics stats (public endpoint)82 */83export function useRealTimeStats(refreshInterval: number = 10000) {84 const [stats, setStats] = useState<any>(null);85 const [loading, setLoading] = useState(true);8687 useEffect(() => {88 const fetchStats = async () => {89 try {90 const response = await fetch('/api/analytics/real-time-stats');91 if (response.ok) {92 const data = await response.json();93 setStats(data);94 }95 } catch (error) {96 console.error('Failed to fetch real-time stats:', error);97 } finally {98 setLoading(false);99 }100 };101102 fetchStats();103 const interval = setInterval(fetchStats, refreshInterval);104105 return () => clearInterval(interval);106 }, [refreshInterval]);107108 return { stats, loading };109}110111