import { useState, useEffect, useRef } from "react"; import { Link, useNavigate, useLocation } from "react-router-dom"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { AuthForm } from "@/components/auth-form"; import { apiClient, setAuthToken } from "@/lib/api-client"; import { useAuthStore } from "@/store/auth-store"; import { isTauri } from "@/lib/tauri"; function getUrlParam(name: string): string | null { return new URLSearchParams(window.location.search).get(name); } export function LoginPage() { const navigate = useNavigate(); const queryClient = useQueryClient(); const setUser = useAuthStore((state) => state.setUser); const location = useLocation(); const [error, setError] = useState(null); const oauthTokenConsumed = useRef(false); const [oauthProcessing, setOauthProcessing] = useState(false); // Handle OAuth callback: the API redirects to /login?token= // Must re-run on location.search change (SPA navigates to /login?token=xxx) useEffect(() => { const token = getUrlParam("token"); if (!token || oauthTokenConsumed.current) return; oauthTokenConsumed.current = true; setOauthProcessing(true); // Store token for future API calls and fetch user setAuthToken(token); apiClient .getMe() .then((data) => { setUser(data.user); queryClient.setQueryData(["auth", "me"], data); navigate("/dashboard", { replace: true }); }) .catch((err) => { setAuthToken(null); setOauthProcessing(false); setError(err instanceof Error ? err.message : "Google login gagal"); }); }, [setUser, queryClient, navigate, location.search]); // Backup: when app returns from background (e.g. after Google OAuth browser) // re-check URL params — the deep-link event may have been missed. useEffect(() => { if (!isTauri()) return; if (getUrlParam("token") || oauthTokenConsumed.current) return; const onVisibility = () => { if (document.visibilityState !== "visible") return; const token = getUrlParam("token"); if (token && !oauthTokenConsumed.current) { setOauthProcessing(true); } }; const onFocus = () => { const token = getUrlParam("token"); if (token && !oauthTokenConsumed.current) { setOauthProcessing(true); } }; document.addEventListener("visibilitychange", onVisibility); window.addEventListener("focus", onFocus); return () => { document.removeEventListener("visibilitychange", onVisibility); window.removeEventListener("focus", onFocus); }; }, []); // Show OAuth error from query param const oauthError = getUrlParam("error"); const meQuery = useQuery({ queryKey: ["auth", "me"], queryFn: () => apiClient.getMe(), }); // Already authenticated — redirect to dashboard useEffect(() => { if (!meQuery.isLoading && meQuery.data?.user) { navigate("/dashboard", { replace: true }); } }, [meQuery.data, meQuery.isLoading, navigate]); const mutation = useMutation({ mutationFn: apiClient.login, onSuccess: (response) => { setUser(response.user); queryClient.setQueryData(["auth", "me"], response); navigate("/dashboard"); }, onError: (err) => setError(err instanceof Error ? err.message : "Login gagal"), }); // Show loading spinner while OAuth token is being processed if (oauthProcessing) { return (

Menyelesaikan login dengan Google...

); } return (
{/* Background Image with Overlay */}
{/* Glassmorphism Container */}
{ setError(null); return mutation.mutateAsync({ email, password }); }} onFieldChange={() => setError(null)} />

Belum punya akun?{" "} Daftar

); }