import { createContext, useContext, useState, useEffect, useCallback } from "react"; import { jpost } from "../api"; const AuthContext = createContext(null); export function AuthProvider({ children }) { const [user, setUser] = useState(() => localStorage.getItem("tnt_user") || ""); const [authorized, setAuthorized] = useState(() => localStorage.getItem("tnt_auth") === "true"); const [uid, setUid] = useState(() => localStorage.getItem("tnt_uid") || ""); useEffect(() => { localStorage.setItem("tnt_user", user); localStorage.setItem("tnt_auth", authorized ? "true" : ""); // Mã U00N dùng làm user_id trong log (ngắn, ổn định). Thiếu mã -> để rỗng, // track.js tự lùi về tên đăng nhập. localStorage.setItem("tnt_uid", uid || ""); }, [user, authorized, uid]); const login = useCallback(async (username) => { try { const data = await jpost("/api/auth/login", { username: username.trim() }); if (data.authorized) { setUser(username.trim()); setUid(data.code || ""); setAuthorized(true); return { ok: true }; } setUser(""); setAuthorized(false); // `denied` = máy chủ trả lời rành mạch "tài khoản này chưa được cấp quyền". // Phân biệt với trường hợp máy chủ trục trặc ở catch bên dưới — hai thứ // này cần hai câu khác nhau, và chỉ cái đầu mới nên gửi yêu cầu cấp quyền. return { ok: false, denied: true, error: "Bạn chưa được cấp quyền truy cập. Liên hệ quản trị viên." }; } catch (e) { return { ok: false, error: e.message }; } }, []); const logout = useCallback(() => { setUser(""); setUid(""); setAuthorized(false); }, []); return ( {children} ); } export function useAuth() { const ctx = useContext(AuthContext); if (!ctx) throw new Error("useAuth must be inside AuthProvider"); return ctx; }