Saat user baru registrasi maka akan diarahkan ke page waiting-room dan menunggu validasi admin

This commit is contained in:
2025-11-20 14:07:26 +08:00
parent a0537810e8
commit 78b8aa74cd
5 changed files with 89 additions and 139 deletions

View File

@@ -76,7 +76,7 @@ export default function Validasi() {
const regData = await regRes.json();
if (regData.success) {
cleanupStorage();
router.push('/admin/landing-page/profil/program-inovasi');
router.push('/waiting-room'); // ✅
} else {
toast.error(regData.message || 'Registrasi gagal');
}

View File

@@ -336,7 +336,8 @@ export const navBar = [
path: "/admin/lingkungan/konservasi-adat-bali/filosofi-tri-hita-karana"
}
]
}, {
},
{
id: "Pendidikan",
name: "Pendidikan",
path: "",
@@ -377,5 +378,49 @@ export const navBar = [
path: "/admin/pendidikan/data-pendidikan"
}
]
},
{
id: "User & Role",
name: "User & Role",
path: "",
children: [
{
id: "User",
name: "User",
path: "/admin/user/user"
},
{
id: "Role",
name: "Role",
path: "/admin/role/role"
},
{
id: "Pendidikan_3",
name: "Program Pendidikan Anak",
path: "/admin/pendidikan/program-pendidikan-anak/program-unggulan"
},
{
id: "Pendidikan_4",
name: "Bimbingan Belajar Desa",
path: "/admin/pendidikan/bimbingan-belajar-desa/tujuan-program"
},
{
id: "Pendidikan_5",
name: "Pendidikan Non Formal",
path: "/admin/pendidikan/pendidikan-non-formal/tujuan-program"
},
{
id: "Pendidikan_6",
name: "Perpustakaan Digital",
path: "/admin/pendidikan/perpustakaan-digital/data-perpustakaan"
},
{
id: "Pendidikan_7",
name: "Data Pendidikan",
path: "/admin/pendidikan/data-pendidikan"
}
]
}
]

View File

