Spaces:
Sleeping
Sleeping
Download src/context/AuthContext.tsx from viraj-421/InterviewAI: direct link, hf CLI and curl.
- Browser
- Download file 5.33 kB
-
https://huggingface.co/spaces/viraj-421/InterviewAI/resolve/main/src/context/AuthContext.tsx
- Command line
-
hf download hf://spaces/viraj-421/InterviewAI/src/context/AuthContext.tsx
-
curl -L -o AuthContext.tsx https://huggingface.co/spaces/viraj-421/InterviewAI/resolve/main/src/context/AuthContext.tsx
5.33 kB
| 'use client'; | |
| import React, { createContext, useContext, useState, useEffect, useCallback } from 'react'; | |
| export interface User { | |
| id: string; | |
| username: string; | |
| displayName: string; | |
| createdAt: number; | |
| } | |
| export interface ExamResult { | |
| id: string; | |
| userId: string; | |
| role: string; | |
| difficulty: string; | |
| score: number; | |
| maxScore: number; | |
| averageScore: number; | |
| totalQuestions: number; | |
| answeredQuestions: number; | |
| grade: string; | |
| passed: boolean; | |
| duration: number; // seconds | |
| completedAt: number; | |
| certificateId: string | null; | |
| } | |
| interface AuthContextType { | |
| user: User | null; | |
| isAuthenticated: boolean; | |
| examResults: ExamResult[]; | |
| login: (username: string, password: string) => { success: boolean; error?: string }; | |
| signup: (username: string, displayName: string, password: string) => { success: boolean; error?: string }; | |
| logout: () => void; | |
| addExamResult: (result: Omit<ExamResult, 'id' | 'userId' | 'certificateId'>) => ExamResult; | |
| } | |
| const AuthContext = createContext<AuthContextType | null>(null); | |
| function generateId(): string { | |
| return Date.now().toString(36) + Math.random().toString(36).substring(2); | |
| } | |
| export function AuthProvider({ children }: { children: React.ReactNode }) { | |
| const [user, setUser] = useState<User | null>(null); | |
| const [examResults, setExamResults] = useState<ExamResult[]>([]); | |
| // Load user from localStorage on mount | |
| useEffect(() => { | |
| const storedUser = localStorage.getItem('interviewai-user'); | |
| if (storedUser) { | |
| const parsed = JSON.parse(storedUser); | |
| setUser(parsed); | |
| // Load exam results for this user | |
| const results = localStorage.getItem(`interviewai-results-${parsed.id}`); | |
| if (results) setExamResults(JSON.parse(results)); | |
| } | |
| }, []); | |
| const login = useCallback((username: string, password: string) => { | |
| const usersData = localStorage.getItem('interviewai-users') || '{}'; | |
| const users = JSON.parse(usersData); | |
| const userKey = username.toLowerCase().trim(); | |
| if (!users[userKey]) { | |
| return { success: false, error: 'Account not found. Please sign up first.' }; | |
| } | |
| if (users[userKey].password !== password) { | |
| return { success: false, error: 'Incorrect password.' }; | |
| } | |
| const userData: User = { | |
| id: users[userKey].id, | |
| username: users[userKey].username, | |
| displayName: users[userKey].displayName, | |
| createdAt: users[userKey].createdAt, | |
| }; | |
| setUser(userData); | |
| localStorage.setItem('interviewai-user', JSON.stringify(userData)); | |
| // Load exam results | |
| const results = localStorage.getItem(`interviewai-results-${userData.id}`); | |
| if (results) setExamResults(JSON.parse(results)); | |
| return { success: true }; | |
| }, []); | |
| const signup = useCallback((username: string, displayName: string, password: string) => { | |
| if (username.trim().length < 3) { | |
| return { success: false, error: 'Username must be at least 3 characters.' }; | |
| } | |
| if (password.length < 4) { | |
| return { success: false, error: 'Password must be at least 4 characters.' }; | |
| } | |
| if (!displayName.trim()) { | |
| return { success: false, error: 'Please enter your full name.' }; | |
| } | |
| const usersData = localStorage.getItem('interviewai-users') || '{}'; | |
| const users = JSON.parse(usersData); | |
| const userKey = username.toLowerCase().trim(); | |
| if (users[userKey]) { | |
| return { success: false, error: 'Username already exists. Please choose another.' }; | |
| } | |
| const newUser = { | |
| id: generateId(), | |
| username: username.trim(), | |
| displayName: displayName.trim(), | |
| password: password, | |
| createdAt: Date.now(), | |
| }; | |
| users[userKey] = newUser; | |
| localStorage.setItem('interviewai-users', JSON.stringify(users)); | |
| const userData: User = { | |
| id: newUser.id, | |
| username: newUser.username, | |
| displayName: newUser.displayName, | |
| createdAt: newUser.createdAt, | |
| }; | |
| setUser(userData); | |
| localStorage.setItem('interviewai-user', JSON.stringify(userData)); | |
| setExamResults([]); | |
| return { success: true }; | |
| }, []); | |
| const logout = useCallback(() => { | |
| setUser(null); | |
| setExamResults([]); | |
| localStorage.removeItem('interviewai-user'); | |
| }, []); | |
| const addExamResult = useCallback((result: Omit<ExamResult, 'id' | 'userId' | 'certificateId'>) => { | |
| if (!user) throw new Error('Must be logged in'); | |
| const passed = result.averageScore >= 5; // Pass threshold: 50% | |
| const certificateId = passed ? `CERT-${generateId().toUpperCase()}` : null; | |
| const newResult: ExamResult = { | |
| ...result, | |
| id: generateId(), | |
| userId: user.id, | |
| passed, | |
| certificateId, | |
| }; | |
| const updated = [...examResults, newResult]; | |
| setExamResults(updated); | |
| localStorage.setItem(`interviewai-results-${user.id}`, JSON.stringify(updated)); | |
| return newResult; | |
| }, [user, examResults]); | |
| return ( | |
| <AuthContext.Provider | |
| value={{ | |
| user, | |
| isAuthenticated: !!user, | |
| examResults, | |
| login, | |
| signup, | |
| logout, | |
| addExamResult, | |
| }} | |
| > | |
| {children} | |
| </AuthContext.Provider> | |
| ); | |
| } | |
| export function useAuth() { | |
| const context = useContext(AuthContext); | |
| if (!context) { | |
| throw new Error('useAuth must be used within AuthProvider'); | |
| } | |
| return context; | |
| } | |