'use client'; import colors from '@/con/colors'; import { Box, Button, Center, Loader, Paper, PinInput, Stack, Text, Title, } from '@mantine/core'; import { useRouter } from 'next/navigation'; import { useEffect, useState } from 'react'; import { toast } from 'react-toastify'; import { authStore } from '@/store/authStore'; export default function Validasi() { const router = useRouter(); const [nomor, setNomor] = useState(null); const [otp, setOtp] = useState(''); const [loading, setLoading] = useState(false); const [isLoading, setIsLoading] = useState(true); const [kodeId, setKodeId] = useState(null); const [isRegistrationFlow, setIsRegistrationFlow] = useState(false); // ✅ Deteksi flow dari cookie via API useEffect(() => { const checkFlow = async () => { try { const res = await fetch('/api/auth/get-flow', { credentials: 'include' }); const data = await res.json(); if (data.success) { setIsRegistrationFlow(data.flow === 'register'); console.log('🔍 Flow detected from cookie:', data.flow); } } catch (error) { console.error('❌ Error getting flow:', error); setIsRegistrationFlow(false); } }; checkFlow(); }, []); useEffect(() => { const storedKodeId = localStorage.getItem('auth_kodeId'); if (!storedKodeId) { toast.error('Akses tidak valid'); router.replace('/login'); return; } setKodeId(storedKodeId); const loadOtpData = async () => { try { const res = await fetch(`/api/auth/otp-data?kodeId=${encodeURIComponent(storedKodeId)}`); const result = await res.json(); if (res.ok && result.data?.nomor) { setNomor(result.data.nomor); } else { throw new Error('Data OTP tidak valid'); } } catch (error) { console.error('Gagal memuat data OTP:', error); toast.error('Kode verifikasi tidak valid'); router.replace('/login'); } finally { setIsLoading(false); } }; loadOtpData(); }, [router]); const handleVerify = async () => { if (!kodeId || !nomor || otp.length < 4) return; setLoading(true); try { if (isRegistrationFlow) { await handleRegistrationVerification(); } else { await handleLoginVerification(); } } catch (error) { console.error('Error saat verifikasi:', error); toast.error('Terjadi kesalahan sistem'); } finally { setLoading(false); } }; const handleRegistrationVerification = async () => { const username = localStorage.getItem('auth_username'); if (!username) { toast.error('Data registrasi tidak ditemukan.'); return; } const cleanNomor = nomor?.replace(/\D/g, '') ?? ''; if (cleanNomor.length < 10 || username.trim().length < 5) { toast.error('Data tidak valid'); return; } // ✅ Verify OTP const verifyRes = await fetch('/api/auth/verify-otp-register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nomor: cleanNomor, otp, kodeId }), credentials: 'include' }); const verifyData = await verifyRes.json(); if (!verifyRes.ok) { toast.error(verifyData.message || 'Verifikasi OTP gagal'); return; } // ✅ Finalize registration const finalizeRes = await fetch('/api/auth/finalize-registration', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nomor: cleanNomor, username, kodeId }), credentials: 'include' }); const data = await finalizeRes.json(); // ✅ Check JSON response (bukan redirect) if (data.success) { toast.success('Registrasi berhasil! Menunggu persetujuan admin.'); await cleanupStorage(); // ✅ Client-side redirect setTimeout(() => { window.location.href = '/waiting-room'; }, 1000); } else { toast.error(data.message || 'Registrasi gagal'); } }; const handleLoginVerification = async () => { const loginRes = await fetch('/api/auth/verify-otp-login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nomor, otp, kodeId }), credentials: 'include' }); const loginData = await loginRes.json(); if (!loginRes.ok) { toast.error(loginData.message || 'Verifikasi gagal'); return; } const { id, name, roleId, isActive } = loginData.user; authStore.setUser({ id, name: name || 'User', roleId: Number(roleId), }); // ✅ Cleanup setelah login sukses await cleanupStorage(); if (!isActive) { window.location.href = '/waiting-room'; return; } const redirectPath = getRedirectPath(Number(roleId)); router.replace(redirectPath); }; const getRedirectPath = (roleId: number): string => { switch (roleId) { case 0: case 1: case 2: return '/admin/landing-page/profil/program-inovasi'; case 3: return '/admin/kesehatan/posyandu/list-posyandu'; case 4: return '/admin/pendidikan/info-sekolah/jenjang-pendidikan'; default: return '/admin'; } }; // ✅ CLEANUP FUNCTION - Hapus localStorage + Cookie const cleanupStorage = async () => { // Clear localStorage localStorage.removeItem('auth_kodeId'); localStorage.removeItem('auth_nomor'); localStorage.removeItem('auth_username'); // Clear cookie try { await fetch('/api/auth/clear-flow', { method: 'POST', credentials: 'include' }); } catch (error) { console.error('Error clearing flow cookie:', error); } }; const handleResend = async () => { if (!nomor) return; try { const res = await fetch('/api/auth/resend', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nomor }), }); const data = await res.json(); if (data.success) { localStorage.setItem('auth_kodeId', data.kodeId); toast.success('OTP baru dikirim'); } else { toast.error(data.message || 'Gagal mengirim ulang OTP'); } } catch { toast.error('Gagal menghubungi server'); } }; if (isLoading) { return ( ); } if (!nomor) return null; return ( {isRegistrationFlow ? 'Verifikasi Registrasi' : 'Verifikasi Login'} Kami telah mengirim kode ke nomor {nomor} Masukkan Kode Verifikasi
Tidak menerima kode?{' '}
); }