@@ -54,7 +54,7 @@ export const apiFetchRegister = async ({
const cleanPhone = nomor.replace(/\D/g, '');
if (cleanPhone.length < 10) throw new Error('Nomor tidak valid');
const response = await fetch("/api/auth/send-otp-register", {
const response = await fetch("/api/auth/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username: username.trim(), nomor: cleanPhone }),
@@ -86,38 +86,6 @@ export const apiFetchOtpData = async ({ kodeId }: { kodeId: string }) => {
return data;
};
// export const apiFetchVerifyOtp = async ({
// nomor,
// otp,
// kodeId
// }: {
// nomor: string;
// otp: string;
// kodeId: string;
// }) => {
// if (!nomor || !otp || !kodeId) {
// throw new Error('Data verifikasi tidak lengkap');
// }
// if (!/^\d{4,6}$/.test(otp)) {
// throw new Error('Kode OTP harus 4-6 digit angka');
// }
// const response = await fetch('/api/auth/verify-otp', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({ nomor, otp, kodeId }),
// });
// const data = await response.json();
// if (!response.ok) {
// throw new Error(data.message || 'Verifikasi OTP gagal');
// }
// return data;
// };
export const apiFetchVerifyOtp = async ({
nomor,
otp,

View File

@@ -1,7 +1,8 @@
// app/api/auth/finalize-registration/route.ts
import prisma from "@/lib/prisma";
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import { sessionCreate } from "../_lib/session_create";
// import { sessionCreate } from "../_lib/session_create";
export async function POST(req: Request) {
try {
@@ -15,21 +16,28 @@ export async function POST(req: Request) {
// Buat user
const user = await prisma.user.create({
data: { username, nomor, isActive: true }
data: { username, nomor, isActive: false }
});
// Nonaktifkan OTP
await prisma.kodeOtp.update({ where: { id: kodeId }, data: { isActive: false } });
// Buat session
const token = await sessionCreate({
sessionKey: process.env.BASE_SESSION_KEY!,
jwtSecret: process.env.BASE_TOKEN_KEY!,
user: { id: user.id, nomor: user.nomor, username: user.username, roleId: user.roleId, isActive: true },
// const token = await sessionCreate({
// sessionKey: process.env.BASE_SESSION_KEY!,
// jwtSecret: process.env.BASE_TOKEN_KEY!,
// user: { id: user.id, nomor: user.nomor, username: user.username, roleId: user.roleId, isActive: true },
// });
(await cookies()).set('desadarmasaba_user_id', user.id, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
path: '/',
maxAge: 30 * 24 * 60 * 60, // 30 hari
});
const response = NextResponse.json({ success: true, roleId: user.roleId });
response.cookies.set(process.env.BASE_SESSION_KEY!, token, { /* options */ });
// response.cookies.set(process.env.BASE_SESSION_KEY!, token, { /* options */ });
return response;
} catch (error) {
console.error('Finalize Registration Error:', error);

View File

@@ -1,121 +1,50 @@
// app/api/auth/register/route.ts
import { NextResponse } from 'next/server';
import prisma from '@/lib/prisma';
import { randomOTP } from '../_lib/randomOTP'; // pastikan ada
export async function POST(req: Request) {
try {
// Terima langsung properti, bukan { data: { ... } }
const { username, nomor } = await req.json();
// Validasi input
if (!username || !nomor) {
return NextResponse.json(
{ success: false, message: 'Data tidak lengkap' },
{ status: 400 }
);
return NextResponse.json({ success: false, message: 'Data tidak lengkap' }, { status: 400 });
}
// // Validasi OTP: pastikan berisi digit saja
// const cleanOtp = otp.toString().trim();
// if (!/^\d{4,6}$/.test(cleanOtp)) {
// return NextResponse.json(
// { success: false, message: 'Kode OTP tidak valid' },
// { status: 400 }
// );
// }
// const receivedOtp = parseInt(cleanOtp, 10);
// if (isNaN(receivedOtp)) {
// return NextResponse.json(
// { success: false, message: 'Kode OTP tidak valid' },
// { status: 400 }
// );
// }
// // Cari OTP record
// const otpRecord = await prisma.kodeOtp.findUnique({
// where: { id: kodeId },
// });
// if (!otpRecord) {
// return NextResponse.json(
// { success: false, message: 'Kode verifikasi tidak valid' },
// { status: 400 }
// );
// }
// if (!otpRecord.isActive) {
// return NextResponse.json(
// { success: false, message: 'Kode verifikasi sudah kadaluarsa' },
// { status: 400 }
// );
// }
// if (otpRecord.otp !== receivedOtp) {
// return NextResponse.json(
// { success: false, message: 'Kode OTP salah' },
// { status: 400 }
// );
// }
// if (otpRecord.nomor !== nomor) {
// return NextResponse.json(
// { success: false, message: 'Nomor tidak sesuai' },
// { status: 400 }
// );
// }
// Cek duplikat nomor
const existingUser = await prisma.user.findUnique({
where: { nomor },
});
if (existingUser) {
return NextResponse.json(
{ success: false, message: 'Nomor sudah terdaftar' },
{ status: 409 }
);
// Cek duplikat
if (await prisma.user.findUnique({ where: { nomor } })) {
return NextResponse.json({ success: false, message: 'Nomor sudah terdaftar' }, { status: 409 });
}
if (await prisma.user.findUnique({ where: { username } })) {
return NextResponse.json({ success: false, message: 'Username sudah digunakan' }, { status: 409 });
}
// Cek username unik (pastikan ada @unique di schema!)
const existingByUsername = await prisma.user.findUnique({
where: { username },
});
// ✅ Generate dan kirim OTP
const codeOtp = randomOTP();
const otpNumber = Number(codeOtp);
if (existingByUsername) {
return NextResponse.json(
{ success: false, message: 'Username sudah digunakan' },
{ status: 409 }
);
const waMessage = `Website Desa Darmasaba - Kode verifikasi Anda: ${codeOtp}`;
const waUrl = `https://wa.wibudev.com/code?nom=${encodeURIComponent(nomor)}&text=${encodeURIComponent(waMessage)}`;
const waRes = await fetch(waUrl);
const waData = await waRes.json();
if (waData.status !== "success") {
return NextResponse.json({ success: false, message: 'Gagal mengirim OTP via WhatsApp' }, { status: 400 });
}
// Buat user
const newUser = await prisma.user.create({
data: {
username: username.trim(),
nomor,
isActive: false,
// roleId default "1"
},
// ✅ Simpan OTP ke database
const otpRecord = await prisma.kodeOtp.create({
data: { nomor, otp: otpNumber, isActive: true }
});
// // Nonaktifkan OTP
// await prisma.kodeOtp.update({
// where: { id: kodeId },
// data: { isActive: false },
// });
// ✅ Kembalikan kodeId (jangan buat user di sini!)
return NextResponse.json({
success: true,
message: 'Pendaftaran berhasil. Menunggu persetujuan admin.',
userId: newUser.id,
message: 'Kode verifikasi dikirim',
kodeId: otpRecord.id,
});
} catch (error) {
console.error('Registration error:', error);
return NextResponse.json(
{ success: false, message: 'Terjadi kesalahan saat pendaftaran' },
{ status: 500 }
);
console.error('Register OTP Error:', error);
return NextResponse.json({ success: false, message: 'Gagal mengirim OTP' }, { status: 500 });
} finally {
await prisma.$disconnect();
}