User yang sudah registrasi sudah langsung diarahkan ke layout sesuai dengan roleIdnya

Superadmin sudah bisa menambah atau mengurangkan menu pad user yang diinginkan
Next-------------------------------
Ada bug saat tampilan menu sudah di edit superamin berhasil namun saat user logout tampilan menunya balik ke sebelumnya
This commit is contained in:
2025-11-26 10:14:05 +08:00
parent e30b27f7a4
commit 2fb3666e57
8 changed files with 239 additions and 157 deletions

View File

@@ -82,64 +82,48 @@ export default function Validasi() {
}
};
// ✅ Verifikasi OTP untuk REGISTRASI
const handleRegistrationVerification = async () => {
const username = localStorage.getItem('auth_username');
if (!username) {
toast.error('Data registrasi tidak ditemukan. Silakan ulangi dari awal.');
return;
}
const handleRegistrationVerification = async () => {
const username = localStorage.getItem('auth_username');
if (!username) {
toast.error('Data registrasi tidak ditemukan.');
return;
}
// ✅ Validasi format
const cleanNomor = nomor?.replace(/\D/g, '') ?? '';
if (cleanNomor.length < 10) {
toast.error('Nomor tidak valid');
return;
}
const cleanNomor = nomor?.replace(/\D/g, '') ?? '';
if (cleanNomor.length < 10 || username.trim().length < 5) {
toast.error('Data tidak valid');
return;
}
if (username.trim().length < 5) {
toast.error('Username minimal 5 karakter');
return;
}
// Verifikasi OTP dulu
const verifyRes = await fetch('/api/auth/verify-otp-register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nomor: cleanNomor, otp, kodeId }),
});
// 1. Verifikasi OTP via endpoint register
const verifyRes = await fetch('/api/auth/verify-otp-register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nomor: cleanNomor, otp, kodeId }),
});
const verifyData = await verifyRes.json();
if (!verifyRes.ok) {
toast.error(verifyData.message || 'Verifikasi OTP gagal');
return;
}
const verifyData = await verifyRes.json();
// ✅ Kirim ke finalize-registration → akan redirect ke /waiting-room
const finalizeRes = await fetch('/api/auth/finalize-registration', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nomor, username, kodeId }),
credentials: 'include'
});
if (!verifyRes.ok) {
toast.error(verifyData.message || 'Verifikasi OTP gagal');
return;
}
// 2. Finalisasi registrasi
const finalizeRes = await fetch('/api/auth/finalize-registration', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nomor, username, kodeId }), // 🔴 Tidak perlu kirim `otp` ke sini
});
const finalizeData = await finalizeRes.json();
if (!finalizeRes.ok) {
toast.error(finalizeData.message || 'Registrasi gagal');
return;
}
// 3. Set user & redirect
authStore.setUser({
id: finalizeData.user.id,
name: finalizeData.user.name,
roleId: Number(finalizeData.user.roleId),
});
cleanupStorage();
window.location.href = '/waiting-room';
};
if (finalizeRes.redirected) {
// ✅ Redirect otomatis oleh server
window.location.href = finalizeRes.url;
} else {
const data = await finalizeRes.json();
toast.error(data.message || 'Registrasi gagal');
}
};
// ✅ Verifikasi OTP untuk LOGIN
const handleLoginVerification = async () => {

View File

@@ -50,38 +50,45 @@ export default function Layout({ children }: { children: React.ReactNode }) {
return;
}
const fetchUser = async () => {
try {
const res = await fetch('/api/auth/me');
const data = await res.json();
const fetchUser = async () => {
try {
const res = await fetch('/api/auth/me');
const data = await res.json();
if (data.user) {
const menuRes = await fetch(`/api/admin/user-menu-access?userId=${data.user.id}`);
const menuData = await menuRes.json();
// ✅ Clone ke array mutable
const menuIds = menuData.success && Array.isArray(menuData.menuIds)
? [...menuData.menuIds] // Converts readonly array to mutable
: null;
authStore.setUser({
id: data.user.id,
name: data.user.name,
roleId: Number(data.user.roleId),
menuIds,
});
} else {
authStore.setUser(null);
router.replace('/login');
}
} catch (error) {
console.error('Gagal memuat data pengguna:', error);
if (data.user) {
// Check if user is active
if (!data.user.isActive) {
authStore.setUser(null);
router.replace('/login');
} finally {
setLoading(false);
router.replace('/waiting-room');
return;
}
};
const menuRes = await fetch(`/api/admin/user-menu-access?userId=${data.user.id}`);
const menuData = await menuRes.json();
const menuIds = menuData.success && Array.isArray(menuData.menuIds)
? [...menuData.menuIds]
: null;
authStore.setUser({
id: data.user.id,
name: data.user.name,
roleId: Number(data.user.roleId),
menuIds,
isActive: data.user.isActive // Add isActive to store
});
} else {
authStore.setUser(null);
router.replace('/login');
}
} catch (error) {
console.error('Gagal memuat data pengguna:', error);
authStore.setUser(null);
router.replace('/login');
} finally {
setLoading(false);
}
};
fetchUser();
}, [router]);