's'
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useCallback, useEffect } from "react";
|
||||
import { useState, useCallback, useEffect, useRef } from "react";
|
||||
import { Link, useLocale } from "@/i18n/navigation";
|
||||
import { useTranslation } from "@/i18n/navigation";
|
||||
import JoinModal from "./JoinModal";
|
||||
@@ -85,6 +85,9 @@ export default function HeroSection() {
|
||||
return () => window.removeEventListener("auth:updated", onAuth);
|
||||
}, []);
|
||||
|
||||
const checkUserCacheRef = useRef<{ email: string; data: { exists: boolean; vip: boolean }; ts: number } | null>(null);
|
||||
const CACHE_TTL_MS = 60_000;
|
||||
|
||||
const handleCheckAndProceed = useCallback(
|
||||
async (em: string) => {
|
||||
if (checking) return;
|
||||
@@ -96,6 +99,15 @@ export default function HeroSection() {
|
||||
setError(null);
|
||||
setChecking(true);
|
||||
try {
|
||||
const cached = checkUserCacheRef.current;
|
||||
if (cached && cached.email === trimmed && Date.now() - cached.ts < CACHE_TTL_MS) {
|
||||
const { exists, vip } = cached.data;
|
||||
if (exists) {
|
||||
setJoinModalVipOnly(!!vip);
|
||||
setJoinModalOpen(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const checkRes = await fetch("/api/meetup/check-user", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -107,6 +119,7 @@ export default function HeroSection() {
|
||||
throw new Error(checkData?.error || checkData?.detail || (locale === "zh" ? "操作失败" : "Operation failed"));
|
||||
}
|
||||
if (checkData.exists) {
|
||||
checkUserCacheRef.current = { email: trimmed, data: { exists: true, vip: !!checkData.vip }, ts: Date.now() };
|
||||
if (checkData.vip) {
|
||||
setJoinModalOpen(true);
|
||||
setJoinModalVipOnly(true);
|
||||
@@ -136,6 +149,9 @@ export default function HeroSection() {
|
||||
(locale === "zh" ? "创建用户失败" : "Failed to create user")
|
||||
);
|
||||
}
|
||||
if (ensureData.is_new) {
|
||||
await fetch("/api/meetup/set-needs-password-change", { method: "POST", credentials: "include" });
|
||||
}
|
||||
user_id = String(ensureData.user_id).trim();
|
||||
if (ensureData?.token && ensureData?.record) {
|
||||
await fetch("/api/auth/sync-session", {
|
||||
|
||||
@@ -54,6 +54,9 @@ export default function JoinModal({ isOpen, onClose, initialEmail = "", vipOnly
|
||||
if (!res.ok || !data?.ok) {
|
||||
throw new Error(data?.error || (locale === "zh" ? "操作失败" : "Operation failed"));
|
||||
}
|
||||
if (data.is_new) {
|
||||
await fetch("/api/meetup/set-needs-password-change", { method: "POST", credentials: "include" });
|
||||
}
|
||||
const { pbSaveAuth } = await import("@/app/lib/pocketbase");
|
||||
pbSaveAuth(data.token, data.record);
|
||||
await fetch("/api/auth/sync-session", {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { Link, useLocale, usePathname, useRouter, useTranslation } from "@/i18n/navigation";
|
||||
import { getStoredUserEmail, pbLogout } from "@/app/lib/pocketbase";
|
||||
import { getStoredUserEmail, getStoredUser, getStoredToken, pbLogout } from "@/app/lib/pocketbase";
|
||||
import { getNavLinks } from "@/config";
|
||||
import AuthModal from "./AuthModal";
|
||||
import ThemeToggle from "./ThemeToggle";
|
||||
@@ -25,8 +25,8 @@ export default function NavbarComponent() {
|
||||
|
||||
const fetchAuth = useCallback(async () => {
|
||||
try {
|
||||
const res = await fetch("/api/auth/me", { credentials: "include", cache: "no-store" });
|
||||
const data = await res.json();
|
||||
let res = await fetch("/api/auth/me", { credentials: "include", cache: "no-store" });
|
||||
let data = await res.json();
|
||||
if (data?.user && data?.token) {
|
||||
const { pbSaveAuth } = await import("@/app/lib/pocketbase");
|
||||
pbSaveAuth(data.token, { id: data.user.id, email: data.user.email });
|
||||
@@ -34,6 +34,25 @@ export default function NavbarComponent() {
|
||||
setUserVip(!!data.user.vip);
|
||||
return;
|
||||
}
|
||||
const token = getStoredToken();
|
||||
const record = getStoredUser();
|
||||
if (token && record?.id && record?.email) {
|
||||
const syncRes = await fetch("/api/auth/sync-session", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ token, record }),
|
||||
credentials: "include",
|
||||
});
|
||||
if (syncRes.ok) {
|
||||
res = await fetch("/api/auth/me", { credentials: "include", cache: "no-store" });
|
||||
data = await res.json();
|
||||
if (data?.user && data?.token) {
|
||||
setUserEmail(data.user.email);
|
||||
setUserVip(!!data.user.vip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
@@ -47,15 +66,21 @@ export default function NavbarComponent() {
|
||||
|
||||
useEffect(() => {
|
||||
const onAuthUpdated = () => fetchAuth();
|
||||
const onVipUpdated = () => fetchAuth();
|
||||
window.addEventListener("auth:updated", onAuthUpdated);
|
||||
return () => window.removeEventListener("auth:updated", onAuthUpdated);
|
||||
window.addEventListener("vip:updated", onVipUpdated);
|
||||
return () => {
|
||||
window.removeEventListener("auth:updated", onAuthUpdated);
|
||||
window.removeEventListener("vip:updated", onVipUpdated);
|
||||
};
|
||||
}, [fetchAuth]);
|
||||
|
||||
const handleLogout = useCallback(async () => {
|
||||
await pbLogout();
|
||||
setUserEmail(null);
|
||||
setUserVip(false);
|
||||
}, []);
|
||||
router.replace("/");
|
||||
}, [router]);
|
||||
|
||||
const isActive = useCallback((href: string) => {
|
||||
if (href.startsWith("/#")) return false;
|
||||
@@ -124,7 +149,7 @@ export default function NavbarComponent() {
|
||||
<span className="hidden sm:block max-w-[120px] truncate text-sm text-gray-600 dark:text-gray-400">
|
||||
{userEmail}
|
||||
</span>
|
||||
<UserAvatar email={userEmail} isVip={userVip} onLogout={() => { setUserEmail(null); setUserVip(false); }} />
|
||||
<UserAvatar email={userEmail} isVip={userVip} onLogout={handleLogout} />
|
||||
</div>
|
||||
) : null}
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user