user_kasir/src/routes/userBAST.tsx

228 lines
8.4 KiB
TypeScript

// src/routes/BAST.tsx
import React, { useState, useEffect } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom"; // Kita pakai untuk redirect user biasa
import { FileText, ArrowRight, ClipboardList, User, ShieldAlert } from "lucide-react";
interface UserType {
user_id: number;
nama_lengkap: string;
role: string;
}
interface BarangType {
barang_id: number;
nama_barang: string;
}
export default function BAST() {
const [daftarUser, setDaftarUser] = useState<UserType[]>([]);
const [daftarBarang, setDaftarBarang] = useState<BarangType[]>([]);
// State Input Form
const [barangId, setBarangId] = useState("");
const [userSerahId, setUserSerahId] = useState(""); // Ditambahkan sesuai soal: Admin bebas pilih User Serah
const [userTerimaId, setUserTerimaId] = useState(""); // Ditambahkan sesuai soal: Admin bebas pilih User Terima
const [loadingSubmit, setLoadingSubmit] = useState(false);
// State Otentikasi Role
const [currentAdmin, setCurrentAdmin] = useState<UserType | null>(null);
const [isAuthorized, setIsAuthorized] = useState(false);
const navigate = useNavigate();
useEffect(() => {
// 1. CEK SESSION LOGIN DAN ROLE NYA
const savedUser = sessionStorage.getItem("user");
if (!savedUser) {
alert("Silakan login terlebih dahulu!");
navigate("/login");
return;
}
try {
const parsed = JSON.parse(savedUser);
// KUNCI UTAMA SESUAI SOAL UKK: JIKA BUKAN ADMIN, BLOKIR AKSESNYA!
if (parsed.role !== "Admin") {
setIsAuthorized(false);
alert("Akses Ditolak! Berdasarkan soal UKK, hanya Admin yang boleh membuat dokumen BAST.");
navigate("/userDashboard"); // Buang user biasa ke dashboard mereka sendiri
return;
}
// Jika dia Admin, izinkan akses halaman ini
setCurrentAdmin(parsed);
setIsAuthorized(true);
} catch (e) {
console.error("Gagal membaca session:", e);
navigate("/login");
return;
}
// 2. AMBIL DATA PILIHAN USER (UNTUK DROPDOWN SERAH & TERIMA)
axios.get("http://localhost:5000/api/users")
.then((res) => {
if (res.data.success) setDaftarUser(res.data.data);
})
.catch((err) => console.error("Gagal memuat list user:", err));
// 3. AMBIL DATA BARANG DARI BACKEND
axios.get("http://localhost:5000/api/barang")
.then((res) => {
if (res.data.success) setDaftarBarang(res.data.data);
})
.catch((err) => console.error("Gagal memuat list barang:", err));
}, [navigate]);
// PROSES KIRIM FORM (ADMIN YANG MEMBUATKAN)
const handleSubmitBAST = async (e: React.FormEvent) => {
e.preventDefault();
if (!barangId || !userSerahId || !userTerimaId) {
alert("Harap lengkapi semua pilihan barang, pihak penyerah, dan pihak penerima!");
return;
}
if (userSerahId === userTerimaId) {
alert("Pihak Penyerah dan Pihak Penerima tidak boleh orang yang sama!");
return;
}
setLoadingSubmit(true);
try {
const response = await axios.post("http://localhost:5000/api/bast", {
barang_id: Number(barangId),
user_serah_id: Number(userSerahId), // Input dinamis pilihan Admin
user_terima_id: Number(userTerimaId), // Input dinamis pilihan Admin
});
if (response.data.success) {
alert("Dokumen BAST Baru Berhasil Diterbitkan! Status otomatis 'Menunggu Approval' dari kedua belah pihak.");
// Reset pilihan form
setBarangId("");
setUserSerahId("");
setUserTerimaId("");
} else {
alert("Gagal menerbitkan BAST: " + response.data.message);
}
} catch (error: any) {
console.error(error);
alert(error.response?.data?.message || "Terjadi kendala pada sistem backend.");
} finally {
setLoadingSubmit(false);
}
};
// Guarding UI biar tidak bocor sekilas saat loading validasi role
if (!isAuthorized) {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-900 text-white p-4">
<div className="text-center space-y-3">
<ShieldAlert className="mx-auto text-red-500 animate-pulse" size={48} />
<h2 className="text-xl font-bold">Memvalidasi Otoritas Akun...</h2>
</div>
</div>
);
}
return (
<div className="min-h-screen bg-gray-50 p-6 flex items-center justify-center">
<div className="max-w-2xl w-full bg-white border border-gray-200 rounded-3xl shadow-xl overflow-hidden">
{/* HEADER FORM (KHUSUS PORTAL ADMIN) */}
<div className="bg-gradient-to-r from-blue-700 to-indigo-800 p-6 text-white flex items-center gap-4">
<div className="p-3 bg-white/10 rounded-2xl">
<FileText size={28} />
</div>
<div>
<h1 className="text-2xl font-bold">Penerbitan BAST (Admin)</h1>
<p className="text-blue-100 text-xs mt-0.5">Petugas: {currentAdmin?.nama_lengkap} (Manajemen Inventaris)</p>
</div>
</div>
{/* BODY FORM */}
<form onSubmit={handleSubmitBAST} className="p-6 space-y-6">
{/* SELEKSI BARANG */}
<div className="space-y-2">
<label className="text-sm font-semibold text-gray-700 flex items-center gap-2">
<ClipboardList size={16} className="text-gray-400" />
1. Pilih Inventaris Barang Sekolah
</label>
<select
value={barangId}
onChange={(e) => setBarangId(e.target.value)}
className="w-full bg-white border border-gray-300 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">-- Cari / Pilih Barang --</option>
{daftarBarang.map((b) => (
<option key={b.barang_id} value={b.barang_id}>
{b.nama_barang}
</option>
))}
</select>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
{/* SELEKSI PIHAK 1 (PENYERAH) */}
<div className="space-y-2">
<label className="text-sm font-semibold text-gray-700 flex items-center gap-2">
<User size={16} className="text-green-600" />
2. Pihak 1 (User Penyerah)
</label>
<select
value={userSerahId}
onChange={(e) => setUserSerahId(e.target.value)}
className="w-full bg-white border border-gray-300 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">-- Pilih Penyerah --</option>
{daftarUser.map((u) => (
<option key={u.user_id} value={u.user_id}>
{u.nama_lengkap} ({u.role})
</option>
))}
</select>
</div>
{/* SELEKSI PIHAK 2 (PENERIMA) */}
<div className="space-y-2">
<label className="text-sm font-semibold text-gray-700 flex items-center gap-2">
<User size={16} className="text-orange-500" />
3. Pihak 2 (User Penerima)
</label>
<select
value={userTerimaId}
onChange={(e) => setUserTerimaId(e.target.value)}
className="w-full bg-white border border-gray-300 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">-- Pilih Penerima --</option>
{daftarUser.map((u) => (
<option key={u.user_id} value={u.user_id}>
{u.nama_lengkap} ({u.role})
</option>
))}
</select>
</div>
</div>
{/* BUTTON PEMBUATAN DOKUMEN */}
<button
type="submit"
disabled={loadingSubmit}
className="w-full bg-indigo-600 hover:bg-indigo-700 disabled:bg-indigo-300 text-white font-bold py-3 px-4 rounded-xl shadow-lg shadow-indigo-500/10 flex items-center justify-center gap-2 transition active:scale-[0.99]"
>
{loadingSubmit ? "Sedang Mendaftarkan Dokumen..." : (
<>
Terbitkan Dokumen BAST Resmi
<ArrowRight size={18} />
</>
)}
</button>
</form>
</div>
</div>
);
}