"use client"; import { useCallback, useState, useEffect, type FormEvent } from "react"; import { createPortal } from "react-dom"; import { emailLogin, googleLogin, pbSaveAuth, } from "@/app/lib/pocketbase"; import { useTranslation } from "@/i18n/navigation"; import { syncAuthSession } from "@/app/lib/api-client"; import GoogleLoginButton from "./GoogleLoginButton"; interface AuthModalProps { isOpen: boolean; onClose: () => void; onSuccess: (email: string) => void; } const GOOGLE_CLIENT_ID = process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || ""; export default function AuthModal({ isOpen, onClose, onSuccess }: AuthModalProps) { const { t } = useTranslation("auth"); const [email, setEmail] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const finishAuth = useCallback( async (result: Awaited>, successEmail: string) => { pbSaveAuth(result.token, result.record); await syncAuthSession(result.token, result.record as Record); onSuccess(successEmail); onClose(); setEmail(""); }, [onClose, onSuccess] ); const handleSubmit = async (e: FormEvent) => { e.preventDefault(); setError(null); setLoading(true); try { const normalizedEmail = email.trim(); const result = await emailLogin(normalizedEmail); await finishAuth(result, normalizedEmail); } catch (err) { setError(err instanceof Error ? err.message : "操作失败"); } finally { setLoading(false); } }; const handleGoogleCredential = useCallback(async (credential: string) => { setError(null); setLoading(true); try { const result = await googleLogin(credential); await finishAuth(result, result.record.email); } catch (err) { setError(err instanceof Error ? err.message : "Google 登录失败"); } finally { setLoading(false); } }, [finishAuth]); const [mounted, setMounted] = useState(false); useEffect(() => setMounted(true), []); if (!isOpen || !mounted) return null; const modalContent = (

{t("login")}

{t("loginHint")}

setEmail(e.target.value)} placeholder="your@email.com" required className="w-full rounded-lg border border-gray-200 px-4 py-2.5 text-gray-800 placeholder-gray-400 focus:border-[#ff4d4f] focus:outline-none focus:ring-1 focus:ring-[#ff4d4f] dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100" />
{error && (

{error}

)}
{GOOGLE_CLIENT_ID && ( <>
or
)}
); return createPortal(modalContent, document.body); }