File size: 3,645 Bytes
8314cf4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { useState, useEffect, createContext, useContext, ReactNode, useCallback } from "react";

export interface AuthUser {
  id: number;
  name: string;
  email: string;
  team: string;
  role: string;
  avatarColor: string;
  createdAt: string;
}

interface AuthContextType {
  user: AuthUser | null;
  token: string | null;
  login: (email: string, password: string) => Promise<void>;
  logout: () => void;
  isLoading: boolean;
  error: string | null;
  // Legacy compatibility for pages still using activeUser
  activeUser: AuthUser | null;
  setActiveUserId: (id: number | null) => void;
}

const AuthContext = createContext<AuthContextType>({
  user: null,
  token: null,
  login: async () => {},
  logout: () => {},
  isLoading: false,
  error: null,
  activeUser: null,
  setActiveUserId: () => {},
});

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<AuthUser | null>(null);
  const [token, setToken] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // On mount, restore from localStorage
  useEffect(() => {
    const savedToken = localStorage.getItem("teamtasker_token");
    const savedUser = localStorage.getItem("teamtasker_user");
    if (savedToken && savedUser) {
      try {
        const u = JSON.parse(savedUser) as AuthUser;
        setToken(savedToken);
        setUser(u);
        // Verify token is still valid
        fetch("/api/auth/me", {
          method: "POST",
          headers: { Authorization: `Bearer ${savedToken}` },
        }).then(async (res) => {
          if (res.ok) {
            const data = await res.json();
            setUser(data.user);
            localStorage.setItem("teamtasker_user", JSON.stringify(data.user));
          } else {
            // Token invalid, clear
            setToken(null);
            setUser(null);
            localStorage.removeItem("teamtasker_token");
            localStorage.removeItem("teamtasker_user");
          }
        }).finally(() => setIsLoading(false));
      } catch {
        setIsLoading(false);
      }
    } else {
      setIsLoading(false);
    }
  }, []);

  const login = useCallback(async (email: string, password: string) => {
    setIsLoading(true);
    setError(null);
    try {
      const res = await fetch("/api/auth/login", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email, password }),
      });
      const data = await res.json();
      if (!res.ok) {
        setError(data.error ?? "فشل تسجيل الدخول");
        return;
      }
      setToken(data.token);
      setUser(data.user);
      localStorage.setItem("teamtasker_token", data.token);
      localStorage.setItem("teamtasker_user", JSON.stringify(data.user));
    } catch {
      setError("خطأ في الاتصال. حاول مجدداً.");
    } finally {
      setIsLoading(false);
    }
  }, []);

  const logout = useCallback(() => {
    setToken(null);
    setUser(null);
    localStorage.removeItem("teamtasker_token");
    localStorage.removeItem("teamtasker_user");
  }, []);

  // Legacy shim — pages that still call setActiveUserId will do nothing harmful
  const setActiveUserId = useCallback((_id: number | null) => {}, []);

  return (
    <AuthContext.Provider value={{
      user,
      token,
      login,
      logout,
      isLoading,
      error,
      activeUser: user,
      setActiveUserId,
    }}>
      {children}
    </AuthContext.Provider>
  );
}

export const useAuth = () => useContext(AuthContext);