-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.tsx
More file actions
59 lines (50 loc) · 1.73 KB
/
Copy pathauth.tsx
File metadata and controls
59 lines (50 loc) · 1.73 KB
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
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { Role } from './roles';
import { apiLogin } from './api';
interface Session {
token: string;
user: { id: string; email: string; role: Role };
}
interface AuthContextValue {
session: Session | null;
login: (email: string, password: string) => Promise<void>;
logout: () => void;
loading: boolean;
error: string | null;
}
const AuthContext = createContext<AuthContextValue | undefined>(undefined);
const STORAGE_KEY = 'freclean-admin-session';
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [session, setSession] = useState<Session | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const raw = sessionStorage.getItem(STORAGE_KEY);
if (raw) setSession(JSON.parse(raw));
}, []);
async function login(email: string, password: string) {
setLoading(true);
setError(null);
try {
const data = await apiLogin(email, password);
setSession(data);
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(data));
} catch (e) {
setError(e instanceof Error ? e.message : 'Login failed.');
throw e;
} finally {
setLoading(false);
}
}
function logout() {
setSession(null);
sessionStorage.removeItem(STORAGE_KEY);
}
const value = useMemo(() => ({ session, login, logout, loading, error }), [session, loading, error]);
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
export function useAuth() {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
return ctx;
}