Fix QC Kak Ayu 15 Des
Fix QC Kak Inno 15 Des Fix UI User Font Size, Font Weight, Line Height Fix UI Admin Font Size, Font Weight, Line Height & UI Mobile
This commit is contained in:
@@ -10,10 +10,19 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
Progress,
|
||||
Group,
|
||||
} from '@mantine/core';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { authStore } from '@/store/authStore'; // ✅ integrasi authStore
|
||||
import { authStore } from '@/store/authStore';
|
||||
|
||||
// ⚙️ Configuration
|
||||
const CONFIG = {
|
||||
POLL_INTERVAL: 3000, // 3 detik
|
||||
MAX_RETRIES: 2, // 2x retry
|
||||
TIMEOUT_DURATION: 5 * 60 * 1000, // 5 menit (300 detik)
|
||||
};
|
||||
|
||||
async function fetchUser() {
|
||||
const res = await fetch('/api/auth/me', {
|
||||
@@ -26,21 +35,48 @@ async function fetchUser() {
|
||||
return res.json();
|
||||
}
|
||||
|
||||
function formatTime(seconds: number): string {
|
||||
const mins = Math.floor(seconds / 60);
|
||||
const secs = seconds % 60;
|
||||
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
export default function WaitingRoom() {
|
||||
const router = useRouter();
|
||||
const [user, setUser] = useState<any>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [isRedirecting, setIsRedirecting] = useState(false);
|
||||
const [retryCount, setRetryCount] = useState(0);
|
||||
const MAX_RETRIES = 2;
|
||||
|
||||
// ⏱️ Countdown timer
|
||||
const [timeLeft, setTimeLeft] = useState(CONFIG.TIMEOUT_DURATION / 1000); // dalam detik
|
||||
const [hasTimedOut, setHasTimedOut] = useState(false);
|
||||
|
||||
// ⏱️ Countdown effect
|
||||
useEffect(() => {
|
||||
if (isRedirecting || hasTimedOut) return;
|
||||
|
||||
const countdownInterval = setInterval(() => {
|
||||
setTimeLeft((prev) => {
|
||||
if (prev <= 1) {
|
||||
setHasTimedOut(true);
|
||||
setError('Waktu tunggu habis. Silakan hubungi administrator atau coba login ulang nanti.');
|
||||
return 0;
|
||||
}
|
||||
return prev - 1;
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(countdownInterval);
|
||||
}, [isRedirecting, hasTimedOut]);
|
||||
|
||||
// 🔄 Polling effect
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
let interval: ReturnType<typeof setInterval>;
|
||||
|
||||
const poll = async () => {
|
||||
if (isRedirecting || !isMounted) return;
|
||||
if (isRedirecting || !isMounted || hasTimedOut) return;
|
||||
|
||||
try {
|
||||
const data = await fetchUser();
|
||||
@@ -59,12 +95,11 @@ export default function WaitingRoom() {
|
||||
});
|
||||
}
|
||||
|
||||
// In the poll function
|
||||
// ✅ Check if approved
|
||||
if (currentUser?.isActive === true) {
|
||||
setIsRedirecting(true);
|
||||
clearInterval(interval);
|
||||
|
||||
// Update authStore with the current user data
|
||||
authStore.setUser({
|
||||
id: currentUser.id,
|
||||
name: currentUser.name || 'User',
|
||||
@@ -78,7 +113,7 @@ export default function WaitingRoom() {
|
||||
localStorage.removeItem('auth_nomor');
|
||||
localStorage.removeItem('auth_username');
|
||||
|
||||
// Force a session refresh
|
||||
// Force session refresh
|
||||
try {
|
||||
const res = await fetch('/api/auth/refresh-session', {
|
||||
method: 'POST',
|
||||
@@ -99,26 +134,26 @@ export default function WaitingRoom() {
|
||||
redirectPath = '/admin/pendidikan/info-sekolah/jenjang-pendidikan';
|
||||
break;
|
||||
}
|
||||
window.location.href = redirectPath; // Use window.location to force full page reload
|
||||
window.location.href = redirectPath;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error refreshing session:', error);
|
||||
router.refresh(); // Fallback to client-side refresh
|
||||
router.refresh();
|
||||
}
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (!isMounted) return;
|
||||
|
||||
if (err.message.includes('401')) {
|
||||
if (retryCount < MAX_RETRIES) {
|
||||
if (retryCount < CONFIG.MAX_RETRIES) {
|
||||
setRetryCount((prev) => prev + 1);
|
||||
setTimeout(() => {
|
||||
if (isMounted) interval = setInterval(poll, 3000);
|
||||
if (isMounted) interval = setInterval(poll, CONFIG.POLL_INTERVAL);
|
||||
}, 800);
|
||||
} else {
|
||||
setError('Sesi tidak valid. Silakan login ulang.');
|
||||
clearInterval(interval);
|
||||
authStore.setUser(null); // ✅ clear sesi
|
||||
authStore.setUser(null);
|
||||
}
|
||||
} else {
|
||||
console.error('Error polling:', err);
|
||||
@@ -126,26 +161,53 @@ export default function WaitingRoom() {
|
||||
}
|
||||
};
|
||||
|
||||
interval = setInterval(poll, 3000);
|
||||
interval = setInterval(poll, CONFIG.POLL_INTERVAL);
|
||||
return () => {
|
||||
isMounted = false;
|
||||
if (interval) clearInterval(interval);
|
||||
};
|
||||
}, [router, isRedirecting, retryCount]);
|
||||
}, [router, isRedirecting, retryCount, hasTimedOut]);
|
||||
|
||||
// ✅ UI Error
|
||||
if (error) {
|
||||
// 🚨 Handle logout
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
await fetch('/api/auth/logout', {
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Logout error:', err);
|
||||
} finally {
|
||||
authStore.setUser(null);
|
||||
localStorage.clear();
|
||||
router.push('/login');
|
||||
}
|
||||
};
|
||||
|
||||
// ❌ UI Error / Timeout
|
||||
if (error || hasTimedOut) {
|
||||
return (
|
||||
<Center h="100vh">
|
||||
<Paper p="xl" radius="md" bg={colors['white-trans-1']} w={400}>
|
||||
<Center h="100vh" bg={colors.Bg}>
|
||||
<Paper p="xl" radius="md" bg={colors['white-trans-1']} w={{ base: '90%', sm: 400 }}>
|
||||
<Stack align="center" gap="md">
|
||||
<Title order={3} c="red">
|
||||
Sesi Tidak Valid
|
||||
<Title order={3} c="red" ta="center">
|
||||
{hasTimedOut ? '⏱️ Waktu Habis' : '❌ Sesi Tidak Valid'}
|
||||
</Title>
|
||||
<Text>{error}</Text>
|
||||
<Button onClick={() => router.push('/login')}>
|
||||
Login Ulang
|
||||
</Button>
|
||||
<Text ta="center" size="sm">
|
||||
{error || 'Waktu tunggu persetujuan telah habis.'}
|
||||
</Text>
|
||||
<Text ta="center" size="xs" c="dimmed">
|
||||
Silakan hubungi Superadmin atau coba login ulang nanti.
|
||||
</Text>
|
||||
<Group gap="sm" w="100%">
|
||||
<Button
|
||||
fullWidth
|
||||
variant="outline"
|
||||
onClick={handleLogout}
|
||||
>
|
||||
Kembali ke Login
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Center>
|
||||
@@ -171,24 +233,56 @@ export default function WaitingRoom() {
|
||||
);
|
||||
}
|
||||
|
||||
// ✅ UI Default (MENUNGGU) — INI YANG KAMU HILANGKAN!
|
||||
// ⏳ UI Default (MENUNGGU)
|
||||
const progressValue = ((CONFIG.TIMEOUT_DURATION / 1000 - timeLeft) / (CONFIG.TIMEOUT_DURATION / 1000)) * 100;
|
||||
|
||||
return (
|
||||
<Center h="100vh" bg={colors.Bg}>
|
||||
<Paper p="xl" radius="md" bg={colors['white-trans-1']} w={{ base: '90%', sm: 400 }}>
|
||||
<Stack align="center" gap="lg">
|
||||
<Title order={2} c={colors['blue-button']} ta="center">
|
||||
Menunggu Persetujuan
|
||||
⏳ Menunggu Persetujuan
|
||||
</Title>
|
||||
|
||||
<Text ta="center" c="dimmed">
|
||||
Akun Anda sedang dalam proses verifikasi oleh Superadmin.
|
||||
</Text>
|
||||
<Text ta="center" size="sm" c="dimmed">
|
||||
|
||||
<Text ta="center" size="sm" fw={500}>
|
||||
Nomor: {user?.nomor || '...'}
|
||||
</Text>
|
||||
|
||||
{/* ⏱️ Countdown Timer */}
|
||||
<Stack w="100%" gap="xs">
|
||||
<Group justify="space-between" w="100%">
|
||||
<Text size="sm" c="dimmed">Sisa waktu:</Text>
|
||||
<Text size="sm" fw={600} c={timeLeft < 60 ? 'red' : colors['blue-button']}>
|
||||
{formatTime(timeLeft)}
|
||||
</Text>
|
||||
</Group>
|
||||
<Progress
|
||||
value={progressValue}
|
||||
color={timeLeft < 60 ? 'red' : colors['blue-button']}
|
||||
size="sm"
|
||||
animated
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<Loader size="sm" color={colors['blue-button']} />
|
||||
|
||||
<Text ta="center" size="xs" c="dimmed">
|
||||
Jangan tutup halaman ini. Anda akan dialihkan otomatis setelah disetujui.
|
||||
</Text>
|
||||
|
||||
{/* 🚪 Tombol Keluar */}
|
||||
<Button
|
||||
variant="subtle"
|
||||
size="xs"
|
||||
onClick={handleLogout}
|
||||
c="dimmed"
|
||||
>
|
||||
Keluar dari Halaman Ini
|
||||
</Button>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Center>
|
||||
|
||||
Reference in New Issue
Block a user