Phase 1 Complete by Claude Code

This commit is contained in:
2026-02-16 22:32:28 +02:00
parent 19c069949d
commit 5e2d4b6b1b
20 changed files with 692 additions and 32 deletions

View File

@@ -1 +1,70 @@
// TODO: JWT token state management
import { createContext, useContext, useState, useEffect } from "react";
import api from "../api/client";
const AuthContext = createContext(null);
export function AuthProvider({ children }) {
const [user, setUser] = useState(() => {
const stored = localStorage.getItem("user");
return stored ? JSON.parse(stored) : null;
});
const [loading, setLoading] = useState(true);
useEffect(() => {
const token = localStorage.getItem("access_token");
if (!token) {
setUser(null);
setLoading(false);
return;
}
try {
const payload = JSON.parse(atob(token.split(".")[1]));
if (payload.exp * 1000 < Date.now()) {
localStorage.removeItem("access_token");
localStorage.removeItem("user");
setUser(null);
}
} catch {
localStorage.removeItem("access_token");
localStorage.removeItem("user");
setUser(null);
}
setLoading(false);
}, []);
const login = async (email, password) => {
const data = await api.post("/auth/login", { email, password });
localStorage.setItem("access_token", data.access_token);
const userInfo = { name: data.name, role: data.role };
localStorage.setItem("user", JSON.stringify(userInfo));
setUser(userInfo);
return data;
};
const logout = () => {
localStorage.removeItem("access_token");
localStorage.removeItem("user");
setUser(null);
};
const hasRole = (...roles) => {
if (!user) return false;
if (user.role === "superadmin") return true;
return roles.includes(user.role);
};
return (
<AuthContext.Provider value={{ user, login, logout, loading, hasRole }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
}