Implement active user tiers, class-based Tailwind theme switcher, 3-tiled static dashboard layout, Minio object storage integration, school & state settings database sync, and streak wishes onboarding modal
This commit is contained in:
118
src/hooks/useActiveUser.ts
Normal file
118
src/hooks/useActiveUser.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
"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;
|
||||
}
|
||||
|
||||
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<string>(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
return localStorage.getItem("activeUserId") || DEFAULT_USER_ID;
|
||||
}
|
||||
return DEFAULT_USER_ID;
|
||||
});
|
||||
|
||||
const [user, setUser] = useState<UserProfile | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchUserProfile = useCallback(async (id: string) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const res = await fetch(`/api/users/${id}`);
|
||||
if (!res.ok) {
|
||||
throw new Error("Failed to fetch user profile");
|
||||
}
|
||||
const data = await res.json();
|
||||
setUser(data);
|
||||
} catch (err: any) {
|
||||
console.error("Error fetching active user profile:", err);
|
||||
setError(err.message || "Failed to load user");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
const storedId = localStorage.getItem("activeUserId") || DEFAULT_USER_ID;
|
||||
setUserIdState(storedId);
|
||||
fetchUserProfile(storedId);
|
||||
}
|
||||
}, [fetchUserProfile]);
|
||||
|
||||
const switchUser = useCallback((newId: string) => {
|
||||
if (typeof window !== "undefined") {
|
||||
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: () => fetchUserProfile(userId)
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user