| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- 'use client';
- import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
- import { authApi, usersApi, User } from './api';
- interface AcceptedProject {
- projectId: string;
- projectName: string;
- }
- interface AuthContextValue {
- user: User | null;
- token: string | null;
- loading: boolean;
- acceptedProjects: AcceptedProject[];
- justRegisteredName: string;
- clearAcceptedProjects: () => void;
- login: (email: string, password: string) => Promise<void>;
- register: (email: string, name: string, password: string, inviteToken?: string) => Promise<void>;
- logout: () => Promise<void>;
- refreshUser: () => Promise<void>;
- updateUserData: (data: Partial<User>) => void;
- }
- const AuthContext = createContext<AuthContextValue | null>(null);
- export function AuthProvider({ children }: { children: React.ReactNode }) {
- const [user, setUser] = useState<User | null>(null);
- const [token, setToken] = useState<string | null>(null);
- const [loading, setLoading] = useState(true);
- const [acceptedProjects, setAcceptedProjects] = useState<AcceptedProject[]>([]);
- const [justRegisteredName, setJustRegisteredName] = useState('');
- useEffect(() => {
- const savedToken = localStorage.getItem('vidreview_token');
- const savedUser = localStorage.getItem('vidreview_user');
- if (savedToken && savedUser) {
- setToken(savedToken);
- try {
- setUser(JSON.parse(savedUser));
- } catch {
- localStorage.removeItem('vidreview_token');
- localStorage.removeItem('vidreview_user');
- }
- }
- setLoading(false);
- }, []);
- const clearAcceptedProjects = useCallback(() => setAcceptedProjects([]), []);
- const login = useCallback(async (email: string, password: string) => {
- const { user: u, token: t, acceptedProjects: ap } = await authApi.login({ email, password });
- localStorage.setItem('vidreview_token', t);
- localStorage.setItem('vidreview_user', JSON.stringify(u));
- setToken(t);
- setUser(u);
- setAcceptedProjects(ap ?? []);
- }, []);
- const register = useCallback(async (email: string, name: string, password: string, inviteToken?: string) => {
- const result = await authApi.register({ email, name, password, inviteToken });
- const { user: u, token: t, acceptedProjects: ap, userName } = result;
- localStorage.setItem('vidreview_token', t);
- localStorage.setItem('vidreview_user', JSON.stringify(u));
- setToken(t);
- setUser(u);
- setAcceptedProjects(ap ?? []);
- setJustRegisteredName(userName ?? name);
- }, []);
- const logout = useCallback(async () => {
- try { await authApi.logout(); } catch { /* ignore */ }
- localStorage.removeItem('vidreview_token');
- localStorage.removeItem('vidreview_user');
- setToken(null);
- setUser(null);
- setAcceptedProjects([]);
- }, []);
- const refreshUser = useCallback(async () => {
- if (!token) return;
- try {
- const { user: u } = await usersApi.getMe(token);
- setUser(u);
- localStorage.setItem('vidreview_user', JSON.stringify(u));
- } catch { /* ignore refresh errors */ }
- }, [token]);
- const updateUserData = useCallback((data: Partial<User>) => {
- setUser(prev => {
- if (!prev) return prev;
- const updated = { ...prev, ...data };
- localStorage.setItem('vidreview_user', JSON.stringify(updated));
- return updated;
- });
- }, []);
- return (
- <AuthContext.Provider value={{ user, token, loading, acceptedProjects, justRegisteredName, clearAcceptedProjects, login, register, logout, refreshUser, updateUserData }}>
- {children}
- </AuthContext.Provider>
- );
- }
- export function useAuth() {
- const ctx = useContext(AuthContext);
- if (!ctx) throw new Error('useAuth must be used within AuthProvider');
- return ctx as Required<AuthContextValue>;
- }
|