InterviewAI / src /context /AuthContext.tsx
viraj-421's picture
Initial commit: AI-Powered Mock Interview Platform with Auth, Certificates, and Timer
a0da743
Raw History Blame Contribute Delete
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;
}