Fitur lengkap: - Auth JWT + RBAC (Admin/Teacher) + halaman login - Shell 3 kolom (left nav, topbar, right rail dashboard) - CRUD siswa + follow up kanban + status calon/student/ex - Dashboard: siswa aktif, kehadiran, bar sumber lead, perlu follow up - Pembayaran prorata per pertemuan (cash/transfer/qris) - Kelas, enrollment, generate sesi, kehadiran bulk - Jurnal aktivitas + upload multi-foto - Raport + placement test (tampil di detail siswa) - Pengaturan & seed data contoh Stack: Next.js 16, TypeScript, Tailwind v4, Prisma (SQLite), Recharts, Zod
36 lines
1.1 KiB
TypeScript
36 lines
1.1 KiB
TypeScript
"use server";
|
|
|
|
import { redirect } from "next/navigation";
|
|
import bcrypt from "bcryptjs";
|
|
import { prisma } from "@/lib/prisma";
|
|
import { loginSchema } from "@/lib/validators";
|
|
import { clearSessionCookie, setSessionCookie } from "@/lib/auth";
|
|
|
|
export type LoginState = { error?: string } | undefined;
|
|
|
|
export async function loginAction(_prev: LoginState, formData: FormData): Promise<LoginState> {
|
|
const parsed = loginSchema.safeParse({
|
|
email: formData.get("email"),
|
|
password: formData.get("password"),
|
|
});
|
|
if (!parsed.success) return { error: "Email atau password tidak valid." };
|
|
|
|
const user = await prisma.user.findUnique({ where: { email: parsed.data.email } });
|
|
if (!user || !user.isActive || !bcrypt.compareSync(parsed.data.password, user.passwordHash)) {
|
|
return { error: "Email atau password salah." };
|
|
}
|
|
|
|
await setSessionCookie({
|
|
userId: user.id,
|
|
name: user.name,
|
|
email: user.email,
|
|
role: user.role === "ADMIN" ? "ADMIN" : "TEACHER",
|
|
});
|
|
redirect("/dashboard");
|
|
}
|
|
|
|
export async function logoutAction() {
|
|
await clearSessionCookie();
|
|
redirect("/login");
|
|
}
|