68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
"use client";
|
||
|
||
import { useState, useEffect, useCallback } from "react";
|
||
import { getStoredUser, getStoredToken } from "@/app/lib/pocketbase";
|
||
|
||
export interface AuthAndVipState {
|
||
user: { id: string; email: string } | null;
|
||
vip: boolean;
|
||
loading: boolean;
|
||
refetch: () => Promise<{ user: { id: string; email: string } | null; vip: boolean }>;
|
||
}
|
||
|
||
export function useAuthAndVip(): AuthAndVipState {
|
||
const [user, setUser] = useState<{ id: string; email: string } | null>(null);
|
||
const [vip, setVip] = useState(false);
|
||
const [loading, setLoading] = useState(true);
|
||
|
||
const refetch = useCallback(async (): Promise<{ user: { id: string; email: string } | null; vip: boolean }> => {
|
||
setLoading(true);
|
||
try {
|
||
const [meRes, vipRes] = await Promise.all([
|
||
fetch("/api/auth/me", { credentials: "include" }),
|
||
fetch("/api/vip/check", { credentials: "include" }),
|
||
]);
|
||
const meData = await meRes.json();
|
||
const vipData = await vipRes.json();
|
||
let newUser = meData?.user ?? null;
|
||
let newVip = vipData?.vip === true;
|
||
|
||
// 与 Header 一致:API 无用户时,尝试从 localStorage 恢复(如 cookie 未同步、localhost 开发等)
|
||
if (!newUser) {
|
||
const storedUser = getStoredUser();
|
||
const storedToken = getStoredToken();
|
||
if (storedUser && storedToken) {
|
||
newUser = storedUser;
|
||
try {
|
||
await fetch("/api/auth/sync-session", {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify({ token: storedToken, record: storedUser }),
|
||
credentials: "include",
|
||
});
|
||
} catch {
|
||
/* ignore */
|
||
}
|
||
}
|
||
}
|
||
|
||
setUser(newUser);
|
||
setVip(newVip);
|
||
return { user: newUser, vip: newVip };
|
||
} catch {
|
||
const storedUser = getStoredUser();
|
||
setUser(storedUser);
|
||
setVip(false);
|
||
return { user: storedUser, vip: false };
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
refetch();
|
||
}, [refetch]);
|
||
|
||
return { user, vip, loading, refetch };
|
||
}
|