"use client"; import { useEffect, useState, useCallback } from "react"; export interface UserProfile { id: string; name: string; email: string | null; phone: string | null; class: string; target_exam: "JEE_Main" | "JEE_Advanced" | "NEET"; medium: "English" | "Hindi" | "Bilingual"; school: string | null; city: string; state: string; tier: "Free" | "Pro" | "Al_Coach"; // Al_Coach in database schema streak_count: number; longest_streak: number; active_session_token?: string; created_at?: string; trial_end?: string; } export const DEFAULT_USER_ID = "b0e17378-864d-439e-8806-708dc48a891b"; // AI Coach export const DEMO_USERS = { FREE: { id: "11111111-1111-1111-1111-111111111111", label: "Amit Kumar (Free Tier)" }, PRO: { id: "22222222-2222-2222-2222-222222222222", label: "Priya Singh (Pro Tier)" }, AI_COACH: { id: DEFAULT_USER_ID, label: "Rahul Sharma (AI Coach)" } }; export function useActiveUser() { const [userId, setUserIdState] = useState(() => { if (typeof window !== "undefined") { return localStorage.getItem("activeUserId") || DEFAULT_USER_ID; } return DEFAULT_USER_ID; }); const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchUserProfile = useCallback(async (id: string, isPoll: boolean = false) => { if (!isPoll) setLoading(true); setError(null); try { const res = await fetch(`/api/users/${id}`); if (!res.ok) { console.error("Failed to fetch user profile, status:", res.status); setError("Failed to fetch user profile"); setUser(null); return; } const data = await res.json(); // Single Active Session Check if (typeof window !== 'undefined') { const localToken = localStorage.getItem("active_session_token"); if (data.active_session_token && localToken && data.active_session_token !== localToken) { localStorage.removeItem("activeUserId"); localStorage.removeItem("active_session_token"); alert("Your account was logged in from another device. You have been logged out."); window.location.href = "/"; return; } } setUser(data); } catch (err: any) { console.error("Error fetching active user profile:", err); setError(err.message || "Failed to load user"); } finally { if (!isPoll) setLoading(false); } }, []); useEffect(() => { if (typeof window !== "undefined") { const storedId = localStorage.getItem("activeUserId") || DEFAULT_USER_ID; setUserIdState(storedId); fetchUserProfile(storedId); } }, [fetchUserProfile]); useEffect(() => { if (typeof window === "undefined") return; const handleUpdate = () => fetchUserProfile(userId); window.addEventListener('pragativeer-user-updated', handleUpdate); // Poll every 10 seconds for session validity const interval = setInterval(() => { fetchUserProfile(userId, true); }, 10000); return () => { window.removeEventListener('pragativeer-user-updated', handleUpdate); clearInterval(interval); }; }, [userId, fetchUserProfile]); const switchUser = useCallback(async (newId: string) => { if (typeof window !== "undefined") { const sessionToken = crypto.randomUUID(); localStorage.setItem("active_session_token", sessionToken); try { await fetch(`/api/users/${newId}/session`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ session_token: sessionToken }) }); } catch (err) { console.error("Failed to set session", err); } localStorage.setItem("activeUserId", newId); setUserIdState(newId); window.location.reload(); } }, []); const hasAccessTo = useCallback((feature: string): boolean => { if (!user) return false; const tier = user.tier; // Core restrictions mapping based on PRD feature matrix switch (feature) { case "topic-wise-microtests-unlimited": case "weekly-test-series": case "full-length-mock-tests": case "previous-year-papers": case "detailed-performance-analytics": case "chapter-wise-progress-tracking": case "doubt-resolution-community": case "parent-dashboard": case "offline-mode": case "pdf-export": return tier === "Pro" || tier === "Al_Coach"; case "ai-mistake-tracking": case "spaced-repetition": case "personalized-study-plan": case "ai-tutor-chat": case "exam-readiness-score": case "exam-day-strategy": case "college-predictor": case "study-time-optimization": return tier === "Al_Coach"; default: // Free tier features: DPS (1/day), basic dashboard, basic streak tracking, leaderboard return true; } }, [user]); return { userId, user, loading, error, switchUser, hasAccessTo, refreshUser: async () => { await fetchUserProfile(userId); window.dispatchEvent(new CustomEvent('pragativeer-user-updated')); } }; }