feat: Implement user banning, dynamic user creation forms, and enhance dashboard UI with overdue book status and modals.
This commit is contained in:
commit
6f94cb2a91
|
|
@ -22,7 +22,7 @@ public function index(Request $request)
|
||||||
$peminjamanAktif = $groupedLoans->map(function ($userLoans, $userId) {
|
$peminjamanAktif = $groupedLoans->map(function ($userLoans, $userId) {
|
||||||
$user = $userLoans->first()->user;
|
$user = $userLoans->first()->user;
|
||||||
$firstLoan = $userLoans->first();
|
$firstLoan = $userLoans->first();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'id_peminjaman' => 'PIN-ADM-' . sprintf('%03d', $userId),
|
'id_peminjaman' => 'PIN-ADM-' . sprintf('%03d', $userId),
|
||||||
'user_id' => $userId,
|
'user_id' => $userId,
|
||||||
|
|
@ -43,7 +43,7 @@ public function index(Request $request)
|
||||||
$daftarPeminjam = $peminjamanAktif->pluck('peminjam')->unique();
|
$daftarPeminjam = $peminjamanAktif->pluck('peminjam')->unique();
|
||||||
|
|
||||||
return view('admin.peminjaman.index', [
|
return view('admin.peminjaman.index', [
|
||||||
'pageTitle' => 'Manajemen Peminjaman & Denda',
|
'pageTitle' => 'Manajemen Peminjaman',
|
||||||
'peminjamanAktif' => $peminjamanAktif,
|
'peminjamanAktif' => $peminjamanAktif,
|
||||||
'daftarPeminjam' => $daftarPeminjam,
|
'daftarPeminjam' => $daftarPeminjam,
|
||||||
]);
|
]);
|
||||||
|
|
@ -52,7 +52,7 @@ public function index(Request $request)
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
$users = User::whereIn('role', ['siswa', 'guru'])->get();
|
$users = User::whereIn('role', ['siswa', 'guru'])->get();
|
||||||
|
|
||||||
$groupedUsers = $users->map(function ($user) {
|
$groupedUsers = $users->map(function ($user) {
|
||||||
$jumlahPinjam = Loan::where('user_id', $user->id)
|
$jumlahPinjam = Loan::where('user_id', $user->id)
|
||||||
->whereIn('status', ['Dipinjam', 'Terlambat'])
|
->whereIn('status', ['Dipinjam', 'Terlambat'])
|
||||||
|
|
@ -98,7 +98,7 @@ public function store(Request $request)
|
||||||
try {
|
try {
|
||||||
foreach ($validated['buku_ids'] as $bookId) {
|
foreach ($validated['buku_ids'] as $bookId) {
|
||||||
$book = Book::findOrFail($bookId);
|
$book = Book::findOrFail($bookId);
|
||||||
|
|
||||||
// Check if book is available
|
// Check if book is available
|
||||||
if ($book->status !== 'Tersedia') {
|
if ($book->status !== 'Tersedia') {
|
||||||
throw new \Exception("Buku '{$book->judul}' tidak tersedia.");
|
throw new \Exception("Buku '{$book->judul}' tidak tersedia.");
|
||||||
|
|
@ -129,14 +129,14 @@ public function store(Request $request)
|
||||||
public function dendaIndex()
|
public function dendaIndex()
|
||||||
{
|
{
|
||||||
$now = Carbon::now();
|
$now = Carbon::now();
|
||||||
|
|
||||||
// Fetch all loans that are overdue or users that are banned
|
// Fetch all loans that are overdue or users that are banned
|
||||||
$loans = Loan::with(['user', 'book'])
|
$loans = Loan::with(['user', 'book'])
|
||||||
->where(function($query) use ($now) {
|
->where(function ($query) use ($now) {
|
||||||
$query->where('due_at', '<', $now)
|
$query->where('due_at', '<', $now)
|
||||||
->whereIn('status', ['Dipinjam', 'Terlambat']);
|
->whereIn('status', ['Dipinjam', 'Terlambat']);
|
||||||
})
|
})
|
||||||
->orWhereHas('user', function($query) {
|
->orWhereHas('user', function ($query) {
|
||||||
$query->where('is_banned', true);
|
$query->where('is_banned', true);
|
||||||
})
|
})
|
||||||
->get();
|
->get();
|
||||||
|
|
@ -146,10 +146,10 @@ public function dendaIndex()
|
||||||
$siswaTelat = $groupedLoans->map(function ($userLoans, $userId) use ($now) {
|
$siswaTelat = $groupedLoans->map(function ($userLoans, $userId) use ($now) {
|
||||||
$user = $userLoans->first()->user;
|
$user = $userLoans->first()->user;
|
||||||
$firstLoan = $userLoans->first();
|
$firstLoan = $userLoans->first();
|
||||||
|
|
||||||
$tenggat = Carbon::parse($firstLoan->due_at);
|
$tenggat = Carbon::parse($firstLoan->due_at);
|
||||||
$hariTelat = $now->greaterThan($tenggat) ? (int) $tenggat->diffInDays($now) : 0;
|
$hariTelat = $now->greaterThan($tenggat) ? (int) $tenggat->diffInDays($now) : 0;
|
||||||
|
|
||||||
$isGuru = $user->role === 'guru';
|
$isGuru = $user->role === 'guru';
|
||||||
$totalDenda = $isGuru ? 0 : ($hariTelat * 1000);
|
$totalDenda = $isGuru ? 0 : ($hariTelat * 1000);
|
||||||
|
|
||||||
|
|
@ -158,15 +158,15 @@ public function dendaIndex()
|
||||||
$waLink = '#';
|
$waLink = '#';
|
||||||
if ($hp) {
|
if ($hp) {
|
||||||
if (substr($hp, 0, 1) == '0') $hp = '62' . substr($hp, 1);
|
if (substr($hp, 0, 1) == '0') $hp = '62' . substr($hp, 1);
|
||||||
|
|
||||||
if ($isGuru && $hariTelat > 0) {
|
if ($isGuru && $hariTelat > 0) {
|
||||||
$pesan = "Halo Bapak/Ibu {$user->nama_lengkap}, anda terlambat pengembalian buku selama {$hariTelat} hari. Mohon segera dikembalikan ke perpustakaan. Terima kasih.";
|
$pesan = "Halo Bapak/Ibu {$user->nama_lengkap}, anda terlambat pengembalian buku selama {$hariTelat} hari. Mohon segera dikembalikan ke perpustakaan. Terima kasih.";
|
||||||
} else {
|
} else {
|
||||||
$pesan = $hariTelat > 0
|
$pesan = $hariTelat > 0
|
||||||
? "Halo {$user->nama_lengkap}, anda terlambat pengembalian buku. Total Denda: Rp " . number_format($totalDenda, 0, ',', '.')
|
? "Halo {$user->nama_lengkap}, anda terlambat pengembalian buku. Total Denda: Rp " . number_format($totalDenda, 0, ',', '.')
|
||||||
: "Halo {$user->nama_lengkap}, akun anda sedang dinonaktifkan sementara. Mohon hubungi petugas.";
|
: "Halo {$user->nama_lengkap}, akun anda sedang dinonaktifkan sementara. Mohon hubungi petugas.";
|
||||||
}
|
}
|
||||||
|
|
||||||
$waLink = "https://wa.me/{$hp}?text=" . urlencode($pesan);
|
$waLink = "https://wa.me/{$hp}?text=" . urlencode($pesan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -257,4 +257,4 @@ public function kembalikan(Request $request)
|
||||||
return response()->json(['status' => 'error', 'message' => $e->getMessage()], 500);
|
return response()->json(['status' => 'error', 'message' => $e->getMessage()], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,22 @@
|
||||||
use App\Models\MasterInduk;
|
use App\Models\MasterInduk;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\MasterInduk;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
class UserController extends Controller
|
class UserController extends Controller
|
||||||
{
|
{
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$users = User::orderBy('created_at', 'desc')->paginate(10);
|
$query = User::orderBy('created_at', 'desc');
|
||||||
|
|
||||||
|
if (request()->has('role') && request('role') != '') {
|
||||||
|
$query->where('role', request('role'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$users = $query->paginate(10)->appends(request()->query());
|
||||||
|
|
||||||
$whitelists = MasterInduk::orderBy('created_at', 'desc')->get();
|
$whitelists = MasterInduk::orderBy('created_at', 'desc')->get();
|
||||||
|
|
||||||
|
|
@ -23,29 +33,148 @@ public function index()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Menampilkan form untuk membuat pengguna baru.
|
|
||||||
*/
|
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
return view('admin.pengguna.create', [
|
return view('admin.pengguna.create', ['pageTitle' => 'Tambah Pengguna Baru']);
|
||||||
'pageTitle' => 'Tambah Pengguna Baru',
|
}
|
||||||
]);
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'nama_lengkap' => 'required|string|max:255',
|
||||||
|
'email' => 'required|email|unique:users,email',
|
||||||
|
'role' => 'required|in:siswa,guru,penjaga perpus',
|
||||||
|
'no_hp' => 'nullable|string|max:20',
|
||||||
|
'password' => 'required|min:6|confirmed',
|
||||||
|
'nomor_induk' => [
|
||||||
|
'required',
|
||||||
|
function ($attribute, $value, $fail) use ($request) {
|
||||||
|
$label = $request->role == 'siswa' ? 'NISN' : 'NIP/NIK';
|
||||||
|
|
||||||
|
// Cek Nisn/Nip sudah dipakai di tabel users
|
||||||
|
$sudahDipakai = User::where('nisn', $value)->orWhere('nip', $value)->exists();
|
||||||
|
if ($sudahDipakai) {
|
||||||
|
$fail("{$label} ini sudah digunakan oleh akun lain.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($request->role, ['siswa', 'guru'])) {
|
||||||
|
$terdaftar = MasterInduk::where('nomor_induk', $value)
|
||||||
|
->where('role', $request->role)
|
||||||
|
->exists();
|
||||||
|
if (!$terdaftar) {
|
||||||
|
$fail("{$label} tidak terdaftar di data sekolah. Hubungi admin.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'role.in' => 'Pilih role yang valid.',
|
||||||
|
'email.unique' => 'Email sudah terdaftar.',
|
||||||
|
'password.confirmed' => 'Konfirmasi password tidak cocok.'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = new User();
|
||||||
|
$user->name = $request->nama_lengkap;
|
||||||
|
$user->email = $request->email;
|
||||||
|
$user->role = $request->role;
|
||||||
|
$user->password = Hash::make($request->password);
|
||||||
|
$user->no_hp = $request->no_hp;
|
||||||
|
|
||||||
|
// Validasi NISN dan NIP berdasarkan Role
|
||||||
|
if ($request->role == 'siswa') {
|
||||||
|
$user->nisn = $request->nomor_induk;
|
||||||
|
$user->kelas = $request->kelas;
|
||||||
|
$user->golongan = $request->golongan;
|
||||||
|
} else {
|
||||||
|
$user->nip = $request->nomor_induk;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
return redirect()->route('admin.pengguna.index')->with('success', 'Pengguna berhasil ditambahkan.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Menampilkan form untuk mengedit pengguna yang ada.
|
|
||||||
*/
|
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
$pengguna = User::findOrFail($id);
|
$pengguna = User::findOrFail($id);
|
||||||
|
|
||||||
return view('admin.pengguna.edit', [
|
return view('admin.pengguna.edit', [
|
||||||
'pageTitle' => 'Edit Pengguna: ' . $pengguna->nama_lengkap,
|
'pageTitle' => 'Edit Pengguna: ' . $pengguna->nama_lengkap,
|
||||||
'pengguna' => $pengguna,
|
'pengguna' => $pengguna,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, $id)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'nama_lengkap' => 'required|string|max:255',
|
||||||
|
'email' => 'required|email|unique:users,email,' . $id,
|
||||||
|
'role' => 'required|in:siswa,guru,penjaga perpus',
|
||||||
|
'no_hp' => 'nullable|string|max:20',
|
||||||
|
'password' => 'nullable|min:6|confirmed',
|
||||||
|
'nomor_induk' => [
|
||||||
|
'required',
|
||||||
|
function ($attribute, $value, $fail) use ($request, $id) {
|
||||||
|
$label = $request->role == 'siswa' ? 'NISN' : 'NIP/NIK';
|
||||||
|
|
||||||
|
// cek nisn/nip sudah dipakai di tabel users (kecuali oleh dirinya sendiri)
|
||||||
|
$sudahDipakai = User::where(function ($query) use ($value) {
|
||||||
|
$query->where('nisn', $value)->orWhere('nip', $value);
|
||||||
|
})->where('id', '!=', $id)->exists();
|
||||||
|
|
||||||
|
if ($sudahDipakai) {
|
||||||
|
$fail("{$label} ini sudah digunakan oleh akun lain.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($request->role, ['siswa', 'guru'])) {
|
||||||
|
$terdaftar = MasterInduk::where('nomor_induk', $value)
|
||||||
|
->where('role', $request->role)
|
||||||
|
->exists();
|
||||||
|
if (!$terdaftar) {
|
||||||
|
$fail("{$label} tidak terdaftar di data sekolah. Hubungi admin.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = User::findOrFail($id);
|
||||||
|
$user->name = $request->nama_lengkap;
|
||||||
|
$user->email = $request->email;
|
||||||
|
$user->role = $request->role;
|
||||||
|
$user->no_hp = $request->no_hp;
|
||||||
|
|
||||||
|
// Jika password diisi, maka update. Jika kosong, biarkan password lama.
|
||||||
|
if ($request->filled('password')) {
|
||||||
|
$user->password = \Illuminate\Support\Facades\Hash::make($request->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->nisn = null;
|
||||||
|
$user->nip = null;
|
||||||
|
$user->kelas = null;
|
||||||
|
$user->golongan = null;
|
||||||
|
|
||||||
|
// Masukkan kembali sesuai role
|
||||||
|
if ($request->role == 'siswa') {
|
||||||
|
$user->nisn = $request->nomor_induk;
|
||||||
|
$user->kelas = $request->kelas;
|
||||||
|
$user->golongan = $request->golongan;
|
||||||
|
} else {
|
||||||
|
$user->nip = $request->nomor_induk;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
return redirect()->route('admin.pengguna.index')->with('success', 'Data pengguna berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
User::findOrFail($id)->delete();
|
||||||
|
return back()->with('success', 'Pengguna berhasil dihapus.');
|
||||||
|
}
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$validated = $request->validate([
|
$validated = $request->validate([
|
||||||
|
|
@ -100,4 +229,4 @@ public function destroy($id)
|
||||||
|
|
||||||
return redirect()->route('admin.pengguna.index')->with('success', 'Pengguna berhasil dihapus.');
|
return redirect()->route('admin.pengguna.index')->with('success', 'Pengguna berhasil dihapus.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ public function create(): View
|
||||||
// Memproses login admin
|
// Memproses login admin
|
||||||
public function store(LoginRequest $request): RedirectResponse
|
public function store(LoginRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$request->authenticate(); // Menjalankan logika ketat di LoginRequest
|
$request->authenticate();
|
||||||
$request->session()->regenerate();
|
$request->session()->regenerate();
|
||||||
return redirect()->route('admin.dashboard');
|
return redirect()->route('admin.dashboard');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,39 +4,35 @@
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\MasterInduk;
|
||||||
use Illuminate\Auth\Events\Registered;
|
use Illuminate\Auth\Events\Registered;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Validation\Rules;
|
use Illuminate\Validation\Rules;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
|
|
||||||
class RegisteredUserController extends Controller
|
class RegisteredUserController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Menampilkan halaman registrasi.
|
|
||||||
*/
|
|
||||||
public function create(Request $request): View
|
public function create(Request $request): View
|
||||||
{
|
{
|
||||||
// Bagian Pengambilan Role dari URL
|
$role = $request->query('role', 'siswa');
|
||||||
$role = $request->query('role', 'siswa'); // Ambil 'role' dari URL, default ke 'siswa'
|
|
||||||
|
|
||||||
// Kirim $role ke view
|
|
||||||
return view('auth.register', ['role' => $role]);
|
return view('auth.register', ['role' => $role]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Menangani permintaan registrasi yang masuk.
|
|
||||||
*/
|
|
||||||
public function store(Request $request): RedirectResponse
|
public function store(Request $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$role = $request->input('role');
|
$role = $request->input('role');
|
||||||
|
|
||||||
|
|
||||||
$rules = [
|
$rules = [
|
||||||
'name' => ['required', 'string', 'max:255'],
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
||||||
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
||||||
'role' => ['required', 'in:siswa,guru'],
|
'role' => ['required', 'in:siswa,guru'],
|
||||||
|
'role' => ['required', 'in:siswa,guru'],
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($role === 'siswa') {
|
if ($role === 'siswa') {
|
||||||
|
|
@ -47,13 +43,27 @@ public function store(Request $request): RedirectResponse
|
||||||
|
|
||||||
$request->validate($rules);
|
$request->validate($rules);
|
||||||
|
|
||||||
|
|
||||||
|
$nomorInduk = ($role === 'siswa') ? $request->nisn : $request->nip;
|
||||||
|
|
||||||
|
$isWhitelisted = MasterInduk::where('nomor_induk', $nomorInduk)
|
||||||
|
->where('role', $role)
|
||||||
|
->exists();
|
||||||
|
|
||||||
|
if (!$isWhitelisted) {
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
($role === 'siswa' ? 'nisn' : 'nip') => ['Nomor induk tidak terdaftar di Data Sekolah. Hubungi petugas.'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$user = User::create([
|
$user = User::create([
|
||||||
'name' => $request->name,
|
'name' => $request->name,
|
||||||
'nama_lengkap' => $request->name,
|
'email' => $request->email,
|
||||||
'email' => ($request->nisn ?: $request->nip) . '@smkn1perpus.sch.id',
|
|
||||||
'password' => Hash::make($request->password),
|
'password' => Hash::make($request->password),
|
||||||
'role' => $request->role,
|
'role' => $role,
|
||||||
'nomor_induk' => $request->nisn ?: $request->nip,
|
'nisn' => ($role === 'siswa') ? $nomorInduk : null,
|
||||||
|
'nip' => ($role === 'guru') ? $nomorInduk : null,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
event(new Registered($user));
|
event(new Registered($user));
|
||||||
|
|
@ -66,4 +76,4 @@ public function store(Request $request): RedirectResponse
|
||||||
return redirect()->route('dashboard');
|
return redirect()->route('dashboard');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,9 @@
|
||||||
class ProfileController extends Controller
|
class ProfileController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Menampilkan halaman utama profil pengguna secara dinamis berdasarkan role.
|
* Tampilkan halaman profil user.
|
||||||
*/
|
*/
|
||||||
public function index(): RedirectResponse|View
|
public function index(Request $request): View
|
||||||
{
|
{
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
|
|
@ -27,7 +27,6 @@ public function index(): RedirectResponse|View
|
||||||
|
|
||||||
$viewData = ['user' => $user];
|
$viewData = ['user' => $user];
|
||||||
|
|
||||||
// Menyiapkan data berdasarkan role pengguna
|
|
||||||
if ($user->role === 'penjaga perpus') {
|
if ($user->role === 'penjaga perpus') {
|
||||||
// Data untuk Penjaga Perpus: Statistik global & aktivitas terkini
|
// Data untuk Penjaga Perpus: Statistik global & aktivitas terkini
|
||||||
$viewData['statistik'] = [
|
$viewData['statistik'] = [
|
||||||
|
|
@ -43,11 +42,10 @@ public function index(): RedirectResponse|View
|
||||||
'waktu' => $loan->created_at->diffForHumans(),
|
'waktu' => $loan->created_at->diffForHumans(),
|
||||||
'status' => $loan->status,
|
'status' => $loan->status,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} elseif ($user->role === 'guru') {
|
} elseif ($user->role === 'guru') {
|
||||||
// Data untuk Guru
|
// Data untuk Guru
|
||||||
$loans = Loan::with('book')->where('user_id', $user->id)->whereIn('status', ['Dipinjam', 'Terlambat'])->get();
|
$loans = Loan::with('book')->where('user_id', $user->id)->whereIn('status', ['Dipinjam', 'Terlambat'])->get();
|
||||||
|
|
||||||
$viewData['bukuOffline'] = $loans->map(fn($loan) => [
|
$viewData['bukuOffline'] = $loans->map(fn($loan) => [
|
||||||
'judul' => $loan->book->judul,
|
'judul' => $loan->book->judul,
|
||||||
'penulis' => $loan->book->penulis,
|
'penulis' => $loan->book->penulis,
|
||||||
|
|
@ -67,11 +65,10 @@ public function index(): RedirectResponse|View
|
||||||
'buku_terpopuler' => Book::withCount('loans')->orderBy('loans_count', 'desc')->take(3)->get(),
|
'buku_terpopuler' => Book::withCount('loans')->orderBy('loans_count', 'desc')->take(3)->get(),
|
||||||
'insight' => 'Siswa aktif meminjam buku kategori Sains.'
|
'insight' => 'Siswa aktif meminjam buku kategori Sains.'
|
||||||
];
|
];
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Data untuk Siswa
|
// Data untuk Siswa
|
||||||
$loans = Loan::with('book')->where('user_id', $user->id)->whereIn('status', ['Dipinjam', 'Terlambat'])->get();
|
$loans = Loan::with('book')->where('user_id', $user->id)->whereIn('status', ['Dipinjam', 'Terlambat'])->get();
|
||||||
|
|
||||||
$viewData['bukuOffline'] = $loans->map(fn($loan) => [
|
$viewData['bukuOffline'] = $loans->map(fn($loan) => [
|
||||||
'judul' => $loan->book->judul,
|
'judul' => $loan->book->judul,
|
||||||
'penulis' => $loan->book->penulis,
|
'penulis' => $loan->book->penulis,
|
||||||
|
|
@ -98,7 +95,7 @@ public function index(): RedirectResponse|View
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Menampilkan form untuk mengedit profil.
|
* Tampilkan form edit profil.
|
||||||
*/
|
*/
|
||||||
public function edit(Request $request): View
|
public function edit(Request $request): View
|
||||||
{
|
{
|
||||||
|
|
@ -108,9 +105,9 @@ public function edit(Request $request): View
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Memperbarui informasi profil pengguna.
|
* Update data profil ke Database MySQL.
|
||||||
*/
|
*/
|
||||||
public function update(ProfileUpdateRequest $request): RedirectResponse
|
public function update(Request $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
$user->fill($request->validated());
|
$user->fill($request->validated());
|
||||||
|
|
@ -120,13 +117,14 @@ public function update(ProfileUpdateRequest $request): RedirectResponse
|
||||||
$user->email_verified_at = null;
|
$user->email_verified_at = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$user->save();
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
return Redirect::route('profile.edit')->with('status', 'profile-updated');
|
return Redirect::route('profile.edit')->with('status', 'profile-updated');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Menghapus akun pengguna.
|
* Hapus akun user.
|
||||||
*/
|
*/
|
||||||
public function destroy(Request $request): RedirectResponse
|
public function destroy(Request $request): RedirectResponse
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,14 @@
|
||||||
use App\Models\Loan;
|
use App\Models\Loan;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class RiwayatController extends Controller
|
class RiwayatController extends Controller
|
||||||
{
|
{
|
||||||
public function offlineIndex()
|
public function offlineIndex()
|
||||||
{
|
{
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
|
|
||||||
$loans = Loan::with('book.category')
|
$loans = Loan::with('book.category')
|
||||||
->where('user_id', $user->id)
|
->where('user_id', $user->id)
|
||||||
->whereIn('status', ['Dipinjam', 'Dikembalikan', 'Terlambat'])
|
->whereIn('status', ['Dipinjam', 'Dikembalikan', 'Terlambat'])
|
||||||
|
|
@ -80,4 +81,4 @@ public function onlineIndex()
|
||||||
'riwayatOnline' => $riwayatOnline,
|
'riwayatOnline' => $riwayatOnline,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,54 +2,27 @@
|
||||||
|
|
||||||
namespace App\Http\Requests\Auth;
|
namespace App\Http\Requests\Auth;
|
||||||
|
|
||||||
use App\Models\User;
|
use Illuminate\Auth\Events\Lockout;
|
||||||
use App\Services\DummyDataService;
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\RateLimiter;
|
use Illuminate\Support\Facades\RateLimiter;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
use Illuminate\Auth\Events\Lockout;
|
|
||||||
|
|
||||||
class LoginRequest extends FormRequest
|
class LoginRequest extends FormRequest
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Menentukan apakah pengguna diizinkan untuk membuat request ini.
|
|
||||||
* Selalu true karena semua orang boleh mencoba login.
|
|
||||||
*/
|
|
||||||
public function authorize(): bool
|
public function authorize(): bool
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mendapatkan aturan validasi yang berlaku untuk request ini.
|
|
||||||
* Aturan ini dinamis, berubah tergantung pada 'role' yang dikirim dari form.
|
|
||||||
*/
|
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
// Jika form mengirim 'role' dengan nilai 'siswa'...
|
|
||||||
if ($this->input('role') === 'siswa') {
|
|
||||||
// ...maka validasi input 'nisn' dan 'password'.
|
|
||||||
return [
|
|
||||||
'nisn' => ['required', 'string'],
|
|
||||||
'password' => ['required', 'string'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jika tidak (untuk 'guru' dan 'penjaga perpus')
|
|
||||||
return [
|
return [
|
||||||
'nip' => ['required', 'string'],
|
|
||||||
'password' => ['required', 'string'],
|
'password' => ['required', 'string'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mencoba untuk mengautentikasi kredensial dari request.
|
|
||||||
* Ini adalah "otak" dari proses login yang berisi logika paling penting.
|
|
||||||
*
|
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
|
||||||
*/
|
|
||||||
public function authenticate(): void
|
public function authenticate(): void
|
||||||
{
|
{
|
||||||
$this->ensureIsNotRateLimited();
|
$this->ensureIsNotRateLimited();
|
||||||
|
|
@ -98,19 +71,15 @@ public function authenticate(): void
|
||||||
RateLimiter::clear($this->throttleKey());
|
RateLimiter::clear($this->throttleKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Memastikan request login tidak dibatasi karena terlalu banyak percobaan.
|
|
||||||
*/
|
|
||||||
public function ensureIsNotRateLimited(): void
|
public function ensureIsNotRateLimited(): void
|
||||||
{
|
{
|
||||||
// Jika percobaan belum melebihi 5 kali, lanjutkan.
|
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
|
||||||
if (!RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jika sudah lebih dari 5 kali, lemparkan error 'throttle'.
|
|
||||||
event(new Lockout($this));
|
event(new Lockout($this));
|
||||||
$seconds = RateLimiter::availableIn($this->throttleKey());
|
$seconds = RateLimiter::availableIn($this->throttleKey());
|
||||||
|
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'email' => trans('auth.throttle', [
|
'email' => trans('auth.throttle', [
|
||||||
'seconds' => $seconds,
|
'seconds' => $seconds,
|
||||||
|
|
@ -119,14 +88,9 @@ public function ensureIsNotRateLimited(): void
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mendapatkan kunci throttle untuk request ini.
|
|
||||||
* Kunci ini unik untuk setiap pengguna (berdasarkan nisn/email) dan alamat IP.
|
|
||||||
*/
|
|
||||||
public function throttleKey(): string
|
public function throttleKey(): string
|
||||||
{
|
{
|
||||||
// Gunakan 'nisn' jika ada, jika tidak, gunakan 'email' sebagai identitas.
|
$field = $this->input('email') ?? $this->input('nisn') ?? $this->input('nip') ?? 'unknown';
|
||||||
$loginIdentifier = $this->input('nisn') ?: $this->input('nip');
|
return Str::transliterate(Str::lower($field) . '|' . $this->ip());
|
||||||
return Str::transliterate(Str::lower($loginIdentifier) . '|' . $this->ip());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,4 +53,9 @@ protected function casts(): array
|
||||||
'password' => 'hashed',
|
'password' => 'hashed',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getNamaLengkapAttribute()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,14 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use App\Auth\DummyUserProvider;
|
// use App\Auth\DummyUserProvider; // Hapus atau Komen baris ini
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||||
|
|
||||||
class AuthServiceProvider extends ServiceProvider
|
class AuthServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The model to policy mappings for the application.
|
* The model to policy mappings for the application.
|
||||||
*
|
|
||||||
* @var array<class-string, class-string>
|
|
||||||
*/
|
*/
|
||||||
protected $policies = [
|
protected $policies = [
|
||||||
//
|
//
|
||||||
|
|
@ -24,4 +22,4 @@ public function boot(): void
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,26 +2,92 @@
|
||||||
|
|
||||||
namespace Database\Seeders;
|
namespace Database\Seeders;
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\MasterInduk;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class DatabaseSeeder extends Seeder
|
class DatabaseSeeder extends Seeder
|
||||||
{
|
{
|
||||||
/**
|
public function run()
|
||||||
* Seed the application's database.
|
|
||||||
*/
|
|
||||||
public function run(): void
|
|
||||||
{
|
{
|
||||||
// User seeder is already handled or skipped as per user request
|
// Bersihkan data lama
|
||||||
|
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
|
||||||
$this->call([
|
User::truncate();
|
||||||
UserSeeder::class,
|
MasterInduk::truncate();
|
||||||
CategorySeeder::class,
|
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
|
||||||
BookSeeder::class,
|
|
||||||
RecommendationSeeder::class,
|
$whitelist = [
|
||||||
AnnouncementSeeder::class,
|
['nomor_induk' => '1234567890', 'role' => 'siswa', 'nama_pemilik' => 'Silvi Rahmawati'],
|
||||||
LoanSeeder::class,
|
['nomor_induk' => '9988776655', 'role' => 'siswa', 'nama_pemilik' => 'Siti Nurhaliza'],
|
||||||
|
['nomor_induk' => '5566778899', 'role' => 'siswa', 'nama_pemilik' => 'Andi Pratama'],
|
||||||
|
['nomor_induk' => '198506152010012', 'role' => 'guru', 'nama_pemilik' => 'Rina Marlina'],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($whitelist as $w) {
|
||||||
|
MasterInduk::create($w);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ISI USER ASLI
|
||||||
|
|
||||||
|
// ID 1: Silvi (Siswa)
|
||||||
|
User::create([
|
||||||
|
'id' => 1,
|
||||||
|
'name' => 'Silvi Rahmawati',
|
||||||
|
'email' => 'silvi.rahmawati@smkn1perpus.sch.id',
|
||||||
|
'password' => Hash::make('password'),
|
||||||
|
'role' => 'siswa',
|
||||||
|
'nisn' => '1234567890',
|
||||||
|
'no_hp' => '08123456789',
|
||||||
|
'kelas' => 'XII RPL',
|
||||||
|
'golongan' => 'A'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// ID 2: Budi (Admin/Penjaga)
|
||||||
|
User::create([
|
||||||
|
'id' => 2,
|
||||||
|
'name' => 'Budi Santoso',
|
||||||
|
'email' => 'budi.santoso@smkn1perpus.sch.id',
|
||||||
|
'password' => Hash::make('password'),
|
||||||
|
'role' => 'penjaga perpus',
|
||||||
|
'nip' => '197812312005011',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// ID 3: Siti (Siswa)
|
||||||
|
User::create([
|
||||||
|
'id' => 3,
|
||||||
|
'name' => 'Siti Nurhaliza',
|
||||||
|
'email' => 'siti.nurhaliza@smkn1perpus.sch.id',
|
||||||
|
'password' => Hash::make('password'),
|
||||||
|
'role' => 'siswa',
|
||||||
|
'nisn' => '9988776655',
|
||||||
|
'no_hp' => '081998877665',
|
||||||
|
'kelas' => 'XII RPL',
|
||||||
|
'golongan' => 'B'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// ID 4: Andi (Siswa)
|
||||||
|
User::create([
|
||||||
|
'id' => 4,
|
||||||
|
'name' => 'Andi Pratama',
|
||||||
|
'email' => 'andi.pratama@smkn1perpus.sch.id',
|
||||||
|
'password' => Hash::make('password'),
|
||||||
|
'role' => 'siswa',
|
||||||
|
'nisn' => '5566778899',
|
||||||
|
'no_hp' => '081556677889',
|
||||||
|
'kelas' => 'XII RPL',
|
||||||
|
'golongan' => 'C'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// ID 5: Rina (Guru)
|
||||||
|
User::create([
|
||||||
|
'id' => 5,
|
||||||
|
'name' => 'Rina Marlina',
|
||||||
|
'email' => 'rina.marlina@smkn1perpus.sch.id',
|
||||||
|
'password' => Hash::make('password'),
|
||||||
|
'role' => 'guru',
|
||||||
|
'nip' => '198506152010012',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
<select name="category_id" class="form-select" id="category_id" required>
|
<select name="category_id" class="form-select" id="category_id" required>
|
||||||
<option value="" disabled selected>Pilih Kategori</option>
|
<option value="" disabled selected>Pilih Kategori</option>
|
||||||
@foreach($categories as $category)
|
@foreach($categories as $category)
|
||||||
<option value="{{ $category->id }}">{{ $category->name }}</option>
|
<option value="{{ $category->id }}">{{ $category->name }}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -48,8 +48,12 @@
|
||||||
placeholder="Contoh: 330">
|
placeholder="Contoh: 330">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
</div>
|
||||||
<label class="form-label">Tipe Akses</label>
|
|
||||||
|
{{-- TIPE AKSES --}}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Tipe Akses</label>
|
||||||
|
<div class="d-flex gap-3">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" name="tipe_akses[]" value="offline" id="tipe_offline">
|
<input class="form-check-input" type="checkbox" name="tipe_akses[]" value="offline" id="tipe_offline">
|
||||||
<label class="form-check-label" for="tipe_offline">Peminjaman
|
<label class="form-check-label" for="tipe_offline">Peminjaman
|
||||||
|
|
@ -72,14 +76,41 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
|
||||||
<div class="d-flex justify-content-end">
|
|
||||||
<button type="submit" class="btn btn-primary">Simpan Buku</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
|
<hr class="my-4">
|
||||||
|
<div class="d-flex justify-content-end">
|
||||||
|
<button type="submit" class="btn btn-primary px-4 fw-bold">
|
||||||
|
<i class="bi bi-save me-2"></i>Simpan Buku
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>z
|
</div>
|
||||||
</x-app-layout>
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// LOGIC SIMPAN
|
||||||
|
document.getElementById('formTambahBuku').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Menyimpan...',
|
||||||
|
timer: 1500,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
}).then(() => {
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: 'Buku baru berhasil ditambahkan.'
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "{{ route('admin.buku.index') }}";
|
||||||
|
}, 1500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
</x-app-layout>
|
||||||
|
|
@ -33,9 +33,9 @@
|
||||||
<label for="category_id" class="form-label">Kategori</label>
|
<label for="category_id" class="form-label">Kategori</label>
|
||||||
<select name="category_id" class="form-select" id="category_id" required>
|
<select name="category_id" class="form-select" id="category_id" required>
|
||||||
@foreach($categories as $category)
|
@foreach($categories as $category)
|
||||||
<option value="{{ $category->id }}" {{ old('category_id', $buku->category_id) == $category->id ? 'selected' : '' }}>
|
<option value="{{ $category->id }}" {{ old('category_id', $buku->category_id) == $category->id ? 'selected' : '' }}>
|
||||||
{{ $category->name }}
|
{{ $category->name }}
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -45,12 +45,12 @@
|
||||||
value="{{ old('tahun', $buku->tahun) }}" required>
|
value="{{ old('tahun', $buku->tahun) }}" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@php
|
@php
|
||||||
$tipe_akses = is_array($buku->tipe_akses)
|
$tipe_akses = is_array($buku->tipe_akses)
|
||||||
? $buku->tipe_akses
|
? $buku->tipe_akses
|
||||||
: [$buku->tipe_akses];
|
: [$buku->tipe_akses];
|
||||||
$isOffline = in_array('offline', $tipe_akses);
|
$isOffline = in_array('offline', $tipe_akses);
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
{{-- Field Kode Buku - Hanya untuk Buku Offline --}}
|
{{-- Field Kode Buku - Hanya untuk Buku Offline --}}
|
||||||
|
|
@ -99,4 +99,28 @@ class="img-thumbnail mt-2" width="150">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
document.getElementById('formEditBuku').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Menyimpan Perubahan...',
|
||||||
|
timer: 800,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
}).then(() => {
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: 'Data buku berhasil diperbarui.'
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "{{ route('admin.buku.index') }}";
|
||||||
|
}, 1500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
@ -9,225 +9,379 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
{{-- NAV TABS --}}
|
||||||
<ul class="nav nav-tabs" id="bukuTab" role="tablist">
|
<ul class="nav nav-tabs" id="bukuTab" role="tablist">
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link active" id="offline-tab" data-bs-toggle="tab"
|
<button class="nav-link active" id="offline-tab" data-bs-toggle="tab"
|
||||||
data-bs-target="#offline-tab-pane" type="button" role="tab">Peminjaman Offline
|
data-bs-target="#offline-tab-pane" type="button" role="tab">Peminjaman Offline (<span
|
||||||
({{ $bukuOffline->count() }})</button>
|
id="countOffline">{{ $bukuOffline->count() }}</span>)</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link" id="online-tab" data-bs-toggle="tab" data-bs-target="#online-tab-pane"
|
<button class="nav-link" id="online-tab" data-bs-toggle="tab" data-bs-target="#online-tab-pane"
|
||||||
type="button" role="tab">Baca Online ({{ $bukuOnline->count() }})</button>
|
type="button" role="tab">Baca Online (<span id="countOnline">{{ $bukuOnline->count()
|
||||||
|
}}</span>)</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link text-warning" id="arsip-tab" data-bs-toggle="tab"
|
||||||
|
data-bs-target="#arsip-tab-pane" type="button" role="tab">
|
||||||
|
<i class="bi bi-archive-fill me-1"></i>Diarsipkan (<span id="countArsip">0</span>)
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="tab-content" id="bukuTabContent">
|
<div class="tab-content" id="bukuTabContent">
|
||||||
{{-- TAB UNTUK BUKU OFFLINE --}}
|
|
||||||
|
{{-- BUKU OFFLINE --}}
|
||||||
<div class="tab-pane fade show active" id="offline-tab-pane" role="tabpanel">
|
<div class="tab-pane fade show active" id="offline-tab-pane" role="tabpanel">
|
||||||
<div class="table-responsive mt-3">
|
<div class="table-responsive mt-3">
|
||||||
<table class="table table-hover">
|
<table class="table table-hover align-middle" id="tableOffline">
|
||||||
<thead>
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th>No</th>
|
<th>No</th>
|
||||||
<th>Cover</th>
|
<th>Cover</th>
|
||||||
<th>Judul</th>
|
<th>Judul</th>
|
||||||
<th>Kode Buku</th>
|
<th>Kode Buku</th>
|
||||||
<th>Penulis</th>
|
<th>Penulis</th>
|
||||||
|
<th>Stok</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th>Aksi</th>
|
<th class="text-center">Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@forelse($bukuOffline as $buku)
|
@forelse($bukuOffline as $buku)
|
||||||
<tr>
|
|
||||||
<td>{{ $loop->iteration }}</td>
|
|
||||||
<td><img src="{{ asset($buku['cover']) }}" alt="{{ $buku['judul'] }}"
|
|
||||||
width="50" class="rounded"></td>
|
|
||||||
<td>{{ $buku['judul'] }}</td>
|
|
||||||
<td>{{ $buku['kode_buku'] }}</td>
|
|
||||||
<td>{{ $buku['penulis'] }}</td>
|
|
||||||
<td>
|
|
||||||
@if ($buku['status'] == 'Tersedia')
|
|
||||||
<span
|
|
||||||
class="badge bg-success-subtle text-success-emphasis">Tersedia</span>
|
|
||||||
@else
|
|
||||||
<span
|
|
||||||
class="badge bg-warning-subtle text-warning-emphasis">Dipinjam</span>
|
|
||||||
@endif
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<button class="btn btn-sm btn-outline-secondary" data-bs-toggle="modal"
|
|
||||||
data-bs-target="#detailBukuModal" data-id="{{ $buku['id'] }}"
|
|
||||||
data-cover="{{ asset($buku['cover']) }}"
|
|
||||||
data-judul="{{ $buku['judul'] }}"
|
|
||||||
data-kode_buku="{{ $buku['kode_buku'] }}"
|
|
||||||
data-penulis="{{ $buku['penulis'] }}"
|
|
||||||
data-kategori="{{ $buku->category->name ?? '-' }}"
|
|
||||||
data-tahun="{{ $buku['tahun'] }}" data-status="{{ $buku['status'] }}">
|
|
||||||
<i class="bi bi-eye-fill"></i> Detail
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@empty
|
|
||||||
<tr>
|
|
||||||
<td colspan="6" class="text-center py-4">Tidak ada data buku offline.</td>
|
|
||||||
</tr>
|
|
||||||
@endforelse
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- TAB UNTUK BUKU ONLINE --}}
|
|
||||||
<div class="tab-pane fade" id="online-tab-pane" role="tabpanel">
|
|
||||||
<div class="table-responsive mt-3">
|
|
||||||
<table class="table table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>No</th>
|
<td>{{ $loop->iteration }}</td>
|
||||||
<th>Cover</th>
|
<td><img src="{{ asset($buku['cover']) }}" alt="{{ $buku['judul'] }}"
|
||||||
<th>Judul</th>
|
width="50" class="rounded"></td>
|
||||||
<th>Penulis</th>
|
<td>{{ $buku['judul'] }}</td>
|
||||||
<th>File PDF</th>
|
<td>{{ $buku['kode_buku'] }}</td>
|
||||||
<th>Aksi</th>
|
<td>{{ $buku['penulis'] }}</td>
|
||||||
</tr>
|
<td>
|
||||||
</thead>
|
@if ($buku['status'] == 'Tersedia')
|
||||||
<tbody>
|
<span
|
||||||
@forelse($bukuOnline as $buku)
|
class="badge bg-success-subtle text-success-emphasis">Tersedia</span>
|
||||||
<tr>
|
@else
|
||||||
<td>{{ $loop->iteration }}</td>
|
<span
|
||||||
<td><img src="{{ asset($buku['cover']) }}" alt="{{ $buku['judul'] }}"
|
class="badge bg-warning-subtle text-warning-emphasis">Dipinjam</span>
|
||||||
width="50" class="rounded"></td>
|
@endif
|
||||||
<td>{{ $buku['judul'] }}</td>
|
</td>
|
||||||
<td>{{ $buku['penulis'] }}</td>
|
<td>
|
||||||
<td><span
|
<button class="btn btn-sm btn-outline-secondary" data-bs-toggle="modal"
|
||||||
class="badge bg-info-subtle text-info-emphasis">{{ $buku['file_pdf'] ?? 'N/A' }}</span>
|
data-bs-target="#detailBukuModal" data-id="{{ $buku['id'] }}"
|
||||||
</td>
|
data-cover="{{ asset($buku['cover']) }}"
|
||||||
<td>
|
data-judul="{{ $buku['judul'] }}"
|
||||||
<button class="btn btn-sm btn-outline-secondary" data-bs-toggle="modal"
|
data-kode_buku="{{ $buku['kode_buku'] }}"
|
||||||
data-bs-target="#detailBukuModal" data-id="{{ $buku['id'] }}"
|
data-penulis="{{ $buku['penulis'] }}"
|
||||||
data-cover="{{ asset($buku['cover']) }}"
|
data-kategori="{{ $buku->category->name ?? '-' }}"
|
||||||
data-judul="{{ $buku['judul'] }}"
|
data-tahun="{{ $buku['tahun'] }}" data-status="{{ $buku['status'] }}">
|
||||||
data-penulis="{{ $buku['penulis'] }}"
|
<i class="bi bi-eye-fill"></i> Detail
|
||||||
data-kategori="{{ $buku->category->name ?? '-' }}"
|
</button>
|
||||||
data-tahun="{{ $buku['tahun'] }}" data-status="Dapat Dibaca Online">
|
<button class="btn btn-sm btn-outline-warning btn-arsipkan"
|
||||||
<i class="bi bi-eye-fill"></i> Detail
|
data-judul="{{ $buku['judul'] }}" title="Arsipkan Buku">
|
||||||
</button>
|
<i class="bi bi-archive-fill"></i> Arsip
|
||||||
</td>
|
</button>
|
||||||
</tr>
|
|
||||||
@empty
|
|
||||||
<tr>
|
|
||||||
<td colspan="6" class="text-center py-4">Tidak ada data buku online.</td>
|
|
||||||
</tr>
|
|
||||||
@endforelse
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr class="empty-row">
|
||||||
|
<td colspan="8" class="text-center py-4 text-muted">Tidak ada data buku offline.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- BUKU ONLINE --}}
|
||||||
|
<div class="tab-pane fade" id="online-tab-pane" role="tabpanel">
|
||||||
|
<div class="table-responsive mt-3">
|
||||||
|
<table class="table table-hover align-middle" id="tableOnline">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>No</th>
|
||||||
|
<th>Cover</th>
|
||||||
|
<th>Judul</th>
|
||||||
|
<th>Penulis</th>
|
||||||
|
<th>File PDF</th>
|
||||||
|
<th class="text-center">Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@forelse($bukuOnline as $buku)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $loop->iteration }}</td>
|
||||||
|
<td><img src="{{ asset($buku['cover']) }}" alt="{{ $buku['judul'] }}"
|
||||||
|
width="50" class="rounded"></td>
|
||||||
|
<td>{{ $buku['judul'] }}</td>
|
||||||
|
<td>{{ $buku['penulis'] }}</td>
|
||||||
|
<td><span
|
||||||
|
class="badge bg-info-subtle text-info-emphasis">{{ $buku['file_pdf'] ?? 'N/A' }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-sm btn-outline-secondary" data-bs-toggle="modal"
|
||||||
|
data-bs-target="#detailBukuModal" data-id="{{ $buku['id'] }}"
|
||||||
|
data-cover="{{ asset($buku['cover']) }}"
|
||||||
|
data-judul="{{ $buku['judul'] }}"
|
||||||
|
data-penulis="{{ $buku['penulis'] }}"
|
||||||
|
data-kategori="{{ $buku->category->name ?? '-' }}"
|
||||||
|
data-tahun="{{ $buku['tahun'] }}" data-status="Dapat Dibaca Online">
|
||||||
|
<i class="bi bi-eye-fill"></i> Detail
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-outline-warning btn-arsipkan"
|
||||||
|
data-judul="{{ $buku['judul'] }}" title="Arsipkan Buku">
|
||||||
|
<i class="bi bi-archive-fill"></i> Arsip
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr class="empty-row">
|
||||||
|
<td colspan="6" class="text-center py-4 text-muted">Tidak ada data buku online.</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- ARSIP --}}
|
||||||
|
<div class="tab-pane fade" id="arsip-tab-pane" role="tabpanel">
|
||||||
|
<div class="table-responsive mt-3">
|
||||||
|
<table class="table table-hover align-middle" id="tableArsip">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>No</th>
|
||||||
|
<th>Cover</th>
|
||||||
|
<th>Judul</th>
|
||||||
|
<th>Penulis</th>
|
||||||
|
<th>Tipe Asal</th>
|
||||||
|
<th class="text-center">Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr class="empty-row-arsip">
|
||||||
|
<td colspan="6" class="text-center py-5 text-muted">
|
||||||
|
<i class="bi bi-inbox fs-1 d-block mb-2 text-secondary opacity-50"></i>
|
||||||
|
Belum ada buku yang diarsipkan.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- MODAL DETAIL BUKU --}}
|
||||||
<div class="modal fade" id="detailBukuModal" tabindex="-1">
|
<div class="modal fade" id="detailBukuModal" tabindex="-1">
|
||||||
<div class="modal-dialog modal-lg">
|
<div class="modal-dialog modal-lg">
|
||||||
<div class="modal-content">
|
<div class="modal-content border-0 shadow">
|
||||||
<div class="modal-header">
|
<div class="modal-header border-0">
|
||||||
<h5 class="modal-title fw-bold" id="modalJudul">Detail Buku</h5>
|
<h5 class="modal-title fw-bold" id="modalJudul">Detail Buku</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4 text-center mb-3">
|
||||||
<img src="" id="modalCover" class="img-fluid rounded shadow-sm" alt="Cover Buku">
|
<img src="" id="modalCover" class="img-fluid rounded shadow"
|
||||||
|
style="max-height: 250px; object-fit: cover;">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<h3 id="modalJudulContent" class="fw-bold"></h3>
|
<h3 id="modalJudulContent" class="fw-bold text-dark mb-1"></h3>
|
||||||
<p class="text-muted" id="modalPenulis"></p>
|
<p class="text-muted mb-3" id="modalPenulis"></p>
|
||||||
<table class="table table-sm table-borderless">
|
|
||||||
<tr>
|
<div class="bg-light p-3 rounded-3">
|
||||||
<th width="100px">Kategori</th>
|
<table class="table table-sm table-borderless mb-0">
|
||||||
<td id="modalKategori"></td>
|
<tr>
|
||||||
</tr>
|
<td class="text-secondary" width="130">Kategori</td>
|
||||||
<tr id="rowKodeBuku">
|
<td id="modalKategori" class="fw-bold"></td>
|
||||||
<th>Kode Buku</th>
|
</tr>
|
||||||
<td id="modalKode_buku"></td>
|
<tr id="rowKodeBuku">
|
||||||
</tr>
|
<td class="text-secondary">Kode Buku</td>
|
||||||
<tr>
|
<td id="modalKode" class="fw-bold font-monospace"></td>
|
||||||
<th>Tahun</th>
|
</tr>
|
||||||
<td id="modalTahun"></td>
|
<tr>
|
||||||
</tr>
|
<td class="text-secondary">Tahun Terbit</td>
|
||||||
<tr>
|
<td id="modalTahun" class="fw-bold"></td>
|
||||||
<th>Status</th>
|
</tr>
|
||||||
<td><span id="modalStatus" class="badge"></span></td>
|
<tr>
|
||||||
</tr>
|
<td class="text-secondary">Stok</td>
|
||||||
</table>
|
<td id="modalStok" class="fw-bold"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-secondary">Status</td>
|
||||||
|
<td><span id="modalStatus" class="badge"></span></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer border-0 bg-light">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
|
<button type="button" class="btn btn-secondary rounded-pill px-4"
|
||||||
<a href="#" id="modalEditButton" class="btn btn-primary"><i
|
data-bs-dismiss="modal">Tutup</button>
|
||||||
class="bi bi-pencil-fill me-2"></i>Edit Buku</a>
|
<a href="#" id="modalEditButton" class="btn btn-primary rounded-pill px-4">
|
||||||
|
<i class="bi bi-pencil-square me-2"></i>Edit Buku
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const detailBukuModal = document.getElementById('detailBukuModal');
|
|
||||||
if (detailBukuModal) {
|
|
||||||
detailBukuModal.addEventListener('show.bs.modal', event => {
|
|
||||||
const button = event.relatedTarget;
|
|
||||||
|
|
||||||
const id = button.getAttribute('data-id');
|
function updateTableNumbers() {
|
||||||
const cover = button.getAttribute('data-cover');
|
['#tableOffline', '#tableOnline', '#tableArsip'].forEach(tableId => {
|
||||||
const judul = button.getAttribute('data-judul');
|
let count = 0;
|
||||||
const kode_buku = button.getAttribute('data-kode_buku');
|
$(tableId + ' tbody tr').not('[class^="empty-row"]').each(function(index) {
|
||||||
const penulis = button.getAttribute('data-penulis');
|
$(this).find('.row-number').text(index + 1);
|
||||||
const kategori = button.getAttribute('data-kategori');
|
count++;
|
||||||
const tahun = button.getAttribute('data-tahun');
|
|
||||||
const status = button.getAttribute('data-status');
|
|
||||||
|
|
||||||
const editUrl = `{{ url('admin/buku') }}/${id}/edit`;
|
|
||||||
|
|
||||||
const modalJudul = detailBukuModal.querySelector('#modalJudul');
|
|
||||||
const modalCover = detailBukuModal.querySelector('#modalCover');
|
|
||||||
const modalKode_buku = detailBukuModal.querySelector('#modalKode_buku');
|
|
||||||
const modalJudulContent = detailBukuModal.querySelector('#modalJudulContent');
|
|
||||||
const modalPenulis = detailBukuModal.querySelector('#modalPenulis');
|
|
||||||
const modalKategori = detailBukuModal.querySelector('#modalKategori');
|
|
||||||
const modalTahun = detailBukuModal.querySelector('#modalTahun');
|
|
||||||
const modalStatus = detailBukuModal.querySelector('#modalStatus');
|
|
||||||
const modalEditButton = detailBukuModal.querySelector('#modalEditButton');
|
|
||||||
const rowKodeBuku = detailBukuModal.querySelector('#rowKodeBuku');
|
|
||||||
|
|
||||||
modalJudul.textContent = judul;
|
|
||||||
modalCover.src = cover;
|
|
||||||
modalJudulContent.textContent = judul;
|
|
||||||
modalPenulis.textContent = `oleh ${penulis}`;
|
|
||||||
modalKategori.textContent = `: ${kategori}`;
|
|
||||||
modalTahun.textContent = `: ${tahun}`;
|
|
||||||
modalStatus.textContent = status;
|
|
||||||
modalEditButton.href = editUrl;
|
|
||||||
|
|
||||||
// Tampilkan/sembunyikan kode buku berdasarkan ada tidaknya data
|
|
||||||
if (kode_buku && kode_buku !== 'null' && kode_buku !== '') {
|
|
||||||
rowKodeBuku.style.display = '';
|
|
||||||
modalKode_buku.textContent = `: ${kode_buku}`;
|
|
||||||
} else {
|
|
||||||
rowKodeBuku.style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status === 'Tersedia' || status === 'Dapat Dibaca Online') {
|
|
||||||
modalStatus.className = 'badge bg-success-subtle text-success-emphasis';
|
|
||||||
} else {
|
|
||||||
modalStatus.className = 'badge bg-warning-subtle text-warning-emphasis';
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (tableId === '#tableOffline') $('#countOffline').text(count);
|
||||||
|
if (tableId === '#tableOnline') $('#countOnline').text(count);
|
||||||
|
if (tableId === '#tableArsip') {
|
||||||
|
$('#countArsip').text(count);
|
||||||
|
if (count === 0) $('.empty-row-arsip').show();
|
||||||
|
else $('.empty-row-arsip').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// LOGIC MODAL DETAIL
|
||||||
|
$('#detailBukuModal').on('show.bs.modal', function(event) {
|
||||||
|
const button = $(event.relatedTarget);
|
||||||
|
const buku = button.data('buku');
|
||||||
|
|
||||||
|
$('#modalCover').attr('src', "{{ asset('') }}" + buku.cover);
|
||||||
|
$('#modalJudulContent').text(buku.judul);
|
||||||
|
$('#modalPenulis').text('Penulis: ' + buku.penulis);
|
||||||
|
$('#modalKategori').text(buku.kategori);
|
||||||
|
$('#modalTahun').text(buku.tahun);
|
||||||
|
$('#modalStok').text(buku.stok ? buku.stok + ' Buku' : '-');
|
||||||
|
|
||||||
|
if (buku.kode_buku) {
|
||||||
|
$('#rowKodeBuku').show();
|
||||||
|
$('#modalKode').text(buku.kode_buku);
|
||||||
|
} else {
|
||||||
|
$('#rowKodeBuku').hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Status Badge
|
||||||
|
const statusBadge = $('#modalStatus');
|
||||||
|
statusBadge.removeClass().addClass('badge');
|
||||||
|
if (buku.status === 'Tersedia' || !buku.status) {
|
||||||
|
statusBadge.addClass('bg-success-subtle text-success-emphasis').text('Tersedia / Online');
|
||||||
|
} else {
|
||||||
|
statusBadge.addClass('bg-warning-subtle text-warning-emphasis').text('Dipinjam');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#modalEditButton').attr('href', "{{ url('admin/buku') }}/" + buku.id + "/edit");
|
||||||
});
|
});
|
||||||
</script>
|
|
||||||
|
// LOGIC ARSIPKAN BUKU
|
||||||
|
$(document).on('click', '.btn-arsipkan', function() {
|
||||||
|
const row = $(this).closest('tr');
|
||||||
|
const judul = $(this).data('judul');
|
||||||
|
const tipe = row.data('tipe');
|
||||||
|
|
||||||
|
const rowData = row.prop('outerHTML');
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Arsipkan Buku?',
|
||||||
|
text: `Buku "${judul}" akan dipindahkan ke tab Arsip.`,
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Ya, Arsipkan',
|
||||||
|
cancelButtonText: 'Batal',
|
||||||
|
confirmButtonColor: '#ffc107',
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
row.fadeOut(300, function() {
|
||||||
|
const coverHtml = row.find('td:eq(1)').html();
|
||||||
|
const penulis = row.find('td:eq(3)').text();
|
||||||
|
const badgeTipe = tipe === 'offline' ?
|
||||||
|
'<span class="badge bg-secondary"><i class="bi bi-book me-1"></i>Offline</span>' :
|
||||||
|
'<span class="badge bg-info"><i class="bi bi-globe me-1"></i>Online</span>';
|
||||||
|
|
||||||
|
const originalDataEncoded = encodeURIComponent(rowData);
|
||||||
|
|
||||||
|
const arsipRow = `
|
||||||
|
<tr data-origin="${originalDataEncoded}">
|
||||||
|
<td class="row-number"></td>
|
||||||
|
<td>${coverHtml}</td>
|
||||||
|
<td class="fw-bold text-muted">${judul}</td>
|
||||||
|
<td class="text-muted">${penulis}</td>
|
||||||
|
<td>${badgeTipe}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<button class="btn btn-sm btn-outline-success btn-pulihkan"
|
||||||
|
data-judul="${judul}" title="Kembalikan ke Daftar Aktif">
|
||||||
|
<i class="bi bi-arrow-counterclockwise me-1"></i>Kembalikan
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
|
||||||
|
$('#tableArsip tbody').append(arsipRow);
|
||||||
|
$(this).remove();
|
||||||
|
|
||||||
|
updateTableNumbers();
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Diarsipkan',
|
||||||
|
text: `Buku "${judul}" berhasil diarsipkan.`
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// LOGIC PULIHKAN BUKU
|
||||||
|
$(document).on('click', '.btn-pulihkan', function() {
|
||||||
|
const row = $(this).closest('tr');
|
||||||
|
const judul = $(this).data('judul');
|
||||||
|
const originalDataEncoded = row.data('origin');
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Kembalikan Buku?',
|
||||||
|
text: `Buku "${judul}" akan dikembalikan ke daftar aktif.`,
|
||||||
|
icon: 'question',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Ya, Kembalikan',
|
||||||
|
cancelButtonText: 'Batal',
|
||||||
|
confirmButtonColor: '#198754',
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
row.fadeOut(300, function() {
|
||||||
|
const originalRowHtml = decodeURIComponent(originalDataEncoded);
|
||||||
|
const $originalRow = $(originalRowHtml);
|
||||||
|
|
||||||
|
const tipe = $originalRow.data('tipe');
|
||||||
|
const targetTable = tipe === 'offline' ? '#tableOffline' : '#tableOnline';
|
||||||
|
|
||||||
|
$originalRow.removeAttr('style');
|
||||||
|
|
||||||
|
$(targetTable + ' tbody').append($originalRow);
|
||||||
|
$(this).remove();
|
||||||
|
|
||||||
|
updateTableNumbers();
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Dipulihkan',
|
||||||
|
text: `Buku "${judul}" aktif kembali.`
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
@section('page-title', 'Dashboard Admin')
|
@section('page-title', 'Beranda')
|
||||||
|
|
||||||
{{-- Welcome card Section --}}
|
{{-- Welcome card Section --}}
|
||||||
<div class="card border-0 shadow-sm rounded-4 my-4 p-4 position-relative" style="background-color: #CEDEFF;">
|
<div class="card border-0 shadow-sm rounded-4 my-4 p-4 position-relative" style="background-color: #CEDEFF;">
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<div>
|
<div>
|
||||||
<h3 class="my-0 fw-bold">Manajemen Denda & Sanksi</h3>
|
<h3 class="my-0 fw-bold">Manajemen Denda & Sanksi</h3>
|
||||||
<p class="text-muted mb-0">Pantau siswa terlambat dan berikan sanksi jika diperlukan.</p>
|
<p class="text-muted mb-0">Pantau pengguna terlambat dan berikan sanksi jika diperlukan.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -17,9 +17,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<select id="filterKelas" class="form-select form-select-sm">
|
<select id="filterKelas" class="form-select form-select-sm">
|
||||||
<option value="">Semua Kelas</option>
|
<option value="">Semua Kelas/Golongan</option>
|
||||||
@foreach ($listKelas as $kelas)
|
@foreach ($listKelas as $kelas)
|
||||||
<option value="{{ $kelas }}">{{ $kelas }}</option>
|
<option value="{{ $kelas }}">{{ $kelas }}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
<thead class="table-light">
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="text-center" width="5%">NO</th>
|
<th class="text-center" width="5%">NO</th>
|
||||||
<th width="25%">SISWA & KELAS</th>
|
<th width="25%">NAMA</th>
|
||||||
<th width="25%">BUKU TERLAMBAT</th>
|
<th width="25%">BUKU TERLAMBAT</th>
|
||||||
<th width="15%">STATUS</th>
|
<th width="15%">STATUS</th>
|
||||||
<th width="15%">DENDA</th>
|
<th width="15%">DENDA</th>
|
||||||
|
|
@ -55,78 +55,86 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@forelse ($siswaTelat as $item)
|
@forelse ($siswaTelat as $item)
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-center">{{ $loop->iteration }}</td>
|
<td class="text-center">{{ $loop->iteration }}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="fw-bold text-dark">{{ $item['peminjam'] }}</div>
|
<div class="fw-bold text-dark">{{ $item['peminjam'] }}</div>
|
||||||
<span
|
<span class="badge bg-light text-secondary border mt-1 mb-1">{{ $item['kelas'] }}</span>
|
||||||
class="badge bg-light text-secondary border mt-1 mb-1">{{ $item['kelas'] }}</span>
|
<div class="small text-muted">
|
||||||
<div class="small text-muted"><i
|
<i class="bi bi-telephone me-1"></i>{{ $item['nomor_hp'] }}
|
||||||
class="bi bi-telephone me-1"></i>{{ $item['nomor_hp'] }}</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ul class="mb-0 ps-3 small text-muted">
|
<ul class="mb-0 ps-3 small text-muted">
|
||||||
@foreach ($item['books'] as $buku)
|
@foreach ($item['books'] as $buku)
|
||||||
<li>{{ $buku['judul'] }}</li>
|
<li>{{ $buku['judul'] }}</li>
|
||||||
@endforeach
|
@endforeach
|
||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
<td data-order="{{ $item['tenggat_kembali']->timestamp }}">
|
|
||||||
<span
|
|
||||||
class="badge bg-danger-subtle text-danger border border-danger-subtle rounded-pill px-3">
|
|
||||||
Telat {{ $item['hari_terlambat'] }} Hari
|
|
||||||
</span>
|
|
||||||
<div class="small text-muted mt-1">
|
|
||||||
Tenggat: {{ $item['tenggat_kembali']->format('d/m/Y') }}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td data-order="{{ $item['total_denda'] }}">
|
{{-- KOLOM STATUS --}}
|
||||||
@if($item['is_guru'])
|
<td data-order="{{ $item['tenggat_kembali']->timestamp }}">
|
||||||
<div class="fw-bold text-success">Bebas Denda</div>
|
@if(isset($item['role']) && strtolower($item['role']) === 'guru')
|
||||||
<small class="text-muted" style="font-size: 0.75rem;">Kebijakan Guru</small>
|
<div class="fw-bold text-muted">-</div>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-danger-subtle text-danger border border-danger-subtle rounded-pill px-3">
|
||||||
|
Telat {{ $item['hari_terlambat'] }} Hari
|
||||||
|
</span>
|
||||||
|
<div class="small text-muted mt-1">
|
||||||
|
Tenggat: {{ $item['tenggat_kembali']->format('d/m/Y') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td data-order="{{ $item['total_denda'] }}">
|
||||||
|
@if($item['is_guru'])
|
||||||
|
<div class="fw-bold text-success">Bebas Denda</div>
|
||||||
|
<small class="text-muted" style="font-size: 0.75rem;">Kebijakan Guru</small>
|
||||||
|
@else
|
||||||
|
<div class="fw-bold text-danger">Rp
|
||||||
|
{{ number_format($item['total_denda'], 0, ',', '.') }}
|
||||||
|
</div>
|
||||||
|
<small class="text-muted" style="font-size: 0.75rem;">Rp 1.000/hari</small>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- KOLOM AKSI --}}
|
||||||
|
<td>
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
{{-- Tombol WA (Muncul untuk semua) --}}
|
||||||
|
<a href="{{ $item['wa_link'] }}" target="_blank"
|
||||||
|
class="btn btn-sm btn-success text-white" title="Tagih via WhatsApp">
|
||||||
|
<i class="bi bi-whatsapp"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{{-- LOGIC TOMBOL AKTIFKAN / SANKSI --}}
|
||||||
|
@if ($item['is_banned'])
|
||||||
|
{{-- Jika sudah dibekukan (Otomatis/Manual), muncul tombol AKTIFKAN --}}
|
||||||
|
<button class="btn btn-sm btn-outline-success btn-aktifkan"
|
||||||
|
data-user-id="{{ $item['user_id'] }}"
|
||||||
|
data-nama="{{ $item['peminjam'] }}" title="Aktifkan Kembali Akun">
|
||||||
|
<i class="bi bi-shield-check"></i> Aktifkan
|
||||||
|
</button>
|
||||||
@else
|
@else
|
||||||
<div class="fw-bold text-danger">Rp
|
{{-- Jika belum dibekukan, muncul tombol SANKSI (Manual) --}}
|
||||||
{{ number_format($item['total_denda'], 0, ',', '.') }}</div>
|
<button class="btn btn-sm btn-outline-danger btn-sanksi"
|
||||||
<small class="text-muted" style="font-size: 0.75rem;">Rp 1.000/hari</small>
|
data-user-id="{{ $item['user_id'] }}"
|
||||||
|
data-nama="{{ $item['peminjam'] }}" title="Berikan Sanksi">
|
||||||
|
<i class="bi bi-slash-circle"></i> Sanksi
|
||||||
|
</button>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</div>
|
||||||
<td>
|
</td>
|
||||||
<div class="d-flex gap-2">
|
</tr>
|
||||||
{{-- Tombol WA --}}
|
|
||||||
<a href="{{ $item['wa_link'] }}" target="_blank"
|
|
||||||
class="btn btn-sm btn-success text-white" title="Tagih via WhatsApp">
|
|
||||||
<i class="bi bi-whatsapp"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
{{-- LOGIC TOMBOL AKTIFKAN / SANKSI --}}
|
|
||||||
@if ($item['is_banned'])
|
|
||||||
{{-- Jika sudah dibekukan (Otomatis/Manual), muncul tombol AKTIFKAN --}}
|
|
||||||
<button class="btn btn-sm btn-outline-success btn-aktifkan"
|
|
||||||
data-user-id="{{ $item['user_id'] }}"
|
|
||||||
data-nama="{{ $item['peminjam'] }}" title="Aktifkan Kembali Akun">
|
|
||||||
<i class="bi bi-shield-check"></i> Aktifkan
|
|
||||||
</button>
|
|
||||||
@else
|
|
||||||
{{-- Jika belum dibekukan, muncul tombol SANKSI (Manual) --}}
|
|
||||||
<button class="btn btn-sm btn-outline-danger btn-sanksi"
|
|
||||||
data-user-id="{{ $item['user_id'] }}"
|
|
||||||
data-nama="{{ $item['peminjam'] }}" title="Berikan Sanksi">
|
|
||||||
<i class="bi bi-slash-circle"></i> Sanksi
|
|
||||||
</button>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="6" class="text-center py-5">
|
<td colspan="6" class="text-center py-5">
|
||||||
<div class="text-muted opacity-50">
|
<div class="text-muted opacity-50">
|
||||||
<i class="bi bi-emoji-smile fs-1 mb-2 d-block"></i>
|
<i class="bi bi-emoji-smile fs-1 mb-2 d-block"></i>
|
||||||
<p class="mb-0">Tidak ada siswa yang terlambat hari ini.</p>
|
<p class="mb-0">Tidak ada buku terlambat hari ini.</p>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
@ -135,154 +143,156 @@ class="btn btn-sm btn-success text-white" title="Tagih via WhatsApp">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
var table = $('#dendaTable').DataTable({
|
var table = $('#dendaTable').DataTable({
|
||||||
order: [
|
order: [
|
||||||
[3, 'desc']
|
[3, 'desc']
|
||||||
],
|
],
|
||||||
|
|
||||||
columnDefs: [{
|
columnDefs: [{
|
||||||
"searchable": false,
|
"searchable": false,
|
||||||
"orderable": false,
|
"orderable": false,
|
||||||
"targets": 0
|
"targets": 0
|
||||||
}],
|
}],
|
||||||
|
|
||||||
language: {
|
language: {
|
||||||
search: "_INPUT_",
|
search: "_INPUT_",
|
||||||
searchPlaceholder: "Cari nama siswa..."
|
searchPlaceholder: "Cari nama peminjam..."
|
||||||
},
|
},
|
||||||
dom: 'rtip'
|
dom: 'rtip'
|
||||||
|
});
|
||||||
|
|
||||||
|
table.on('order.dt search.dt', function() {
|
||||||
|
table.column(0, {
|
||||||
|
search: 'applied',
|
||||||
|
order: 'applied'
|
||||||
|
}).nodes().each(function(cell, i) {
|
||||||
|
cell.innerHTML = i + 1;
|
||||||
});
|
});
|
||||||
|
}).draw();
|
||||||
|
|
||||||
table.on('order.dt search.dt', function() {
|
$.fn.dataTable.ext.search.push(
|
||||||
table.column(0, {
|
function(settings, data, dataIndex) {
|
||||||
search: 'applied',
|
var filterKelas = $('#filterKelas').val();
|
||||||
order: 'applied'
|
var filterBesaran = $('#filterBesaran').val();
|
||||||
}).nodes().each(function(cell, i) {
|
var dataSiswa = data[1] || "";
|
||||||
cell.innerHTML = i + 1;
|
var dataDendaRaw = data[4] || "0";
|
||||||
|
var dataDenda = parseInt(dataDendaRaw.replace(/[^0-9]/g, ''), 10);
|
||||||
|
|
||||||
|
if (filterKelas !== "" && !dataSiswa.includes(filterKelas)) return false;
|
||||||
|
if (filterBesaran === "ringan" && dataDenda >= 10000) return false;
|
||||||
|
if (filterBesaran === "berat" && dataDenda < 10000) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$('#filterKelas, #filterBesaran').change(function() {
|
||||||
|
table.draw();
|
||||||
|
});
|
||||||
|
$('#resetFilter').click(function() {
|
||||||
|
$('#filterKelas').val('');
|
||||||
|
$('#filterBesaran').val('');
|
||||||
|
table.draw();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '.btn-sanksi', function() {
|
||||||
|
const nama = $(this).data('nama');
|
||||||
|
const userId = $(this).data('user-id');
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Nonaktifkan Akun?',
|
||||||
|
text: `Apakah Anda yakin ingin memberikan sanksi pembekuan akun kepada ${nama}?`,
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Ya, Bekukan',
|
||||||
|
confirmButtonColor: '#dc3545',
|
||||||
|
cancelButtonText: 'Batal'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Memproses...',
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
});
|
});
|
||||||
}).draw();
|
|
||||||
|
|
||||||
$.fn.dataTable.ext.search.push(
|
$.ajax({
|
||||||
function(settings, data, dataIndex) {
|
url: '{{ route('
|
||||||
var filterKelas = $('#filterKelas').val();
|
admin.denda.sanksi ') }}',
|
||||||
var filterBesaran = $('#filterBesaran').val();
|
method: 'POST',
|
||||||
var dataSiswa = data[1] || "";
|
data: {
|
||||||
var dataDendaRaw = data[4] || "0";
|
_token: '{{ csrf_token() }}',
|
||||||
var dataDenda = parseInt(dataDendaRaw.replace(/[^0-9]/g, ''), 10);
|
user_id: userId,
|
||||||
|
action: 'ban'
|
||||||
if (filterKelas !== "" && !dataSiswa.includes(filterKelas)) return false;
|
},
|
||||||
if (filterBesaran === "ringan" && dataDenda >= 10000) return false;
|
success: function(response) {
|
||||||
if (filterBesaran === "berat" && dataDenda < 10000) return false;
|
if (response.status === 'success') {
|
||||||
|
Toast.fire({
|
||||||
return true;
|
icon: 'success',
|
||||||
}
|
title: 'Sanksi Diterapkan',
|
||||||
);
|
text: response.message
|
||||||
|
});
|
||||||
$('#filterKelas, #filterBesaran').change(function() {
|
setTimeout(() => location.reload(), 1500);
|
||||||
table.draw();
|
} else {
|
||||||
});
|
modernSwal.fire('Gagal', response.message, 'error');
|
||||||
$('#resetFilter').click(function() {
|
|
||||||
$('#filterKelas').val('');
|
|
||||||
$('#filterBesaran').val('');
|
|
||||||
table.draw();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('click', '.btn-sanksi', function() {
|
|
||||||
const nama = $(this).data('nama');
|
|
||||||
const userId = $(this).data('user-id');
|
|
||||||
|
|
||||||
modernSwal.fire({
|
|
||||||
title: 'Bekukan Akun?',
|
|
||||||
text: `Apakah Anda yakin ingin memberikan sanksi pembekuan akun kepada ${nama}?`,
|
|
||||||
icon: 'warning',
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonText: 'Ya, Bekukan',
|
|
||||||
confirmButtonColor: '#dc3545',
|
|
||||||
cancelButtonText: 'Batal'
|
|
||||||
}).then((result) => {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
modernSwal.fire({
|
|
||||||
title: 'Memproses...',
|
|
||||||
didOpen: () => Swal.showLoading()
|
|
||||||
});
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '{{ route('admin.denda.sanksi') }}',
|
|
||||||
method: 'POST',
|
|
||||||
data: {
|
|
||||||
_token: '{{ csrf_token() }}',
|
|
||||||
user_id: userId,
|
|
||||||
action: 'ban'
|
|
||||||
},
|
|
||||||
success: function(response) {
|
|
||||||
if (response.status === 'success') {
|
|
||||||
Toast.fire({
|
|
||||||
icon: 'success',
|
|
||||||
title: 'Sanksi Diterapkan',
|
|
||||||
text: response.message
|
|
||||||
});
|
|
||||||
setTimeout(() => location.reload(), 1500);
|
|
||||||
} else {
|
|
||||||
modernSwal.fire('Gagal', response.message, 'error');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
modernSwal.fire('Gagal', 'Terjadi kesalahan saat memproses data.', 'error');
|
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
}
|
error: function() {
|
||||||
});
|
modernSwal.fire('Gagal', 'Terjadi kesalahan saat memproses data.', 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$(document).on('click', '.btn-aktifkan', function() {
|
$(document).on('click', '.btn-aktifkan', function() {
|
||||||
const nama = $(this).data('nama');
|
const nama = $(this).data('nama');
|
||||||
const userId = $(this).data('user-id');
|
const userId = $(this).data('user-id');
|
||||||
|
|
||||||
modernSwal.fire({
|
modernSwal.fire({
|
||||||
title: 'Aktifkan Akun?',
|
title: 'Aktifkan Akun?',
|
||||||
text: `Pastikan ${nama} sudah melunasi denda. Akun akan diaktifkan kembali.`,
|
text: `Pastikan ${nama} sudah melunasi denda. Akun akan diaktifkan kembali.`,
|
||||||
icon: 'question',
|
icon: 'question',
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
confirmButtonText: 'Ya, Aktifkan',
|
confirmButtonText: 'Ya, Aktifkan',
|
||||||
confirmButtonColor: '#198754',
|
confirmButtonColor: '#198754',
|
||||||
cancelButtonText: 'Batal'
|
cancelButtonText: 'Batal'
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
modernSwal.fire({
|
modernSwal.fire({
|
||||||
title: 'Memproses...',
|
title: 'Memproses...',
|
||||||
didOpen: () => Swal.showLoading()
|
didOpen: () => Swal.showLoading()
|
||||||
});
|
});
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '{{ route('admin.denda.sanksi') }}',
|
url: '{{ route('
|
||||||
method: 'POST',
|
admin.denda.sanksi ') }}',
|
||||||
data: {
|
method: 'POST',
|
||||||
_token: '{{ csrf_token() }}',
|
data: {
|
||||||
user_id: userId,
|
_token: '{{ csrf_token() }}',
|
||||||
action: 'unban'
|
user_id: userId,
|
||||||
},
|
action: 'unban'
|
||||||
success: function(response) {
|
},
|
||||||
if (response.status === 'success') {
|
success: function(response) {
|
||||||
Toast.fire({
|
if (response.status === 'success') {
|
||||||
icon: 'success',
|
Toast.fire({
|
||||||
title: 'Akun Diaktifkan',
|
icon: 'success',
|
||||||
text: response.message
|
title: 'Akun Diaktifkan',
|
||||||
});
|
text: response.message
|
||||||
setTimeout(() => location.reload(), 1500);
|
});
|
||||||
} else {
|
setTimeout(() => location.reload(), 1500);
|
||||||
modernSwal.fire('Gagal', response.message, 'error');
|
} else {
|
||||||
}
|
modernSwal.fire('Gagal', response.message, 'error');
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
modernSwal.fire('Gagal', 'Terjadi kesalahan saat memproses data.', 'error');
|
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
}
|
error: function() {
|
||||||
});
|
modernSwal.fire('Gagal', 'Terjadi kesalahan saat memproses data.', 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
});
|
||||||
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
@ -29,15 +29,17 @@
|
||||||
<h5 class="fw-bold mb-3">Data Peminjaman</h5>
|
<h5 class="fw-bold mb-3">Data Peminjaman</h5>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="peminjam_id" class="form-label">Pilih Peminjam (Siswa/Guru)</label>
|
<label for="peminjam_id" class="form-label">Pilih Peminjam (Siswa/Guru)</label>
|
||||||
|
<select class="form-control" id="peminjam_id" name="peminjam_id" placeholder="Cari nama atau email...">
|
||||||
<select class="form-control" id="peminjam_id" name="peminjam_id"
|
|
||||||
placeholder="Cari nama atau email...">
|
|
||||||
<option value="">Pilih...</option>
|
<option value="">Pilih...</option>
|
||||||
@foreach ($groupedUsers as $role => $users)
|
@foreach ($groupedUsers as $role => $users)
|
||||||
<optgroup label="{{ ucfirst($role) }}">
|
<optgroup label="{{ ucfirst($role) }}">
|
||||||
@foreach ($users as $user)
|
@foreach ($users as $user)
|
||||||
{{-- Logic Disable User --}}
|
|
||||||
<option value="{{ $user['id'] }}"
|
<option value="{{ $user['id'] }}"
|
||||||
|
data-role="{{ strtolower($role) }}"
|
||||||
|
data-identitas="{{ $user['nip'] ?? $user['nisn'] ?? '-' }}"
|
||||||
|
data-kontak="{{ $user['no_hp'] ?? '-' }}"
|
||||||
|
data-info="{{ strtolower($role) == 'guru' ? ($user['jabatan'] ?? 'Guru') : ($user['kelas'] ?? 'Siswa') }}"
|
||||||
{{ $user['disabled'] ? 'disabled' : '' }}>
|
{{ $user['disabled'] ? 'disabled' : '' }}>
|
||||||
{{ $user['nama_lengkap'] }} {{ $user['status_text'] }}
|
{{ $user['nama_lengkap'] }} {{ $user['status_text'] }}
|
||||||
</option>
|
</option>
|
||||||
|
|
@ -47,16 +49,24 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="detailPeminjamCard" class="alert alert-secondary d-none mb-3">
|
||||||
|
<h6 class="fw-bold mb-2 border-bottom pb-1"><i class="bi bi-person-badge me-2"></i>Detail Identitas</h6>
|
||||||
|
<div class="row small">
|
||||||
|
<div class="col-6 mb-1"><span class="text-muted">NIP/NISN:</span> <strong id="lblIdentitas">-</strong></div>
|
||||||
|
<div class="col-6 mb-1"><span class="text-muted">No. HP:</span> <strong id="lblKontak">-</strong></div>
|
||||||
|
<div class="col-6"><span class="text-muted">Jabatan/Kelas:</span> <strong id="lblInfo">-</strong></div>
|
||||||
|
<div class="col-6"><span class="text-muted">Role:</span> <strong id="lblRole" class="text-uppercase">-</strong></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="tanggal_pinjam" class="form-label">Tanggal Pinjam</label>
|
<label for="tanggal_pinjam" class="form-label">Tanggal Pinjam</label>
|
||||||
<input type="text" class="form-control" id="tanggal_pinjam" name="tanggal_pinjam"
|
<input type="text" class="form-control" id="tanggal_pinjam" name="tanggal_pinjam" placeholder="Pilih tanggal pinjam">
|
||||||
placeholder="Pilih tanggal pinjam">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="tanggal_kembali" class="form-label">Tenggat Kembali</label>
|
<label for="tanggal_kembali" class="form-label">Tenggat Kembali</label>
|
||||||
<input type="text" class="form-control" id="tanggal_kembali" name="tanggal_kembali"
|
<input type="text" class="form-control" id="tanggal_kembali" name="tanggal_kembali" placeholder="Pilih tenggat kembali">
|
||||||
placeholder="Pilih tenggat kembali">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -95,8 +105,7 @@
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-text bg-white"><i class="bi bi-search"></i></span>
|
<span class="input-group-text bg-white"><i class="bi bi-search"></i></span>
|
||||||
<input type="text" class="form-control border-start-0" id="searchBuku"
|
<input type="text" class="form-control border-start-0" id="searchBuku" placeholder="Cari judul atau penulis...">
|
||||||
placeholder="Cari judul atau penulis...">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -109,19 +118,15 @@
|
||||||
data-book-kategori="{{ $buku['kategori'] }}">
|
data-book-kategori="{{ $buku['kategori'] }}">
|
||||||
|
|
||||||
<div class="d-flex align-items-center book-item-list"
|
<div class="d-flex align-items-center book-item-list"
|
||||||
onclick="toggleBookSelection(this, {{ $buku['id'] }})"
|
onclick="toggleBookSelection(this, {{ $buku['id'] }})" style="cursor: pointer;">
|
||||||
style="cursor: pointer;">
|
<img src="{{ asset($buku['cover']) }}" alt="Cover" class="rounded me-3" style="width: 50px; height: 70px; object-fit: cover;">
|
||||||
<img src="{{ asset($buku['cover']) }}" alt="Cover" class="rounded me-3"
|
|
||||||
style="width: 50px; height: 70px; object-fit: cover;">
|
|
||||||
<div class="flex-grow-1">
|
<div class="flex-grow-1">
|
||||||
<h6 class="fw-bold mb-1 line-clamp-2">{{ $buku['judul'] }}</h6>
|
<h6 class="fw-bold mb-1 line-clamp-2">{{ $buku['judul'] }}</h6>
|
||||||
<p class="text-muted small mb-1">{{ $buku['penulis'] }}</p>
|
<p class="text-muted small mb-1">{{ $buku['penulis'] }}</p>
|
||||||
<span class="badge bg-info-soft">{{ $buku['kategori'] }}</span>
|
<span class="badge bg-info-soft">{{ $buku['kategori'] }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input class="form-check-input book-checkbox" type="checkbox"
|
<input class="form-check-input book-checkbox" type="checkbox" value="{{ $buku['id'] }}" id="book-check-{{ $buku['id'] }}" style="pointer-events: none;">
|
||||||
value="{{ $buku['id'] }}" id="book-check-{{ $buku['id'] }}"
|
|
||||||
style="pointer-events: none;">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -133,53 +138,47 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
const tomSelect = new TomSelect("#peminjam_id", {
|
const tomSelect = new TomSelect("#peminjam_id", {
|
||||||
create: false,
|
create: false,
|
||||||
sortField: {
|
sortField: { field: "text", direction: "asc" },
|
||||||
field: "text",
|
onChange: function(value) {
|
||||||
direction: "asc"
|
// Munculkan Kartu Detail Peminjam saat Dropdown Berubah
|
||||||
}
|
const selectedOption = this.options[value];
|
||||||
});
|
const detailCard = document.getElementById('detailPeminjamCard');
|
||||||
|
|
||||||
const tglPinjam = flatpickr("#tanggal_pinjam", {
|
if(selectedOption && value !== "") {
|
||||||
dateFormat: "Y-m-d",
|
document.getElementById('lblRole').textContent = selectedOption.dataset.role;
|
||||||
altInput: true,
|
document.getElementById('lblIdentitas').textContent = selectedOption.dataset.identitas;
|
||||||
altFormat: "d/m/Y",
|
document.getElementById('lblKontak').textContent = selectedOption.dataset.kontak;
|
||||||
defaultDate: "today",
|
document.getElementById('lblInfo').textContent = selectedOption.dataset.info;
|
||||||
locale: "id",
|
detailCard.classList.remove('d-none');
|
||||||
onChange: function(selectedDates, dateStr) {
|
} else {
|
||||||
if (selectedDates.length > 0) {
|
detailCard.classList.add('d-none');
|
||||||
tglKembali.set("minDate", new Date(selectedDates[0]).fp_incr(1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const tglKembali = flatpickr("#tanggal_kembali", {
|
const tglPinjam = flatpickr("#tanggal_pinjam", {
|
||||||
dateFormat: "Y-m-d",
|
dateFormat: "Y-m-d", altInput: true, altFormat: "d/m/Y", defaultDate: "today", locale: "id",
|
||||||
altInput: true,
|
onChange: function(selectedDates, dateStr) {
|
||||||
altFormat: "d/m/Y",
|
if (selectedDates.length > 0) tglKembali.set("minDate", new Date(selectedDates[0]).fp_incr(1));
|
||||||
defaultDate: new Date().fp_incr(7),
|
}
|
||||||
locale: "id",
|
|
||||||
minDate: new Date().fp_incr(1)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const tglKembali = flatpickr("#tanggal_kembali", {
|
||||||
|
dateFormat: "Y-m-d", altInput: true, altFormat: "d/m/Y", defaultDate: new Date().fp_incr(7), locale: "id", minDate: new Date().fp_incr(1)
|
||||||
|
});
|
||||||
|
|
||||||
// Logika Pemilihan Buku
|
const MAX_BOOKS_SISWA = 2;
|
||||||
const MAX_BOOKS = 2;
|
|
||||||
let selectedBookIds = new Set();
|
let selectedBookIds = new Set();
|
||||||
const allBooks = new Map();
|
const allBooks = new Map();
|
||||||
|
|
||||||
document.querySelectorAll('.book-option').forEach(el => {
|
document.querySelectorAll('.book-option').forEach(el => {
|
||||||
const id = el.dataset.bookId;
|
const id = el.dataset.bookId;
|
||||||
allBooks.set(id, {
|
allBooks.set(id, { id: id, title: el.querySelector('h6').textContent, author: el.querySelector('p').textContent, cover: el.dataset.bookCover });
|
||||||
id: id,
|
|
||||||
title: el.querySelector('h6').textContent,
|
|
||||||
author: el.querySelector('p').textContent,
|
|
||||||
cover: el.dataset.bookCover
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const daftarBukuPinjamEl = document.getElementById('daftarBukuPinjam');
|
const daftarBukuPinjamEl = document.getElementById('daftarBukuPinjam');
|
||||||
|
|
@ -187,21 +186,14 @@
|
||||||
const counterBukuEl = document.getElementById('counterBuku');
|
const counterBukuEl = document.getElementById('counterBuku');
|
||||||
const emptyStateBukuEl = document.getElementById('emptyStateBuku');
|
const emptyStateBukuEl = document.getElementById('emptyStateBuku');
|
||||||
|
|
||||||
// Fungsi render
|
|
||||||
function renderSelectedBooks() {
|
function renderSelectedBooks() {
|
||||||
daftarBukuPinjamEl.querySelectorAll('.selected-book-item').forEach(el => el.remove());
|
daftarBukuPinjamEl.querySelectorAll('.selected-book-item').forEach(el => el.remove());
|
||||||
hiddenInputsEl.innerHTML = '';
|
hiddenInputsEl.innerHTML = '';
|
||||||
|
emptyStateBukuEl.style.display = selectedBookIds.size === 0 ? 'block' : 'none';
|
||||||
if (selectedBookIds.size === 0) {
|
|
||||||
emptyStateBukuEl.style.display = 'block';
|
|
||||||
} else {
|
|
||||||
emptyStateBukuEl.style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedBookIds.forEach(id => {
|
selectedBookIds.forEach(id => {
|
||||||
const book = allBooks.get(String(id));
|
const book = allBooks.get(String(id));
|
||||||
if (!book) return;
|
if (!book) return;
|
||||||
|
|
||||||
const itemHtml = `
|
const itemHtml = `
|
||||||
<div class="selected-book-item book-item d-flex align-items-start p-3 mb-2 rounded" data-selected-id="${id}">
|
<div class="selected-book-item book-item d-flex align-items-start p-3 mb-2 rounded" data-selected-id="${id}">
|
||||||
<img src="${book.cover}" alt="Cover" class="rounded me-3" style="width: 45px; height: 60px; object-fit: cover;">
|
<img src="${book.cover}" alt="Cover" class="rounded me-3" style="width: 45px; height: 60px; object-fit: cover;">
|
||||||
|
|
@ -209,37 +201,25 @@ function renderSelectedBooks() {
|
||||||
<h6 class="fw-bold mb-0 line-clamp-1">${book.title}</h6>
|
<h6 class="fw-bold mb-0 line-clamp-1">${book.title}</h6>
|
||||||
<p class="text-muted small mb-0">${book.author}</p>
|
<p class="text-muted small mb-0">${book.author}</p>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-sm btn-outline-danger remove-book" onclick="removeBook(${id})">
|
<button type="button" class="btn btn-sm btn-outline-danger remove-book" onclick="removeBook(${id})"><i class="bi bi-trash"></i></button>
|
||||||
<i class="bi bi-trash"></i>
|
</div>`;
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
daftarBukuPinjamEl.insertAdjacentHTML('beforeend', itemHtml);
|
daftarBukuPinjamEl.insertAdjacentHTML('beforeend', itemHtml);
|
||||||
|
hiddenInputsEl.insertAdjacentHTML('beforeend', `<input type="hidden" name="buku_ids[]" value="${id}">`);
|
||||||
const inputHtml = `<input type="hidden" name="buku_ids[]" value="${id}">`;
|
|
||||||
hiddenInputsEl.insertAdjacentHTML('beforeend', inputHtml);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
counterBukuEl.textContent = `${selectedBookIds.size} Buku`;
|
counterBukuEl.textContent = `${selectedBookIds.size} Buku`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fungsi search
|
|
||||||
const searchBukuInput = document.getElementById('searchBuku');
|
|
||||||
searchBukuInput.addEventListener('keyup', function() {
|
|
||||||
const searchTerm = this.value.toLowerCase();
|
|
||||||
document.querySelectorAll('.book-option').forEach(el => {
|
|
||||||
const title = el.dataset.bookTitle;
|
|
||||||
const author = el.dataset.bookAuthor;
|
|
||||||
if (title.includes(searchTerm) || author.includes(searchTerm)) {
|
|
||||||
el.style.display = 'block';
|
|
||||||
} else {
|
|
||||||
el.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Global function untuk toggle selection
|
// Global function untuk toggle selection
|
||||||
window.toggleBookSelection = function(itemElement, id) {
|
window.toggleBookSelection = function(itemElement, id) {
|
||||||
|
const selectEl = document.getElementById('peminjam_id');
|
||||||
|
if(selectEl.value === "") {
|
||||||
|
alert("Silakan pilih Peminjam (Siswa/Guru) terlebih dahulu sebelum memilih buku!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedOption = selectEl.options[selectEl.selectedIndex];
|
||||||
|
const roleUser = selectedOption.dataset.role;
|
||||||
|
|
||||||
const checkbox = itemElement.querySelector('.book-checkbox');
|
const checkbox = itemElement.querySelector('.book-checkbox');
|
||||||
const stringId = String(id);
|
const stringId = String(id);
|
||||||
|
|
||||||
|
|
@ -248,8 +228,8 @@ function renderSelectedBooks() {
|
||||||
checkbox.checked = false;
|
checkbox.checked = false;
|
||||||
itemElement.style.background = 'transparent';
|
itemElement.style.background = 'transparent';
|
||||||
} else {
|
} else {
|
||||||
if (selectedBookIds.size >= MAX_BOOKS) {
|
if (roleUser === 'siswa' && selectedBookIds.size >= MAX_BOOKS_SISWA) {
|
||||||
alert(`Maaf, Anda hanya dapat memilih maksimal ${MAX_BOOKS} buku.`);
|
alert(`Maaf, role Siswa hanya dapat meminjam maksimal ${MAX_BOOKS_SISWA} buku secara bersamaan.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,39 +240,76 @@ function renderSelectedBooks() {
|
||||||
renderSelectedBooks();
|
renderSelectedBooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global function untuk remove
|
|
||||||
window.removeBook = function(id) {
|
window.removeBook = function(id) {
|
||||||
const stringId = String(id);
|
selectedBookIds.delete(String(id));
|
||||||
selectedBookIds.delete(stringId);
|
const itemElement = document.querySelector(`.book-option[data-book-id="${id}"] .book-item-list`);
|
||||||
|
|
||||||
const itemElement = document.querySelector(
|
|
||||||
`.book-option[data-book-id="${id}"] .book-item-list`);
|
|
||||||
if (itemElement) {
|
if (itemElement) {
|
||||||
itemElement.querySelector('.book-checkbox').checked = false;
|
itemElement.querySelector('.book-checkbox').checked = false;
|
||||||
itemElement.style.background = 'transparent';
|
itemElement.style.background = 'transparent';
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSelectedBooks();
|
renderSelectedBooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
const form = document.getElementById('formPeminjaman');
|
// Pencarian
|
||||||
form.reset();
|
document.getElementById('searchBuku').addEventListener('keyup', function() {
|
||||||
|
const searchTerm = this.value.toLowerCase();
|
||||||
tomSelect.clear();
|
document.querySelectorAll('.book-option').forEach(el => {
|
||||||
|
const title = el.dataset.bookTitle;
|
||||||
tglPinjam.setDate("today", false);
|
const author = el.dataset.bookAuthor;
|
||||||
tglKembali.setDate(new Date().fp_incr(7), false);
|
el.style.display = (title.includes(searchTerm) || author.includes(searchTerm)) ? 'block' : 'none';
|
||||||
|
});
|
||||||
selectedBookIds.clear();
|
|
||||||
|
|
||||||
document.querySelectorAll('.book-option').forEach(el => {
|
|
||||||
el.querySelector('.book-checkbox').checked = false;
|
|
||||||
el.querySelector('.book-item-list').style.background = 'transparent';
|
|
||||||
});
|
});
|
||||||
|
|
||||||
renderSelectedBooks();
|
document.getElementById('formPeminjaman').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const peminjam = document.getElementById('peminjam_id').value;
|
||||||
|
const jumlahBuku = selectedBookIds.size;
|
||||||
|
|
||||||
|
// Validasi
|
||||||
|
if (!peminjam) {
|
||||||
|
Toast.fire({ icon: 'warning', title: 'Perhatian', text: 'Pilih peminjam terlebih dahulu!' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (jumlahBuku === 0) {
|
||||||
|
Toast.fire({ icon: 'warning', title: 'Perhatian', text: 'Pilih minimal 1 buku!' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Proses Peminjaman?',
|
||||||
|
text: `Anda akan memproses ${jumlahBuku} buku.`,
|
||||||
|
icon: 'question',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Ya, Proses',
|
||||||
|
cancelButtonText: 'Batal'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
// Loading
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Memproses...',
|
||||||
|
timer: 1000,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
}).then(() => {
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: 'Transaksi peminjaman berhasil disimpan.'
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "{{ route('admin.peminjaman.index') }}";
|
||||||
|
}, 1500);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('formPeminjaman').reset();
|
||||||
|
tomSelect.clear();
|
||||||
|
selectedBookIds.clear();
|
||||||
|
renderSelectedBooks();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
@ -1,26 +1,34 @@
|
||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
@section('page-title', $pageTitle)
|
@section('page-title', $pageTitle)
|
||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-3">
|
||||||
<div>
|
<div>
|
||||||
<h3 class="my-0 fw-bold">Manajemen Peminjaman</h3>
|
<h3 class="my-0 fw-bold">Manajemen Peminjaman</h3>
|
||||||
<p class="text-muted mb-0">Daftar ini hanya menampilkan buku yang masih berstatus "Dipinjam".</p>
|
<p class="text-muted mb-0">Daftar ini hanya menampilkan buku yang masih berstatus "Dipinjam".</p>
|
||||||
</div>
|
</div>
|
||||||
<a href="{{ route('admin.peminjaman.create') }}" class="btn btn-primary">
|
<div class="d-flex align-items-center gap-2">
|
||||||
<i class="bi bi-plus-circle-fill me-2"></i>Buat Peminjaman Manual
|
<form action="#" method="GET" class="d-flex m-0 p-0 bg-white border rounded p-1" onsubmit="alert('Fitur download Excel sedang disiapkan tim Backend'); return false;">
|
||||||
</a>
|
<input type="month" name="bulan_laporan" class="form-control form-control-sm border-0 me-1" required>
|
||||||
|
<button type="submit" class="btn btn-sm btn-success text-nowrap">
|
||||||
|
<i class="bi bi-file-earmark-excel-fill me-1"></i>Excel
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<a href="{{ route('admin.peminjaman.create') }}" class="btn btn-primary text-nowrap">
|
||||||
|
<i class="bi bi-plus-circle-fill me-1"></i>Peminjaman Manual
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card border-0 shadow-sm">
|
<div class="card border-0 shadow-sm">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="peminjamanTable" class="table table-striped table-hover nowrap dt-responsive"
|
<table id="peminjamanTable" class="table table-striped table-hover nowrap dt-responsive" style="width:100%">
|
||||||
style="width:100%">
|
|
||||||
<thead class="table-light">
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th>NO</th>
|
<th>NO</th>
|
||||||
<th>ID PEMINJAMAN</th>
|
<th>ID PEMINJAMAN</th>
|
||||||
<th>NAMA</th>
|
<th>PEMINJAM (JABATAN/KELAS)</th>
|
||||||
<th>JUDUL BUKU</th>
|
<th>JUDUL BUKU</th>
|
||||||
<th>TGL. PINJAM</th>
|
<th>TGL. PINJAM</th>
|
||||||
<th>TENGGAT KEMBALI</th>
|
<th>TENGGAT KEMBALI</th>
|
||||||
|
|
@ -30,199 +38,189 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@php
|
@php
|
||||||
$now = \Carbon\Carbon::now();
|
$now = \Carbon\Carbon::now();
|
||||||
$counter = 1;
|
$counter = 1;
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
@forelse ($peminjamanAktif as $transaksi)
|
@forelse ($peminjamanAktif as $transaksi)
|
||||||
@php
|
@php
|
||||||
$tenggat = $transaksi['tenggat_kembali'];
|
$tenggat = $transaksi['tenggat_kembali'];
|
||||||
$isTerlambat = $now->startOfDay()->isAfter($tenggat->startOfDay());
|
$isTerlambat = $now->startOfDay()->isAfter($tenggat->startOfDay());
|
||||||
$isHariIni = $now->startOfDay()->isSameDay($tenggat->startOfDay());
|
$isHariIni = $now->startOfDay()->isSameDay($tenggat->startOfDay());
|
||||||
$selisihHari = $now->startOfDay()->diffInDays($tenggat->startOfDay(), false);
|
$selisihHari = $now->startOfDay()->diffInDays($tenggat->startOfDay(), false);
|
||||||
|
|
||||||
if ($isTerlambat) {
|
$isGuru = isset($transaksi['role']) && strtolower($transaksi['role']) == 'guru';
|
||||||
$statusClass = 'badge rounded-pill bg-danger-subtle text-danger-emphasis';
|
|
||||||
$statusText =
|
|
||||||
'Terlambat ' . $tenggat->startOfDay()->diffInDays($now->startOfDay()) . ' hari';
|
|
||||||
} elseif ($isHariIni) {
|
|
||||||
$statusClass = 'badge rounded-pill bg-warning-subtle text-warning-emphasis';
|
|
||||||
$statusText = 'Jatuh Tempo Hari Ini';
|
|
||||||
} else {
|
|
||||||
$statusClass = 'badge rounded-pill bg-success-subtle text-success-emphasis';
|
|
||||||
$statusText = 'Sisa ' . abs($selisihHari) . ' hari';
|
|
||||||
}
|
|
||||||
@endphp
|
|
||||||
|
|
||||||
<tr>
|
if ($isTerlambat) {
|
||||||
<td>{{ $counter++ }}</td>
|
if ($isGuru) {
|
||||||
<td>
|
$statusClass = 'badge rounded-pill bg-info-subtle text-info-emphasis';
|
||||||
<span
|
$statusText = 'Terlambat (Bebas Denda)';
|
||||||
class="badge bg-primary-subtle text-primary fw-bold">{{ $transaksi['id_peminjaman'] }}</span>
|
} else {
|
||||||
</td>
|
$statusClass = 'badge rounded-pill bg-danger-subtle text-danger-emphasis';
|
||||||
<td>
|
$statusText = 'Terlambat ' . $tenggat->startOfDay()->diffInDays($now->startOfDay()) . ' hari';
|
||||||
<div class="fw-bold">{{ $transaksi['peminjam'] }}</div>
|
}
|
||||||
<div class="small text-muted">{{ $transaksi['nomor_hp'] }}</div>
|
} elseif ($isHariIni) {
|
||||||
</td>
|
$statusClass = 'badge rounded-pill bg-warning-subtle text-warning-emphasis';
|
||||||
<td>
|
$statusText = 'Jatuh Tempo Hari Ini';
|
||||||
<ul class="mb-0 ps-3 small">
|
} else {
|
||||||
@foreach ($transaksi['books'] as $buku)
|
$statusClass = 'badge rounded-pill bg-success-subtle text-success-emphasis';
|
||||||
<li>{{ $buku['judul'] }}</li>
|
$statusText = 'Sisa ' . abs($selisihHari) . ' hari';
|
||||||
@endforeach
|
}
|
||||||
</ul>
|
@endphp
|
||||||
</td>
|
|
||||||
<td>{{ $transaksi['tanggal_pinjam']->format('d/m/Y') }}</td>
|
|
||||||
<td>{{ $transaksi['tenggat_kembali']->format('d/m/Y') }}</td>
|
|
||||||
<td>
|
|
||||||
<span class="{{ $statusClass }}">{{ $statusText }}</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<button class="btn btn-sm btn-outline-primary" data-bs-toggle="modal"
|
|
||||||
data-bs-target="#modalPengembalian-{{ $transaksi['id_peminjaman'] }}">
|
|
||||||
Proses Pengembalian
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{{-- MODAL PENGEMBALIAN --}}
|
<tr>
|
||||||
<div class="modal fade" id="modalPengembalian-{{ $transaksi['id_peminjaman'] }}"
|
<td>{{ $counter++ }}</td>
|
||||||
tabindex="-1" aria-hidden="true">
|
<td>
|
||||||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
<span class="badge bg-primary-subtle text-primary fw-bold">{{ $transaksi['id_peminjaman'] }}</span>
|
||||||
<div class="modal-content border-0 shadow-lg rounded-3">
|
</td>
|
||||||
<div class="modal-header p-4">
|
<td>
|
||||||
<h5 class="modal-title fw-bold">Proses Pengembalian
|
<div class="fw-bold">{{ $transaksi['peminjam'] }}</div>
|
||||||
({{ count($transaksi['books']) }} Buku)
|
<div class="small text-muted">{{ $transaksi['nomor_hp'] }}</div>
|
||||||
</h5>
|
</td>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"
|
<td>
|
||||||
aria-label="Close"></button>
|
<ul class="mb-0 ps-3 small">
|
||||||
</div>
|
@foreach ($transaksi['books'] as $buku)
|
||||||
<div class="modal-body p-4">
|
<li>{{ $buku['judul'] }}</li>
|
||||||
<div class="alert alert-light border mb-4">
|
@endforeach
|
||||||
<div class="d-flex justify-content-between">
|
</ul>
|
||||||
<span>Peminjam:
|
</td>
|
||||||
<strong>{{ $transaksi['peminjam'] }}</strong></span>
|
<td>{{ $transaksi['tanggal_pinjam']->format('d/m/Y') }}</td>
|
||||||
<span>ID: <strong>{{ $transaksi['id_peminjaman'] }}</strong></span>
|
<td>{{ $transaksi['tenggat_kembali']->format('d/m/Y') }}</td>
|
||||||
</div>
|
<td>
|
||||||
|
<span class="{{ $statusClass }}">{{ $statusText }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-sm btn-outline-primary" data-bs-toggle="modal"
|
||||||
|
data-bs-target="#modalPengembalian-{{ $transaksi['id_peminjaman'] }}">
|
||||||
|
Proses Pengembalian
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{{-- MODAL PENGEMBALIAN --}}
|
||||||
|
<div class="modal fade" id="modalPengembalian-{{ $transaksi['id_peminjaman'] }}" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||||
|
<div class="modal-content border-0 shadow-lg rounded-3">
|
||||||
|
<div class="modal-header p-4">
|
||||||
|
<h5 class="modal-title fw-bold">Proses Pengembalian ({{ count($transaksi['books']) }} Buku)</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body p-4">
|
||||||
|
<div class="alert alert-light border mb-4">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<span>Peminjam: <strong>{{ $transaksi['peminjam'] }}</strong></span>
|
||||||
|
<span>ID: <strong>{{ $transaksi['id_peminjaman'] }}</strong></span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h6 class="fw-bold mb-3">Daftar Buku yang Dikembalikan:</h6>
|
@if($isGuru)
|
||||||
|
<div class="alert alert-info py-2 small mb-3">
|
||||||
|
<i class="bi bi-shield-check me-1"></i> Role Guru: Bebas dari beban denda keterlambatan dan catatan denda/sanksi.
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
@foreach ($transaksi['books'] as $buku)
|
<h6 class="fw-bold mb-3">Daftar Buku yang Dikembalikan:</h6>
|
||||||
<div class="card mb-3 border bg-light book-return-item" data-book-id="{{ $buku['id'] }}">
|
@foreach ($transaksi['books'] as $buku)
|
||||||
<div class="card-body p-3">
|
<div class="card mb-3 border bg-light book-return-item" data-book-id="{{ $buku['id'] }}">
|
||||||
<h6 class="fw-bold text-primary mb-2">{{ $buku['judul'] }}</h6>
|
<div class="card-body p-3">
|
||||||
<div class="row">
|
<h6 class="fw-bold text-primary mb-2">{{ $buku['judul'] }}</h6>
|
||||||
<div class="col-md-6">
|
<div class="row">
|
||||||
<label class="form-label small text-muted mb-1">Kondisi
|
@if(!$isGuru)
|
||||||
Buku</label>
|
<div class="col-md-6">
|
||||||
<div class="d-flex gap-3">
|
<label class="form-label small text-muted mb-1">Kondisi Buku</label>
|
||||||
<div class="form-check">
|
<div class="d-flex gap-3">
|
||||||
<input class="form-check-input radio-kondisi"
|
<div class="form-check">
|
||||||
type="radio"
|
<input class="form-check-input radio-kondisi" type="radio" name="kondisi_{{ $buku['id'] }}_{{ $transaksi['id_peminjaman'] }}" value="baik" checked>
|
||||||
name="kondisi_{{ $buku['id'] }}_{{ $transaksi['id_peminjaman'] }}"
|
<label class="form-check-label small">Baik</label>
|
||||||
value="baik" checked>
|
|
||||||
<label
|
|
||||||
class="form-check-label small">Baik</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input radio-kondisi"
|
|
||||||
type="radio"
|
|
||||||
name="kondisi_{{ $buku['id'] }}_{{ $transaksi['id_peminjaman'] }}"
|
|
||||||
value="rusak">
|
|
||||||
<label
|
|
||||||
class="form-check-label small">Rusak/Hilang</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 denda-rusak-input-wrapper d-none">
|
<div class="form-check">
|
||||||
<label class="form-label small text-muted mb-1">Denda
|
<input class="form-check-input radio-kondisi" type="radio" name="kondisi_{{ $buku['id'] }}_{{ $transaksi['id_peminjaman'] }}" value="rusak">
|
||||||
Kerusakan</label>
|
<label class="form-check-label small">Rusak/Hilang</label>
|
||||||
<input type="number"
|
|
||||||
class="form-control form-control-sm denda-rusak-input"
|
|
||||||
placeholder="0">
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<label class="form-label small text-muted mb-1">
|
|
||||||
<i class="bi bi-pencil-square me-1"></i>Catatan
|
|
||||||
Petugas
|
|
||||||
</label>
|
|
||||||
<textarea class="form-control form-control-sm" rows="2"
|
|
||||||
placeholder="Contoh: Ada coretan di halaman 10, Cover sedikit terlipat, dll..."></textarea>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-6 denda-rusak-input-wrapper d-none">
|
||||||
|
<label class="form-label small text-muted mb-1">Denda Kerusakan</label>
|
||||||
|
<input type="number" class="form-control form-control-sm denda-rusak-input" placeholder="0">
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<label class="form-label small text-muted mb-1"><i class="bi bi-pencil-square me-1"></i>Catatan Petugas</label>
|
||||||
|
<textarea class="form-control form-control-sm" rows="2" placeholder="Contoh: Ada coretan di halaman 10, Cover sedikit terlipat..."></textarea>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="col-12">
|
||||||
|
<span class="badge bg-success-subtle text-success-emphasis border"><i class="bi bi-check-circle me-1"></i> Buku dikembalikan oleh Guru</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
||||||
<span>Denda Keterlambatan ({{ $statusText }})</span>
|
|
||||||
@php
|
|
||||||
$isGuru = ($transaksi['role'] ?? '') === 'guru';
|
|
||||||
$dendaTelat = 0;
|
|
||||||
if ($isTerlambat && !$isGuru) {
|
|
||||||
$hari = $tenggat->startOfDay()->diffInDays($now->startOfDay());
|
|
||||||
$dendaTelat = $hari * 1000;
|
|
||||||
}
|
|
||||||
@endphp
|
|
||||||
{{-- Data Attribute untuk JS --}}
|
|
||||||
@if($isGuru && $isTerlambat)
|
|
||||||
<strong class="text-success denda-keterlambatan-display"
|
|
||||||
data-denda-keterlambatan="0">
|
|
||||||
Bebas Denda
|
|
||||||
</strong>
|
|
||||||
@else
|
|
||||||
<strong class="text-danger denda-keterlambatan-display"
|
|
||||||
data-denda-keterlambatan="{{ $dendaTelat }}">
|
|
||||||
Rp {{ number_format($dendaTelat, 0, ',', '.') }}
|
|
||||||
</strong>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="d-flex justify-content-between align-items-center mb-3 bg-danger bg-opacity-10 p-2 rounded">
|
|
||||||
<span class="fw-bold text-danger">TOTAL YANG HARUS DIBAYAR</span>
|
|
||||||
<strong class="text-danger fs-5 total-denda-display">
|
|
||||||
Rp {{ number_format($dendaTelat, 0, ',', '.') }}
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-check form-switch mb-0">
|
|
||||||
<input class="form-check-input" type="checkbox" role="switch" checked
|
|
||||||
id="waStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
|
||||||
<label class="form-check-label small"
|
|
||||||
for="waStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
|
||||||
Kirim <strong>Bukti Pengembalian</strong> ke WhatsApp siswa
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-switch mb-0">
|
|
||||||
<input class="form-check-input email-toggle" type="checkbox"
|
|
||||||
role="switch" checked
|
|
||||||
id="emailStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
|
||||||
<label class="form-check-label small"
|
|
||||||
for="emailStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
|
||||||
Kirim Bukti Pengembalian</strong> ke Email
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer p-3 bg-light">
|
@endforeach
|
||||||
<button type="button" class="btn btn-outline-secondary"
|
|
||||||
data-bs-dismiss="modal">Batal</button>
|
<hr>
|
||||||
<button type="button" class="btn btn-primary btn-konfirmasi-kembali"
|
|
||||||
data-nama-peminjam="{{ $transaksi['peminjam'] }}"
|
@if(!$isGuru)
|
||||||
data-nomor-hp="{{ $transaksi['nomor_hp'] }}"
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
data-user-id="{{ $transaksi['user_id'] }}">
|
<span>Denda Keterlambatan ({{ $statusText }})</span>
|
||||||
Konfirmasi & Selesai
|
@php
|
||||||
</button>
|
$isGuru = ($transaksi['role'] ?? '') === 'guru';
|
||||||
|
$dendaTelat = 0;
|
||||||
|
if ($isTerlambat && !$isGuru) {
|
||||||
|
if ($isTerlambat && !$isGuru) {
|
||||||
|
$hari = $tenggat->startOfDay()->diffInDays($now->startOfDay());
|
||||||
|
$dendaTelat = $hari * 1000;
|
||||||
|
}
|
||||||
|
@endphp
|
||||||
|
{{-- Data Attribute untuk JS --}}
|
||||||
|
@if($isGuru && $isTerlambat)
|
||||||
|
<strong class="text-success denda-keterlambatan-display"
|
||||||
|
data-denda-keterlambatan="0">
|
||||||
|
Bebas Denda
|
||||||
|
</strong>
|
||||||
|
@else
|
||||||
|
<strong class="text-danger denda-keterlambatan-display"
|
||||||
|
data-denda-keterlambatan="{{ $dendaTelat }}">
|
||||||
|
Rp {{ number_format($dendaTelat, 0, ',', '.') }}
|
||||||
|
</strong>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3 bg-danger bg-opacity-10 p-2 rounded">
|
||||||
|
<span class="fw-bold text-danger">TOTAL YANG HARUS DIBAYAR</span>
|
||||||
|
<strong class="text-danger fs-5 total-denda-display">Rp {{ number_format($dendaTelat, 0, ',', '.') }}</strong>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="form-check form-switch mb-0 mt-3">
|
||||||
|
<input class="form-check-input" type="checkbox" role="switch" checked id="waStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
||||||
|
<label class="form-check-label small" for="waStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
||||||
|
Kirim <strong>Bukti Pengembalian</strong> ke WhatsApp
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-switch mb-0">
|
||||||
|
<input class="form-check-input email-toggle" type="checkbox" role="switch" checked id="emailStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
||||||
|
<label class="form-check-label small" for="emailStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
||||||
|
Kirim <strong>Bukti Pengembalian</strong> ke Email
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer p-3 bg-light">
|
||||||
|
<button type="button" class="btn btn-outline-secondary"
|
||||||
|
data-bs-dismiss="modal">Batal</button>
|
||||||
|
<button type="button" class="btn btn-primary btn-konfirmasi-kembali"
|
||||||
|
data-nama-peminjam="{{ $transaksi['peminjam'] }}"
|
||||||
|
data-nomor-hp="{{ $transaksi['nomor_hp'] }}"
|
||||||
|
data-user-id="{{ $transaksi['user_id'] }}">
|
||||||
|
Konfirmasi & Selesai
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="8" class="text-center py-5">Tidak ada data.</td>
|
<td colspan="8" class="text-center py-5">Tidak ada data.</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
@ -231,200 +229,189 @@ class="d-flex justify-content-between align-items-center mb-3 bg-danger bg-opaci
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('#peminjamanTable').DataTable({
|
$('#peminjamanTable').DataTable({
|
||||||
pageLength: 10,
|
pageLength: 10,
|
||||||
order: [
|
order: [
|
||||||
[0, 'asc']
|
[0, 'asc']
|
||||||
],
|
]
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
function formatRupiah(angka) {
|
function formatRupiah(angka) {
|
||||||
return new Intl.NumberFormat('id-ID', {
|
return new Intl.NumberFormat('id-ID', {
|
||||||
style: 'currency',
|
style: 'currency',
|
||||||
currency: 'IDR',
|
currency: 'IDR',
|
||||||
minimumFractionDigits: 0
|
minimumFractionDigits: 0
|
||||||
}).format(angka).replace(/\s/g, '');
|
}).format(angka).replace(/\s/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function hitungTotalDenda(modal) {
|
function hitungTotalDenda(modal) {
|
||||||
const dendaKeterlambatanEl = modal.querySelector('.denda-keterlambatan-display');
|
const dendaKeterlambatanEl = modal.querySelector('.denda-keterlambatan-display');
|
||||||
const dendaRusakInputs = modal.querySelectorAll('.denda-rusak-input');
|
const totalDendaEl = modal.querySelector('.total-denda-display');
|
||||||
const totalDendaEl = modal.querySelector('.total-denda-display');
|
if (!dendaKeterlambatanEl || !totalDendaEl) return;
|
||||||
|
|
||||||
let dendaKeterlambatan = parseInt(dendaKeterlambatanEl.dataset.dendaKeterlambatan) || 0;
|
let dendaKeterlambatan = parseInt(dendaKeterlambatanEl.dataset.dendaKeterlambatan) || 0;
|
||||||
let totalDendaRusak = 0;
|
let totalDendaRusak = 0;
|
||||||
|
|
||||||
dendaRusakInputs.forEach(input => {
|
modal.querySelectorAll('.denda-rusak-input').forEach(input => {
|
||||||
if (!input.closest('.denda-rusak-input-wrapper').classList.contains('d-none')) {
|
if (!input.closest('.denda-rusak-input-wrapper').classList.contains('d-none')) {
|
||||||
totalDendaRusak += parseInt(input.value) || 0;
|
totalDendaRusak += parseInt(input.value) || 0;
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const totalDenda = dendaKeterlambatan + totalDendaRusak;
|
|
||||||
totalDendaEl.textContent = formatRupiah(totalDenda);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logic Radio Button Kondisi Buku
|
|
||||||
const radioKondisi = document.querySelectorAll('.radio-kondisi');
|
|
||||||
radioKondisi.forEach(radio => {
|
|
||||||
radio.addEventListener('change', function() {
|
|
||||||
const cardBody = this.closest('.card-body');
|
|
||||||
const dendaRusakWrapper = cardBody.querySelector('.denda-rusak-input-wrapper');
|
|
||||||
const dendaRusakInput = cardBody.querySelector('.denda-rusak-input');
|
|
||||||
|
|
||||||
const modal = this.closest('.modal');
|
|
||||||
|
|
||||||
if (this.value === 'rusak') {
|
|
||||||
dendaRusakWrapper.classList.remove('d-none');
|
|
||||||
} else {
|
|
||||||
dendaRusakWrapper.classList.add('d-none');
|
|
||||||
dendaRusakInput.value = 0;
|
|
||||||
}
|
|
||||||
hitungTotalDenda(modal);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Logic Input Denda Rusak
|
|
||||||
const dendaRusakInputs = document.querySelectorAll('.denda-rusak-input');
|
|
||||||
dendaRusakInputs.forEach(input => {
|
|
||||||
input.addEventListener('input', function() {
|
|
||||||
const modal = this.closest('.modal');
|
|
||||||
hitungTotalDenda(modal);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('click', '.btn-konfirmasi-kembali', function() {
|
|
||||||
const nama = $(this).data('nama-peminjam');
|
|
||||||
const hp = $(this).data('nomor-hp');
|
|
||||||
const modalEl = $(this).closest('.modal');
|
|
||||||
const modalInstance = bootstrap.Modal.getInstance(modalEl[0]);
|
|
||||||
const isEmailChecked = modalEl.find('.email-toggle').is(':checked');
|
|
||||||
const isWaChecked = modalEl.find('input[role="switch"][id^="waStrukToggle"]').is(':checked');
|
|
||||||
|
|
||||||
modalInstance.hide();
|
|
||||||
|
|
||||||
modernSwal.fire({
|
|
||||||
title: 'Selesaikan Transaksi?',
|
|
||||||
text: `Buku dari ${nama} akan ditandai sudah kembali.`,
|
|
||||||
icon: 'question',
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonText: 'Ya, Selesaikan',
|
|
||||||
cancelButtonText: 'Batal'
|
|
||||||
}).then((result) => {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
// Loading Simpan DB
|
|
||||||
modernSwal.fire({
|
|
||||||
title: 'Menyimpan Data...',
|
|
||||||
timer: 800,
|
|
||||||
timerProgressBar: true,
|
|
||||||
didOpen: () => Swal.showLoading()
|
|
||||||
}).then(() => {
|
|
||||||
// Prepare Request Data
|
|
||||||
const returnsData = [];
|
|
||||||
const booksList = [];
|
|
||||||
const dendaOverdueTotal = parseInt(modalEl.find('.denda-keterlambatan-display').data('denda-keterlambatan'));
|
|
||||||
const dendaOverduePerBook = dendaOverdueTotal / modalEl.find('.book-return-item').length;
|
|
||||||
|
|
||||||
let totalDendaRusak = 0;
|
|
||||||
modalEl.find('.book-return-item').each(function() {
|
|
||||||
const bookId = $(this).data('book-id');
|
|
||||||
const judul = $(this).find('h6').text();
|
|
||||||
const condition = $(this).find('.radio-kondisi:checked').val();
|
|
||||||
const fineDamage = parseInt($(this).find('.denda-rusak-input').val()) || 0;
|
|
||||||
const notes = $(this).find('textarea').val();
|
|
||||||
|
|
||||||
totalDendaRusak += fineDamage;
|
|
||||||
booksList.push(judul);
|
|
||||||
returnsData.push({
|
|
||||||
book_id: bookId,
|
|
||||||
condition: condition,
|
|
||||||
fine_damage: fineDamage,
|
|
||||||
fine_overdue: Math.round(dendaOverduePerBook),
|
|
||||||
notes: notes
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const userId = modalEl.find('.btn-konfirmasi-kembali').data('user-id');
|
|
||||||
const totalDenda = dendaOverdueTotal + totalDendaRusak;
|
|
||||||
|
|
||||||
// Construct WA Message
|
|
||||||
let waLink = null;
|
|
||||||
if (isWaChecked && hp && hp !== '-') {
|
|
||||||
let phone = hp;
|
|
||||||
if (phone.startsWith('0')) phone = '62' + phone.substring(1);
|
|
||||||
|
|
||||||
let message = `*BUKTI PENGEMBALIAN BUKU*\n\n`;
|
|
||||||
message += `Halo ${nama},\n`;
|
|
||||||
message += `Terima kasih telah mengembalikan buku:\n`;
|
|
||||||
booksList.forEach(b => message += `- ${b}\n`);
|
|
||||||
message += `\n*Status:* Berhasil Dikembalikan\n`;
|
|
||||||
if (totalDenda > 0) {
|
|
||||||
message += `*Total Denda:* Rp ${new Intl.NumberFormat('id-ID').format(totalDenda)}\n`;
|
|
||||||
} else {
|
|
||||||
message += `*Denda:* Bebas Denda\n`;
|
|
||||||
}
|
|
||||||
message += `\n_Simpan pesan ini sebagai bukti pengembalian._`;
|
|
||||||
|
|
||||||
waLink = `https://wa.me/${phone}?text=${encodeURIComponent(message)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loading Kirim Email flow
|
|
||||||
if (isEmailChecked) {
|
|
||||||
const dummyEmail = nama.replace(/\s+/g, '.').toLowerCase() + '@sekolah.sch.id';
|
|
||||||
modernSwal.fire({
|
|
||||||
title: 'Mengirim Email...',
|
|
||||||
html: `Mengirim nota ke: <b>${dummyEmail}</b>`,
|
|
||||||
timer: 2000,
|
|
||||||
timerProgressBar: true,
|
|
||||||
didOpen: () => Swal.showLoading()
|
|
||||||
}).then(() => {
|
|
||||||
finishTransaction(returnsData, userId, waLink);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
finishTransaction(returnsData, userId, waLink);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
modalInstance.show();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
totalDendaEl.textContent = formatRupiah(dendaKeterlambatan + totalDendaRusak);
|
||||||
|
}
|
||||||
|
|
||||||
function finishTransaction(returnsData, userId, waLink) {
|
document.querySelectorAll('.radio-kondisi').forEach(radio => {
|
||||||
$.ajax({
|
radio.addEventListener('change', function() {
|
||||||
url: '{{ route('admin.peminjaman.kembali') }}',
|
const cardBody = this.closest('.card-body');
|
||||||
method: 'POST',
|
const dendaRusakWrapper = cardBody.querySelector('.denda-rusak-input-wrapper');
|
||||||
data: {
|
const dendaRusakInput = cardBody.querySelector('.denda-rusak-input');
|
||||||
_token: '{{ csrf_token() }}',
|
if (this.value === 'rusak') {
|
||||||
user_id: userId,
|
dendaRusakWrapper.classList.remove('d-none');
|
||||||
returns: returnsData
|
} else {
|
||||||
},
|
dendaRusakWrapper.classList.add('d-none');
|
||||||
success: function(response) {
|
dendaRusakInput.value = 0;
|
||||||
if (response.status === 'success') {
|
}
|
||||||
if (waLink) {
|
hitungTotalDenda(this.closest('.modal'));
|
||||||
window.open(waLink, '_blank');
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
Toast.fire({
|
document.querySelectorAll('.denda-rusak-input').forEach(input => {
|
||||||
icon: 'success',
|
input.addEventListener('input', function() {
|
||||||
title: 'Berhasil',
|
hitungTotalDenda(this.closest('.modal'));
|
||||||
text: 'Buku berhasil dikembalikan.'
|
});
|
||||||
});
|
});
|
||||||
setTimeout(() => location.reload(), 1500);
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '.btn-konfirmasi-kembali', function() {
|
||||||
|
const nama = $(this).data('nama-peminjam');
|
||||||
|
const hp = $(this).data('nomor-hp');
|
||||||
|
const modalEl = $(this).closest('.modal');
|
||||||
|
const modalInstance = bootstrap.Modal.getInstance(modalEl[0]);
|
||||||
|
const isEmailChecked = modalEl.find('.email-toggle').is(':checked');
|
||||||
|
const isWaChecked = modalEl.find('input[role="switch"][id^="waStrukToggle"]').is(':checked');
|
||||||
|
|
||||||
|
modalInstance.hide();
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Selesaikan Transaksi?',
|
||||||
|
text: `Buku dari ${nama} akan ditandai sudah kembali.`,
|
||||||
|
icon: 'question',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Ya, Selesaikan',
|
||||||
|
cancelButtonText: 'Batal'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Menyimpan Data...',
|
||||||
|
timer: 800,
|
||||||
|
timerProgressBar: true,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
}).then(() => {
|
||||||
|
// Prepare Request Data
|
||||||
|
const returnsData = [];
|
||||||
|
const booksList = [];
|
||||||
|
const dendaOverdueTotal = parseInt(modalEl.find('.denda-keterlambatan-display').data('denda-keterlambatan'));
|
||||||
|
const dendaOverduePerBook = dendaOverdueTotal / modalEl.find('.book-return-item').length;
|
||||||
|
|
||||||
|
let totalDendaRusak = 0;
|
||||||
|
modalEl.find('.book-return-item').each(function() {
|
||||||
|
const bookId = $(this).data('book-id');
|
||||||
|
const judul = $(this).find('h6').text();
|
||||||
|
const condition = $(this).find('.radio-kondisi:checked').val();
|
||||||
|
const fineDamage = parseInt($(this).find('.denda-rusak-input').val()) || 0;
|
||||||
|
const notes = $(this).find('textarea').val();
|
||||||
|
|
||||||
|
totalDendaRusak += fineDamage;
|
||||||
|
booksList.push(judul);
|
||||||
|
returnsData.push({
|
||||||
|
book_id: bookId,
|
||||||
|
condition: condition,
|
||||||
|
fine_damage: fineDamage,
|
||||||
|
fine_overdue: Math.round(dendaOverduePerBook),
|
||||||
|
notes: notes
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const userId = modalEl.find('.btn-konfirmasi-kembali').data('user-id');
|
||||||
|
const totalDenda = dendaOverdueTotal + totalDendaRusak;
|
||||||
|
|
||||||
|
// Construct WA Message
|
||||||
|
let waLink = null;
|
||||||
|
if (isWaChecked && hp && hp !== '-') {
|
||||||
|
let phone = hp;
|
||||||
|
if (phone.startsWith('0')) phone = '62' + phone.substring(1);
|
||||||
|
|
||||||
|
let message = `*BUKTI PENGEMBALIAN BUKU*\n\n`;
|
||||||
|
message += `Halo ${nama},\n`;
|
||||||
|
message += `Terima kasih telah mengembalikan buku:\n`;
|
||||||
|
booksList.forEach(b => message += `- ${b}\n`);
|
||||||
|
message += `\n*Status:* Berhasil Dikembalikan\n`;
|
||||||
|
if (totalDenda > 0) {
|
||||||
|
message += `*Total Denda:* Rp ${new Intl.NumberFormat('id-ID').format(totalDenda)}\n`;
|
||||||
} else {
|
} else {
|
||||||
modernSwal.fire('Gagal', response.message, 'error');
|
message += `*Denda:* Bebas Denda\n`;
|
||||||
}
|
}
|
||||||
},
|
message += `\n_Simpan pesan ini sebagai bukti pengembalian._`;
|
||||||
error: function(xhr) {
|
|
||||||
modernSwal.fire('Gagal', 'Terjadi kesalahan saat memproses data.', 'error');
|
waLink = `https://wa.me/${phone}?text=${encodeURIComponent(message)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loading Kirim Email flow
|
||||||
|
if (isEmailChecked) {
|
||||||
|
const dummyEmail = nama.replace(/\s+/g, '.').toLowerCase() + '@sekolah.sch.id';
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Mengirim Email...',
|
||||||
|
html: `Mengirim nota ke: <b>${dummyEmail}</b>`,
|
||||||
|
timer: 2000,
|
||||||
|
timerProgressBar: true,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
}).then(() => {
|
||||||
|
finishTransaction(returnsData, userId, waLink);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
finishTransaction(returnsData, userId, waLink);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
modalInstance.show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
|
||||||
|
function finishTransaction(returnsData, userId, waLink) {
|
||||||
|
$.ajax({
|
||||||
|
url: '{{ route('
|
||||||
|
admin.peminjaman.kembali ') }}',
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
_token: '{{ csrf_token() }}',
|
||||||
|
user_id: userId,
|
||||||
|
returns: returnsData
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
if (response.status === 'success') {
|
||||||
|
if (waLink) {
|
||||||
|
window.open(waLink, '_blank');
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: 'Buku berhasil dikembalikan.'
|
||||||
|
});
|
||||||
|
setTimeout(() => location.reload(), 1500);
|
||||||
|
} else {
|
||||||
|
modernSwal.fire('Gagal', response.message, 'error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr) {
|
||||||
|
modernSwal.fire('Gagal', 'Terjadi kesalahan saat memproses data.', 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
@ -11,86 +11,173 @@
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<div class="card border-0 shadow-sm">
|
<div class="card border-0 shadow-sm">
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<div class="card-body">
|
<form action="{{ route('admin.pengguna.store') }}" method="POST" id="formPengguna">
|
||||||
<form action="{{ route('admin.pengguna.store') }}" method="POST">
|
@csrf
|
||||||
@csrf
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="role" class="form-label">Role <span class="text-danger">*</span></label>
|
||||||
|
<select class="form-select @error('role') is-invalid @enderror" id="role" name="role"
|
||||||
|
required onchange="toggleFields()">
|
||||||
|
<option value="" selected disabled>Pilih role terlebih dahulu...</option>
|
||||||
|
<option value="siswa" {{ old('role')=='siswa' ? 'selected' : '' }}>Siswa</option>
|
||||||
|
<option value="guru" {{ old('role')=='guru' ? 'selected' : '' }}>Guru</option>
|
||||||
|
<option value="penjaga perpus" {{ old('role')=='penjaga perpus' ? 'selected' : '' }}>
|
||||||
|
Penjaga Perpustakaan</option>
|
||||||
|
</select>
|
||||||
|
@error('role')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Bagian Form Dinamis --}}
|
||||||
|
<div id="dynamic-form" class="d-none">
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="nama_lengkap" class="form-label">Nama Lengkap</label>
|
<label for="nama_lengkap" class="form-label">Nama Lengkap</label>
|
||||||
<input type="text" name="nama_lengkap" class="form-control" id="nama_lengkap"
|
<input type="text" class="form-control @error('nama_lengkap') is-invalid @enderror"
|
||||||
placeholder="Masukkan nama lengkap" required>
|
id="nama_lengkap" name="nama_lengkap" value="{{ old('nama_lengkap') }}" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="email" class="form-label">Email</label>
|
<label for="nomor_induk" class="form-label" id="label_nomor_induk">NISN / NIP</label>
|
||||||
<input type="email" name="email" class="form-control" id="email"
|
<input type="number" class="form-control @error('nomor_induk') is-invalid @enderror"
|
||||||
placeholder="Masukkan alamat email" required pattern="[^@\s]+@[^@\s]+\.[^@\s]+" title="Masukkan alamat email yang valid">
|
id="nomor_induk" name="nomor_induk" value="{{ old('nomor_induk') }}"
|
||||||
|
placeholder="Masukkan Nomor Induk">
|
||||||
|
@error('nomor_induk')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
|
||||||
<label for="nomor_induk" class="form-label">Nomor Induk (NISN/NUPTK)</label>
|
<div class="row">
|
||||||
<input type="text" name="nomor_induk" class="form-control numeric-only" id="nomor_induk"
|
<div class="col-md-6 mb-3">
|
||||||
placeholder="Masukkan NISN atau NUPTK" inputmode="numeric">
|
<label for="email" class="form-label">Email</label>
|
||||||
|
<input type="email" class="form-control @error('email') is-invalid @enderror"
|
||||||
|
id="email" name="email" value="{{ old('email') }}" required>
|
||||||
|
@error('email')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="no_hp" class="form-label">No. Handphone</label>
|
||||||
|
<input type="text" class="form-control" id="no_hp" name="no_hp"
|
||||||
|
value="{{ old('no_hp') }}" placeholder="Contoh: 08123456789">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
|
||||||
<label for="role" class="form-label">Role</label>
|
<div class="row" id="field_siswa_only" style="display: none;">
|
||||||
<select name="role" class="form-select" id="role" required>
|
<div class="col-md-6 mb-3">
|
||||||
<option value="" selected>Pilih role...</option>
|
<label for="kelas" class="form-label">Kelas</label>
|
||||||
<option value="siswa">Siswa</option>
|
<input type="text" class="form-control" id="kelas" name="kelas"
|
||||||
<option value="guru">Guru</option>
|
value="{{ old('kelas') }}" placeholder="Contoh: XII RPL 1">
|
||||||
<option value="penjaga perpus">Penjaga Perpus</option>
|
</div>
|
||||||
</select>
|
<div class="col-md-6 mb-3">
|
||||||
</div>
|
<label for="golongan" class="form-label">Golongan</label>
|
||||||
<div class="mb-3" id="kelas-container" style="display: none;">
|
<input type="text" class="form-control" id="golongan" name="golongan"
|
||||||
<label for="kelas" class="form-label">Kelas (jika siswa)</label>
|
value="{{ old('golongan') }}" placeholder="Contoh: A/B">
|
||||||
<input type="text" name="kelas" class="form-control" id="kelas" placeholder="Contoh: X IPA 1">
|
</div>
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="phone" class="form-label">Nomor HP</label>
|
|
||||||
<input type="text" name="phone" class="form-control numeric-only" id="phone" placeholder="Masukkan nomor HP" inputmode="numeric">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6 mb-3">
|
<div class="col-md-6 mb-3">
|
||||||
<label for="password" class="form-label">Password</label>
|
<label for="password" class="form-label">Password</label>
|
||||||
<input type="password" name="password" class="form-control" id="password" required>
|
<div class="input-group has-validation">
|
||||||
|
<input type="password"
|
||||||
|
class="form-control @error('password') is-invalid @enderror" id="password"
|
||||||
|
name="password">
|
||||||
|
<button class="btn btn-outline-secondary toggle-password" type="button"
|
||||||
|
data-target="password">
|
||||||
|
<i class="bi bi-eye" id="icon-password"></i>
|
||||||
|
</button>
|
||||||
|
@error('password')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6 mb-3">
|
<div class="col-md-6 mb-3">
|
||||||
<label for="password_confirmation" class="form-label">Konfirmasi Password</label>
|
<label for="password_confirmation" class="form-label">Konfirmasi Password</label>
|
||||||
<input type="password" name="password_confirmation" class="form-control" id="password_confirmation" required>
|
<div class="input-group">
|
||||||
|
<input type="password" class="form-control" id="password_confirmation"
|
||||||
|
name="password_confirmation">
|
||||||
|
<button class="btn btn-outline-secondary toggle-password" type="button"
|
||||||
|
data-target="password_confirmation">
|
||||||
|
<i class="bi bi-eye" id="icon-password_confirmation"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end mt-3">
|
||||||
<button type="submit" class="btn btn-primary">Simpan Pengguna</button>
|
<button type="submit" class="btn btn-primary px-4">Simpan Pengguna</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
|
</form>
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// Numeric only input
|
|
||||||
document.querySelectorAll('.numeric-only').forEach(function(input) {
|
|
||||||
input.addEventListener('input', function(e) {
|
|
||||||
this.value = this.value.replace(/[^0-9]/g, '');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Dynamic Kelas Input
|
|
||||||
const roleSelect = document.getElementById('role');
|
|
||||||
const kelasContainer = document.getElementById('kelas-container');
|
|
||||||
|
|
||||||
function toggleKelas() {
|
|
||||||
if (roleSelect.value === 'siswa') {
|
|
||||||
kelasContainer.style.display = 'block';
|
|
||||||
} else {
|
|
||||||
kelasContainer.style.display = 'none';
|
|
||||||
document.getElementById('kelas').value = ''; // Reset value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
roleSelect.addEventListener('change', toggleKelas);
|
|
||||||
toggleKelas(); // Run on load
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</x-app-layout>
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
function toggleFields() {
|
||||||
|
const role = document.getElementById('role').value;
|
||||||
|
const dynamicForm = document.getElementById('dynamic-form');
|
||||||
|
const labelInduk = document.getElementById('label_nomor_induk');
|
||||||
|
const inputInduk = document.getElementById('nomor_induk');
|
||||||
|
const fieldSiswaOnly = document.getElementById('field_siswa_only');
|
||||||
|
|
||||||
|
if (role) dynamicForm.classList.remove('d-none');
|
||||||
|
|
||||||
|
if (role === 'siswa') {
|
||||||
|
labelInduk.innerHTML = 'NISN <span class="text-danger">*</span>';
|
||||||
|
inputInduk.placeholder = 'Masukkan NISN Siswa';
|
||||||
|
fieldSiswaOnly.style.display = 'flex';
|
||||||
|
} else if (role === 'guru') {
|
||||||
|
labelInduk.innerHTML = 'NIP / NIK <span class="text-danger">*</span>';
|
||||||
|
inputInduk.placeholder = 'Masukkan NIP/NIK Guru';
|
||||||
|
fieldSiswaOnly.style.display = 'none';
|
||||||
|
} else if (role === 'penjaga perpus') {
|
||||||
|
labelInduk.innerHTML = 'NIP / NIK <span class="text-danger">*</span>';
|
||||||
|
inputInduk.placeholder = 'Masukkan NIP/NIK Petugas';
|
||||||
|
fieldSiswaOnly.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', toggleFields);
|
||||||
|
|
||||||
|
document.querySelectorAll('.toggle-password').forEach(function(button) {
|
||||||
|
button.addEventListener('click', function() {
|
||||||
|
const targetId = this.getAttribute('data-target');
|
||||||
|
const input = document.getElementById(targetId);
|
||||||
|
const icon = document.getElementById('icon-' + targetId);
|
||||||
|
|
||||||
|
if (input.type === 'password') {
|
||||||
|
input.type = 'text';
|
||||||
|
icon.classList.replace('bi-eye', 'bi-eye-slash');
|
||||||
|
} else {
|
||||||
|
input.type = 'password';
|
||||||
|
icon.classList.replace('bi-eye-slash', 'bi-eye');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('formPengguna').addEventListener('submit', function() {
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Menyimpan Data...',
|
||||||
|
allowOutsideClick: false,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
@if(session('success'))
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: '{{ session("success") }}'
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
</x-app-layout>
|
||||||
|
|
@ -11,104 +11,122 @@
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<div class="card border-0 shadow-sm">
|
<div class="card border-0 shadow-sm">
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<div class="card-body">
|
<form action="{{ route('admin.pengguna.update', $pengguna->id) }}" method="POST" id="formEditPengguna">
|
||||||
<form action="{{ route('admin.pengguna.update', $pengguna->id) }}" method="POST">
|
@csrf
|
||||||
@csrf
|
@method('PATCH')
|
||||||
@method('PUT')
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="role" class="form-label">Role <span class="text-danger">*</span></label>
|
||||||
|
<select class="form-select @error('role') is-invalid @enderror" id="role" name="role" required onchange="toggleFields()">
|
||||||
|
<option value="siswa" {{ old('role', $pengguna->role) == 'siswa' ? 'selected' : '' }}>Siswa</option>
|
||||||
|
<option value="guru" {{ old('role', $pengguna->role) == 'guru' ? 'selected' : '' }}>Guru</option>
|
||||||
|
<option value="penjaga perpus" {{ old('role', $pengguna->role) == 'penjaga perpus' ? 'selected' : '' }}>Penjaga Perpustakaan</option>
|
||||||
|
</select>
|
||||||
|
@error('role') <div class="invalid-feedback">{{ $message }}</div> @enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="dynamic-form">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="nama_lengkap" class="form-label">Nama Lengkap</label>
|
<label for="nama_lengkap" class="form-label">Nama Lengkap</label>
|
||||||
<input type="text" name="nama_lengkap" class="form-control" id="nama_lengkap"
|
<input type="text" class="form-control @error('nama_lengkap') is-invalid @enderror"
|
||||||
value="{{ old('nama_lengkap', $pengguna->nama_lengkap) }}" required>
|
id="nama_lengkap" name="nama_lengkap" value="{{ old('nama_lengkap', $pengguna->name) }}" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="email" class="form-label">Email</label>
|
@php $oldNomorInduk = old('nomor_induk', $pengguna->role == 'siswa' ? $pengguna->nisn : $pengguna->nip); @endphp
|
||||||
<input type="email" name="email" class="form-control" id="email"
|
<label for="nomor_induk" class="form-label" id="label_nomor_induk">NISN / NIP</label>
|
||||||
value="{{ old('email', $pengguna->email) }}" required pattern="[^@\s]+@[^@\s]+\.[^@\s]+" title="Masukkan alamat email yang valid">
|
<input type="number" class="form-control @error('nomor_induk') is-invalid @enderror"
|
||||||
</div>
|
id="nomor_induk" name="nomor_induk" value="{{ $oldNomorInduk }}" placeholder="Masukkan Nomor Induk">
|
||||||
<div class="mb-3">
|
@error('nomor_induk') <div class="invalid-feedback fw-bold">{{ $message }}</div> @enderror
|
||||||
<label for="nomor_induk" class="form-label">Nomor Induk (NISN/NUPTK)</label>
|
|
||||||
<input type="text" name="nomor_induk" class="form-control numeric-only" id="nomor_induk"
|
|
||||||
value="{{ old('nomor_induk', $pengguna->nomor_induk) }}" inputmode="numeric">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="role" class="form-label">Role</label>
|
|
||||||
<select name="role" class="form-select" id="role" required>
|
|
||||||
<option value="">Pilih role...</option>
|
|
||||||
<option value="siswa" @if (old('role', $pengguna->role) == 'siswa') selected @endif>Siswa
|
|
||||||
</option>
|
|
||||||
<option value="guru" @if (old('role', $pengguna->role) == 'guru') selected @endif>Guru
|
|
||||||
</option>
|
|
||||||
<option value="penjaga perpus" @if (old('role', $pengguna->role) == 'penjaga perpus') selected @endif>
|
|
||||||
Penjaga Perpus</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3" id="kelas-container" style="display: none;">
|
|
||||||
<label for="kelas" class="form-label">Kelas (jika siswa)</label>
|
|
||||||
<input type="text" name="kelas" class="form-control" id="kelas"
|
|
||||||
value="{{ old('kelas', $pengguna->kelas) }}">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="phone" class="form-label">Nomor HP</label>
|
|
||||||
<input type="text" name="phone" class="form-control numeric-only" id="phone"
|
|
||||||
value="{{ old('phone', $pengguna->phone) }}" inputmode="numeric">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6 mb-3">
|
<div class="col-md-6 mb-3">
|
||||||
<label for="password" class="form-label">Password Baru</label>
|
<label for="email" class="form-label">Email</label>
|
||||||
<input type="password" name="password" class="form-control" id="password"
|
<input type="email" class="form-control @error('email') is-invalid @enderror"
|
||||||
placeholder="Kosongkan jika tidak diubah">
|
id="email" name="email" value="{{ old('email', $pengguna->email) }}" required>
|
||||||
|
@error('email') <div class="invalid-feedback">{{ $message }}</div> @enderror
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 mb-3">
|
<div class="col-md-6 mb-3">
|
||||||
<label for="password_confirmation" class="form-label">Konfirmasi Password</label>
|
<label for="no_hp" class="form-label">No. Handphone</label>
|
||||||
<input type="password" name="password_confirmation" class="form-control" id="password_confirmation">
|
<input type="text" class="form-control" id="no_hp" name="no_hp" value="{{ old('no_hp', $pengguna->no_hp) }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
|
||||||
<div class="d-flex justify-content-end">
|
<div class="row" id="field_siswa_only" style="display: none;">
|
||||||
<button type="submit" class="btn btn-primary">Simpan Perubahan</button>
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="kelas" class="form-label">Kelas</label>
|
||||||
|
<input type="text" class="form-control" id="kelas" name="kelas" value="{{ old('kelas', $pengguna->kelas) }}">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="golongan" class="form-label">Golongan</label>
|
||||||
|
<input type="text" class="form-control" id="golongan" name="golongan" value="{{ old('golongan', $pengguna->golongan) }}">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
|
||||||
|
|
||||||
<script>
|
<hr>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// Numeric only input
|
|
||||||
document.querySelectorAll('.numeric-only').forEach(function(input) {
|
|
||||||
input.addEventListener('input', function(e) {
|
|
||||||
this.value = this.value.replace(/[^0-9]/g, '');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Dynamic Kelas Input
|
<div class="row">
|
||||||
const roleSelect = document.getElementById('role');
|
<div class="col-md-6 mb-3">
|
||||||
const kelasContainer = document.getElementById('kelas-container');
|
<label for="password" class="form-label">Password Baru <span class="small text-muted">(opsional)</span></label>
|
||||||
|
<input type="password" class="form-control @error('password') is-invalid @enderror" id="password" name="password" placeholder="Kosongkan jika tidak diubah">
|
||||||
function toggleKelas() {
|
@error('password') <div class="invalid-feedback">{{ $message }}</div> @enderror
|
||||||
if (roleSelect.value === 'siswa') {
|
</div>
|
||||||
kelasContainer.style.display = 'block';
|
<div class="col-md-6 mb-3">
|
||||||
} else {
|
<label for="password_confirmation" class="form-label">Konfirmasi Password Baru</label>
|
||||||
kelasContainer.style.display = 'none';
|
<input type="password" class="form-control" id="password_confirmation" name="password_confirmation" placeholder="Ulangi password baru">
|
||||||
|
</div>
|
||||||
// Optional: Clear value only if changing to non-student to prevent accidental data loss on edit?
|
</div>
|
||||||
// For edit, maybe better NOT to clear immediately unless user saves?
|
|
||||||
// But per request "hide input", clearing might be expected behavior if they change role.
|
|
||||||
// I'll keep it simple: just hide. If they change role to Teacher, they probably want to remove class.
|
|
||||||
// But resetting value on edit might exist data. Let's just hide for now.
|
|
||||||
// Actually, if they SUBMIT, and it is hidden, logic might be needed to clear it in backend or here.
|
|
||||||
// For now, mirroring create behavior (reset logic mainly).
|
|
||||||
// Wait, on Edit, if I load as Guru, it hides. If I change to Siswa, it shows (empty or old value).
|
|
||||||
// If I change Siswa -> Guru, it hides.
|
|
||||||
// For safety in Edit, I won't force clear value on toggle to avoid losing data if they accidentally switch.
|
|
||||||
// Just hide.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
roleSelect.addEventListener('change', toggleKelas);
|
<div class="d-flex justify-content-end mt-3">
|
||||||
toggleKelas(); // Run on load
|
<button type="submit" class="btn btn-primary px-4">Simpan Perubahan</button>
|
||||||
});
|
</div>
|
||||||
</script>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</x-app-layout>
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
function toggleFields() {
|
||||||
|
const role = document.getElementById('role').value;
|
||||||
|
const labelInduk = document.getElementById('label_nomor_induk');
|
||||||
|
const inputInduk = document.getElementById('nomor_induk');
|
||||||
|
const fieldSiswaOnly = document.getElementById('field_siswa_only');
|
||||||
|
|
||||||
|
if (role === 'siswa') {
|
||||||
|
labelInduk.innerHTML = 'NISN <span class="text-danger">*</span>';
|
||||||
|
inputInduk.placeholder = 'Masukkan NISN Siswa';
|
||||||
|
fieldSiswaOnly.style.display = 'flex';
|
||||||
|
} else if (role === 'guru') {
|
||||||
|
labelInduk.innerHTML = 'NIP / NIK <span class="text-danger">*</span>';
|
||||||
|
inputInduk.placeholder = 'Masukkan NIP/NIK Guru';
|
||||||
|
fieldSiswaOnly.style.display = 'none';
|
||||||
|
} else if (role === 'penjaga perpus') {
|
||||||
|
labelInduk.innerHTML = 'NIP / NIK <span class="text-danger">*</span>';
|
||||||
|
inputInduk.placeholder = 'Masukkan NIP/NIK Petugas';
|
||||||
|
fieldSiswaOnly.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.addEventListener('DOMContentLoaded', toggleFields);
|
||||||
|
|
||||||
|
document.getElementById('formEditPengguna').addEventListener('submit', function() {
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Menyimpan Perubahan...',
|
||||||
|
allowOutsideClick: false,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
@if(session('success'))
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: '{{ session("success") }}'
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
</x-app-layout>
|
||||||
|
|
@ -1,66 +1,102 @@
|
||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
@section('page-title', content: 'Manajemen Pengguna')
|
@section('page-title', 'Manajemen Pengguna')
|
||||||
<div class="container-fluid p-0">
|
<div class="container-fluid p-0">
|
||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
<h1 class="h3 text-gray-800">{{ $pageTitle }}</h1>
|
<h1 class="h3 text-gray-800">{{ $pageTitle ?? 'Manajemen Pengguna' }}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card shadow mb-5">
|
<div class="card shadow mb-5">
|
||||||
<div class="card-header py-3">
|
<div class="card-header py-3 d-flex justify-content-between align-items-center flex-wrap gap-2">
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Daftar Pengguna Aktif</h6>
|
<h6 class="m-0 font-weight-bold text-primary">Daftar Pengguna Aktif</h6>
|
||||||
|
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<form action="{{ route('admin.pengguna.index') }}" method="GET" class="me-2 mb-0">
|
||||||
|
<select name="role" class="form-select form-select-sm" onchange="this.form.submit()">
|
||||||
|
<option value="">Semua Kategori</option>
|
||||||
|
<option value="siswa" {{ request('role')=='siswa' ? 'selected' : '' }}>Siswa</option>
|
||||||
|
<option value="guru" {{ request('role')=='guru' ? 'selected' : '' }}>Guru</option>
|
||||||
|
<option value="penjaga perpus" {{ request('role')=='penjaga perpus' ? 'selected' : '' }}>
|
||||||
|
Petugas</option>
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<a href="{{ route('admin.pengguna.create') }}" class="btn btn-sm btn-primary">
|
||||||
|
<i class="bi bi-plus-circle-fill me-1"></i>Tambah Pengguna
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-bordered" width="100%" cellspacing="0">
|
<table class="table table-bordered align-middle" width="100%" cellspacing="0">
|
||||||
<thead>
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th>No</th>
|
<th>No</th>
|
||||||
<th>Nama Lengkap</th>
|
<th>Nama Lengkap</th>
|
||||||
<th>Email</th>
|
<th>Kontak (Email & HP)</th>
|
||||||
<th>Role</th>
|
<th>Role</th>
|
||||||
<th>Nomor Induk</th>
|
<th>NISN / NIP / NIK</th>
|
||||||
<th>Aksi</th>
|
<th>Kelas / Golongan</th>
|
||||||
|
<th class="text-center">Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@forelse($users as $index => $user)
|
@forelse($users as $index => $user)
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ $index + 1 }}</td>
|
<td>{{ $users->firstItem() + $index }}</td>
|
||||||
<td>{{ $user->name }}</td>
|
<td class="fw-bold">{{ $user->name }}</td>
|
||||||
<td>{{ $user->email }}</td>
|
|
||||||
<td>
|
<td>
|
||||||
<span class="badge {{ $user->role == 'guru' ? 'bg-info' : 'bg-primary' }}">
|
<div>{{ $user->email }}</div>
|
||||||
{{ ucfirst($user->role) }}
|
<div class="small text-muted"><i class="bi bi-telephone me-1"></i>{{ $user->no_hp ??
|
||||||
</span>
|
'-' }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ $user->nomor_induk ?? '-' }}
|
@if($user->role == 'guru')
|
||||||
|
<span class="badge bg-info text-dark">Guru</span>
|
||||||
|
@elseif($user->role == 'siswa')
|
||||||
|
<span class="badge bg-primary">Siswa</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-secondary">Petugas</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="font-monospace text-primary">
|
||||||
|
{{ $user->nisn ?? ($user->nip ?? '-') }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex gap-2">
|
@if($user->role == 'siswa')
|
||||||
<a href="{{ route('admin.pengguna.edit', $user->id) }}" class="btn btn-sm btn-warning">
|
<span class="badge bg-light text-black border">Kelas: {{ $user->kelas ?? '-' }} / {{
|
||||||
<i class="bi bi-pencil"></i> Edit
|
$user->golongan ?? '-' }}</span>
|
||||||
</a>
|
@else
|
||||||
<form action="{{ route('admin.pengguna.destroy', $user->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Yakin hapus user ini?')">
|
-
|
||||||
@csrf
|
@endif
|
||||||
@method('DELETE')
|
</td>
|
||||||
<button type="submit" class="btn btn-sm btn-danger">
|
<td class="text-center">
|
||||||
<i class="bi bi-trash"></i> Hapus
|
<a href="{{ route('admin.pengguna.edit', $user->id) }}"
|
||||||
</button>
|
class="btn btn-sm btn-warning">
|
||||||
</form>
|
<i class="bi bi-pencil"></i> Edit
|
||||||
</div>
|
</a>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary btn-reset-password"
|
||||||
|
data-nama="{{ $user->name }}" title="Reset Password (OTP)">
|
||||||
|
<i class="bi bi-key-fill"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<form action="{{ route('admin.pengguna.destroy', $user->id) }}" method="POST"
|
||||||
|
class="d-inline form-delete-user" data-nama="{{ $user->name }}">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button type="button" class="btn btn-sm btn-danger btn-hapus"><i
|
||||||
|
class="bi bi-trash"></i></button>
|
||||||
|
</form>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="6" class="text-center">Belum ada pengguna terdaftar.</td>
|
<td colspan="7" class="text-center py-4 text-muted">Belum ada pengguna terdaftar.</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
{{-- Pagination --}}
|
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
{{ $users->links() }}
|
{{ $users->links() }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -70,14 +106,13 @@
|
||||||
|
|
||||||
<hr class="my-5 border-4">
|
<hr class="my-5 border-4">
|
||||||
|
|
||||||
|
{{-- BAGIAN DATA INDUK (WHITELIST) --}}
|
||||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
<div>
|
<div>
|
||||||
<h4 class="fw-bold text-success mb-1">
|
<h4 class="fw-bold text-success mb-1"><i class="bi bi-database-lock me-2"></i>Data Induk (Whitelist)
|
||||||
<i class="bi bi-database-lock me-2"></i>Data Induk (Whitelist)
|
|
||||||
</h4>
|
</h4>
|
||||||
<p class="text-muted mb-0">Daftar NIP/NISN yang <b>diizinkan</b> untuk mendaftar.</p>
|
<p class="text-muted mb-0">Daftar NIP/NISN/NIK yang <b>diizinkan</b> untuk mendaftar.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalMasterInduk">
|
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalMasterInduk">
|
||||||
<i class="bi bi-plus-lg me-1"></i> Tambah Data Induk
|
<i class="bi bi-plus-lg me-1"></i> Tambah Data Induk
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -86,15 +121,15 @@
|
||||||
<div class="card shadow mb-4 border-left-success">
|
<div class="card shadow mb-4 border-left-success">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover align-middle mb-0">
|
<table class="table table-hover table-bordered align-middle mb-0">
|
||||||
<thead class="table-light">
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th>No</th>
|
<th>No</th>
|
||||||
<th>NIP / NISN</th>
|
<th>NIP / NISN</th>
|
||||||
<th>Nama Pemilik</th>
|
<th>Nama Pemilik</th>
|
||||||
<th>Role</th>
|
<th class="text-center">Role</th>
|
||||||
<th class="text-center">Status Akun</th>
|
<th class="text-center">Status Akun</th>
|
||||||
<th class="text-end">Aksi</th>
|
<th class="text-center">Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
@ -103,32 +138,34 @@
|
||||||
<td>{{ $index + 1 }}</td>
|
<td>{{ $index + 1 }}</td>
|
||||||
<td class="fw-bold font-monospace">{{ $item->nomor_induk }}</td>
|
<td class="fw-bold font-monospace">{{ $item->nomor_induk }}</td>
|
||||||
<td>{{ $item->nama_pemilik }}</td>
|
<td>{{ $item->nama_pemilik }}</td>
|
||||||
<td>
|
|
||||||
<span class="badge {{ $item->role == 'guru' ? 'bg-info' : 'bg-secondary' }}">
|
|
||||||
{{ ucfirst($item->role) }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
{{-- Cek apakah user sudah daftar pakai NIP ini --}}
|
@if($item->role == 'guru')
|
||||||
@php
|
<span class="badge bg-info text-dark">Guru</span>
|
||||||
$isRegistered = \App\Models\User::where('nomor_induk', $item->nomor_induk)->exists();
|
@elseif($item->role == 'siswa')
|
||||||
@endphp
|
<span class="badge bg-primary">Siswa</span>
|
||||||
|
|
||||||
@if($isRegistered)
|
|
||||||
<span class="badge bg-success text-white">
|
|
||||||
<i class="bi bi-check-circle-fill me-1"></i>Terdaftar
|
|
||||||
</span>
|
|
||||||
@else
|
@else
|
||||||
<span class="badge bg-warning text-dark">
|
<span class="badge bg-secondary">Petugas</span>
|
||||||
<i class="bi bi-hourglass-split me-1"></i>Belum Daftar
|
|
||||||
</span>
|
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td class="text-end">
|
<td class="text-center">
|
||||||
<form action="{{ route('admin.master-induk.destroy', $item->id) }}" method="POST" onsubmit="return confirm('Hapus data ini? User dengan NIP/NISN ini tidak akan bisa daftar lagi.');">
|
@php
|
||||||
|
$isRegistered = \App\Models\User::where('nisn', $item->nomor_induk)->orWhere('nip',
|
||||||
|
$item->nomor_induk)->exists();
|
||||||
|
@endphp
|
||||||
|
@if ($isRegistered)
|
||||||
|
<span class="badge bg-success text-white"><i
|
||||||
|
class="bi bi-check-circle-fill me-1"></i>Terdaftar</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-warning text-dark"><i
|
||||||
|
class="bi bi-hourglass-split me-1"></i>Belum Daftar</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<form action="{{ route('admin.master-induk.destroy', $item->id) }}" method="POST"
|
||||||
|
class="d-inline form-delete-whitelist" data-induk="{{ $item->nomor_induk }}">
|
||||||
@csrf
|
@csrf
|
||||||
@method('DELETE')
|
@method('DELETE')
|
||||||
<button type="submit" class="btn btn-sm btn-outline-danger">
|
<button type="button" class="btn btn-sm btn-outline-danger btn-hapus-whitelist">
|
||||||
<i class="bi bi-trash"></i> Hapus
|
<i class="bi bi-trash"></i> Hapus
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -136,9 +173,8 @@
|
||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="6" class="text-center py-4 text-muted">
|
<td colspan="6" class="text-center py-4 text-muted">Belum ada data whitelist. Silakan
|
||||||
Belum ada data whitelist. Silakan tambah data.
|
tambah data.</td>
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -146,7 +182,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- MODAL TAMBAH DATA INDUK --}}
|
{{-- MODAL TAMBAH DATA INDUK --}}
|
||||||
|
|
@ -157,30 +192,31 @@
|
||||||
<h5 class="modal-title fw-bold">Tambah Whitelist (NIP/NISN)</h5>
|
<h5 class="modal-title fw-bold">Tambah Whitelist (NIP/NISN)</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
</div>
|
</div>
|
||||||
<form action="{{ route('admin.master-induk.store') }}" method="POST">
|
{{-- FORM TAMBAH WHITELIST --}}
|
||||||
|
<form action="{{ route('admin.master-induk.store') }}" method="POST" id="formWhitelist">
|
||||||
@csrf
|
@csrf
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="alert alert-info small mb-3">
|
<div class="alert alert-info small mb-3">
|
||||||
<i class="bi bi-info-circle-fill me-1"></i>
|
<i class="bi bi-info-circle-fill me-1"></i>
|
||||||
Masukkan data siswa/guru yang valid agar mereka bisa mendaftar.
|
Masukkan data siswa/guru yang valid agar mereka bisa mendaftar.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Role</label>
|
<label class="form-label">Role</label>
|
||||||
<select name="role" class="form-select" required>
|
<select name="role" class="form-select" required>
|
||||||
<option value="siswa">Siswa</option>
|
<option value="siswa">Siswa</option>
|
||||||
<option value="guru">Guru</option>
|
<option value="guru">Guru</option>
|
||||||
|
<option value="penjaga perpus">Petugas Perpustakaan</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">NIP / NISN</label>
|
<label class="form-label">NIP / NISN / NIK</label>
|
||||||
<input type="number" name="nomor_induk" class="form-control" placeholder="Contoh: 1234567890" required>
|
<input type="number" name="nomor_induk" class="form-control"
|
||||||
|
placeholder="Contoh: 1234567890" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Nama Pemilik</label>
|
<label class="form-label">Nama Pemilik</label>
|
||||||
<input type="text" name="nama_pemilik" class="form-control" placeholder="Nama Siswa/Guru..." required>
|
<input type="text" name="nama_pemilik" class="form-control" placeholder="Nama Siswa/Guru..."
|
||||||
|
required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|
@ -191,4 +227,122 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('.btn-hapus').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let form = $(this).closest('form');
|
||||||
|
let nama = form.data('nama');
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Hapus Pengguna?',
|
||||||
|
text: `Apakah Anda yakin ingin menghapus akun milik ${nama}?`,
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Ya, Hapus',
|
||||||
|
cancelButtonText: 'Batal',
|
||||||
|
confirmButtonColor: '#dc3545'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Menghapus...',
|
||||||
|
allowOutsideClick: false,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
});
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.btn-hapus-whitelist').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let form = $(this).closest('form');
|
||||||
|
let induk = form.data('induk');
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Hapus Data Induk?',
|
||||||
|
text: `Data dengan nomor ${induk} tidak akan bisa mendaftar lagi.`,
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Ya, Hapus',
|
||||||
|
cancelButtonText: 'Batal',
|
||||||
|
confirmButtonColor: '#dc3545'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Menghapus...',
|
||||||
|
allowOutsideClick: false,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
});
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#formWhitelist').on('submit', function() {
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Menyimpan...',
|
||||||
|
allowOutsideClick: false,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
@if(session('success'))
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: '{{ session("success") }}'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
|
||||||
|
// GENERATE OTP & LINK RESET
|
||||||
|
$(document).on('click', '.btn-reset-password', function() {
|
||||||
|
const nama = $(this).data('nama');
|
||||||
|
const otpCode = "678901";
|
||||||
|
const linkReset = "{{ route('reset.password-request') }}";
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Generate OTP Reset?',
|
||||||
|
html: `Anda akan membuat Token Reset Password untuk <b>${nama}</b>.`,
|
||||||
|
icon: 'question',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Ya, Generate',
|
||||||
|
cancelButtonText: 'Batal',
|
||||||
|
confirmButtonColor: '#0d6efd'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Generating...',
|
||||||
|
timer: 1000,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
}).then(() => {
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'OTP Berhasil Dibuat!',
|
||||||
|
html: `
|
||||||
|
<div class="text-start bg-light p-3 rounded border">
|
||||||
|
<p class="mb-1 small text-muted">Kode OTP:</p>
|
||||||
|
<h3 class="text-primary fw-bold letter-spacing-1 mb-3">${otpCode}</h3>
|
||||||
|
<p class="mb-1 small text-muted">Link Reset:</p>
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control form-control-sm" value="${linkReset}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 small text-muted">
|
||||||
|
Silakan salin Kode OTP & Link di atas lalu kirim ke WhatsApp user.
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
icon: 'success',
|
||||||
|
confirmButtonText: 'Selesai'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
@section('page-title', $pageTitle)
|
@section('page-title', $pageTitle)
|
||||||
<div class="d-flex align-items-center mb-4">
|
<div class="d-flex align-items-center mb-4">
|
||||||
<a href="{{ route('admin.pengguna.index') }}" class="btn btn-outline-secondary me-3">
|
<a href="{{ route('admin.pengumuman.index') }}" class="btn btn-outline-secondary me-3">
|
||||||
<i class="bi bi-arrow-left"></i>
|
<i class="bi bi-arrow-left"></i>
|
||||||
</a>
|
</a>
|
||||||
<h3 class="my-0 fw-bold">Formulir Tambah Pengumuman</h3>
|
<h3 class="my-0 fw-bold">Formulir Tambah Pengumuman</h3>
|
||||||
|
|
@ -43,4 +43,28 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</x-app-layout>
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
document.getElementById('formTambahPengumuman').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Menyimpan...',
|
||||||
|
timer: 800,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
}).then(() => {
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: 'Pengumuman baru berhasil ditambahkan.'
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "{{ route('admin.pengumuman.index') }}";
|
||||||
|
}, 1500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
</x-app-layout>
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
@section('page-title', $pageTitle)
|
@section('page-title', $pageTitle)
|
||||||
<div class="d-flex align-items-center mb-4">
|
<div class="d-flex align-items-center mb-4">
|
||||||
<a href="{{ route('admin.pengguna.index') }}" class="btn btn-outline-secondary me-3">
|
<a href="{{ route('admin.pengumuman.index') }}" class="btn btn-outline-secondary me-3">
|
||||||
<i class="bi bi-arrow-left"></i>
|
<i class="bi bi-arrow-left"></i>
|
||||||
</a>
|
</a>
|
||||||
<h3 class="my-0 fw-bold">Formulir Edit Pengumuman</h3>
|
<h3 class="my-0 fw-bold">Formulir Edit Pengumuman</h3>
|
||||||
|
|
@ -48,4 +48,29 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</x-app-layout>
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
document.getElementById('formEditPengumuman').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Menyimpan Perubahan...',
|
||||||
|
timer: 800,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
}).then(() => {
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: 'Pengumuman berhasil diperbarui.'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Redirect setelah 1.5 detik
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "{{ route('admin.pengumuman.index') }}";
|
||||||
|
}, 1500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
</x-app-layout>
|
||||||
|
|
@ -17,13 +17,13 @@
|
||||||
<th scope="col">Tipe</th>
|
<th scope="col">Tipe</th>
|
||||||
<th scope="col">Judul</th>
|
<th scope="col">Judul</th>
|
||||||
<th scope="col">Isi</th>
|
<th scope="col">Isi</th>
|
||||||
<th scope="col">Aksi</th>
|
<th scope="col" class="text-center">Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@forelse ($semuaPengumuman as $item)
|
@forelse ($semuaPengumuman as $item)
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ $loop->iteration }}</td>
|
<td class="row-number">{{ $loop->iteration }}</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge bg-{{ $item['type'] }}-subtle text-{{ $item['type'] }}-emphasis">{{ Str::title($item['type']) }}</span>
|
<span class="badge bg-{{ $item['type'] }}-subtle text-{{ $item['type'] }}-emphasis">{{ Str::title($item['type']) }}</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -36,9 +36,9 @@
|
||||||
<a href="{{ route('admin.pengumuman.edit', $item['id']) }}" class="btn btn-sm btn-outline-secondary">
|
<a href="{{ route('admin.pengumuman.edit', $item['id']) }}" class="btn btn-sm btn-outline-secondary">
|
||||||
<i class="bi bi-pencil-fill"></i>
|
<i class="bi bi-pencil-fill"></i>
|
||||||
</a>
|
</a>
|
||||||
<button class="btn btn-sm btn-outline-danger btn-delete"
|
<button class="btn btn-sm btn-outline-danger btn-delete"
|
||||||
data-id="{{ $item['id'] }}"
|
data-id="{{ $item['id'] }}"
|
||||||
data-title="{{ $item['title'] }}">
|
data-title="{{ $item['title'] }}">
|
||||||
<i class="bi bi-trash3-fill"></i>
|
<i class="bi bi-trash3-fill"></i>
|
||||||
</button>
|
</button>
|
||||||
<form id="delete-form-{{ $item['id'] }}" action="{{ route('admin.pengumuman.destroy', $item['id']) }}" method="POST" style="display: none;">
|
<form id="delete-form-{{ $item['id'] }}" action="{{ route('admin.pengumuman.destroy', $item['id']) }}" method="POST" style="display: none;">
|
||||||
|
|
@ -49,9 +49,9 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr class="empty-row">
|
||||||
<td colspan="5" class="text-center py-4">
|
<td colspan="5" class="text-center py-4">
|
||||||
<p class="text-muted">Belum ada pengumuman yang dibuat.</p>
|
<p class="text-muted mb-0">Belum ada pengumuman yang dibuat.</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
$(document).on('click', '.btn-delete', function() {
|
$(document).on('click', '.btn-delete', function() {
|
||||||
const id = $(this).data('id');
|
const id = $(this).data('id');
|
||||||
const title = $(this).data('title');
|
const title = $(this).data('title');
|
||||||
|
|
||||||
modernSwal.fire({
|
modernSwal.fire({
|
||||||
title: 'Hapus Pengumuman?',
|
title: 'Hapus Pengumuman?',
|
||||||
text: `Apakah Anda yakin ingin menghapus pengumuman "${title}"?`,
|
text: `Apakah Anda yakin ingin menghapus pengumuman "${title}"?`,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
@section('page-title', $pageTitle)
|
@section('page-title', $pageTitle)
|
||||||
<div class="d-flex align-items-center mb-4">
|
<div class="d-flex align-items-center mb-4">
|
||||||
<a href="{{ route('admin.pengguna.index') }}" class="btn btn-outline-secondary me-3">
|
<a href="{{ route('admin.rekomendasi.index') }}" class="btn btn-outline-secondary me-3">
|
||||||
<i class="bi bi-arrow-left"></i>
|
<i class="bi bi-arrow-left"></i>
|
||||||
</a>
|
</a>
|
||||||
<h3 class="my-0 fw-bold">Formulir Tambah Rekomendasi</h3>
|
<h3 class="my-0 fw-bold">Formulir Tambah Rekomendasi</h3>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
@section('page-title', $pageTitle)
|
@section('page-title', $pageTitle)
|
||||||
<div class="d-flex align-items-center mb-4">
|
<div class="d-flex align-items-center mb-4">
|
||||||
<a href="{{ route('admin.pengguna.index') }}" class="btn btn-outline-secondary me-3">
|
<a href="{{ route('admin.rekomendasi.index') }}" class="btn btn-outline-secondary me-3">
|
||||||
<i class="bi bi-arrow-left"></i>
|
<i class="bi bi-arrow-left"></i>
|
||||||
</a>
|
</a>
|
||||||
<h3 class="my-0 fw-bold">Formulir Edit Rekomendasi</h3>
|
<h3 class="my-0 fw-bold">Formulir Edit Rekomendasi</h3>
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,22 @@
|
||||||
<div class="card shadow-sm border-0">
|
<div class="card shadow-sm border-0">
|
||||||
<div class="card-header bg-white d-flex justify-content-between align-items-center">
|
<div class="card-header bg-white d-flex justify-content-between align-items-center">
|
||||||
<h5 class="my-0 fw-bold">Kelola Rekomendasi Pembelajaran</h5>
|
<h5 class="my-0 fw-bold">Kelola Rekomendasi Pembelajaran</h5>
|
||||||
<a href="{{ route('admin.rekomendasi.create') }}" class="btn btn-primary"><i class="bi bi-plus-circle-fill me-2"></i>Buat Rekomendasi</a>
|
<a href="{{ route('admin.rekomendasi.create') }}" class="btn btn-primary">
|
||||||
|
<i class="bi bi-plus-circle-fill me-2"></i>Buat Rekomendasi
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover align-middle">
|
<table class="table table-hover align-middle">
|
||||||
<thead><tr><th>No</th><th>Thumbnail</th><th>Judul</th><th>Kategori</th><th>Aksi</th></tr></thead>
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>No</th>
|
||||||
|
<th>Thumbnail</th>
|
||||||
|
<th>Judul</th>
|
||||||
|
<th>Kategori</th>
|
||||||
|
<th class="text-center">Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach($semuaRekomendasi as $item)
|
@foreach($semuaRekomendasi as $item)
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -21,9 +31,9 @@
|
||||||
<a href="{{ route('admin.rekomendasi.edit', $item['id']) }}" class="btn btn-sm btn-outline-secondary">
|
<a href="{{ route('admin.rekomendasi.edit', $item['id']) }}" class="btn btn-sm btn-outline-secondary">
|
||||||
<i class="bi bi-pencil-fill"></i>
|
<i class="bi bi-pencil-fill"></i>
|
||||||
</a>
|
</a>
|
||||||
<button class="btn btn-sm btn-outline-danger btn-delete"
|
<button class="btn btn-sm btn-outline-danger btn-delete"
|
||||||
data-id="{{ $item['id'] }}"
|
data-id="{{ $item['id'] }}"
|
||||||
data-title="{{ $item['judul'] }}">
|
data-title="{{ $item['judul'] }}">
|
||||||
<i class="bi bi-trash3-fill"></i>
|
<i class="bi bi-trash3-fill"></i>
|
||||||
</button>
|
</button>
|
||||||
<form id="delete-form-{{ $item['id'] }}" action="{{ route('admin.rekomendasi.destroy', $item['id']) }}" method="POST" style="display: none;">
|
<form id="delete-form-{{ $item['id'] }}" action="{{ route('admin.rekomendasi.destroy', $item['id']) }}" method="POST" style="display: none;">
|
||||||
|
|
@ -45,7 +55,7 @@
|
||||||
$(document).on('click', '.btn-delete', function() {
|
$(document).on('click', '.btn-delete', function() {
|
||||||
const id = $(this).data('id');
|
const id = $(this).data('id');
|
||||||
const title = $(this).data('title');
|
const title = $(this).data('title');
|
||||||
|
|
||||||
modernSwal.fire({
|
modernSwal.fire({
|
||||||
title: 'Hapus Rekomendasi?',
|
title: 'Hapus Rekomendasi?',
|
||||||
text: `Apakah Anda yakin ingin menghapus rekomendasi "${title}"?`,
|
text: `Apakah Anda yakin ingin menghapus rekomendasi "${title}"?`,
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,15 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="nip" class="form-label">Nomor Induk Pegawai (NIP)</label>
|
<label for="nip" class="form-label">NIP/NIK</label>
|
||||||
<input id="nip" class="form-control" type="text" name="nip" required autofocus />
|
<input id="nip" class="form-control" type="text" placeholder="Masukan NIP/NIK" name="nip" required autofocus />
|
||||||
<x-input-error :messages="$errors->get('nip')" class="mt-2" />
|
<x-input-error :messages="$errors->get('nip')" class="mt-2" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="password" class="form-label">Kata Sandi</label>
|
<label for="password" class="form-label">Kata Sandi</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="password" class="form-control" type="password" name="password" required />
|
<input id="password" class="form-control" placeholder="Masukan kata sandi" type="password" name="password" required />
|
||||||
<button class="btn btn-outline-secondary" type="button" id="togglePassword">
|
<button class="btn btn-outline-secondary" type="button" id="togglePassword">
|
||||||
<i class="bi bi-eye-slash-fill"></i>
|
<i class="bi bi-eye-slash-fill"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-grid mt-4">
|
<div class="d-grid mt-4">
|
||||||
<button type="submit" class="btn btn-primary btn-lg">Masuk</button>
|
<button type="submit" class="btn btn-primary py-2 fw-medium shadow-sm">Masuk</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="mt-4 text-center text-muted small">
|
<p class="mt-4 text-center text-muted small">
|
||||||
Kembali ke <a href="/" class="fw-semibold text-decoration-none">halaman utama</a>.
|
Kembali ke <a href="/" class="fw-semibold text-decoration-none">halaman utama</a>.
|
||||||
|
|
|
||||||
|
|
@ -1,69 +1,107 @@
|
||||||
<x-guest-layout>
|
<x-guest-layout>
|
||||||
@if ($errors->has('forbidden'))
|
@if ($errors->has('forbidden'))
|
||||||
<div class="alert alert-danger d-flex align-items-center mb-4" role="alert">
|
<div class="alert alert-danger d-flex align-items-center mb-4" role="alert">
|
||||||
<i class="bi bi-exclamation-triangle-fill me-2 fs-5"></i>
|
<i class="bi bi-exclamation-triangle-fill me-2 fs-5"></i>
|
||||||
<div class="fw-bold">{{ $errors->first('forbidden') }}</div>
|
<div class="fw-bold">{{ $errors->first('forbidden') }}</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<form method="POST" action="{{ route('login') }}">
|
<form method="POST" action="{{ route('login') }}">
|
||||||
@csrf
|
@csrf
|
||||||
<input type="hidden" name="role" value="{{ $role }}">
|
<input type="hidden" name="role" value="{{ $role }}">
|
||||||
|
|
||||||
|
{{-- HEADER LOGIN --}}
|
||||||
<div class="text-center mb-4">
|
<div class="text-center mb-4">
|
||||||
{{-- Judul dinamis --}}
|
<div class="bg-primary bg-opacity-10 text-primary rounded-circle d-inline-flex align-items-center justify-content-center mb-3"
|
||||||
<h3 class="fw-bold text-primary">Login {{ Str::title($role) }}</h3>
|
style="width: 70px; height: 70px;">
|
||||||
<p class="text-muted">
|
<i class="bi bi-shield-lock-fill fs-1"></i>
|
||||||
|
</div>
|
||||||
|
<h3 class="fw-bold text-dark">Login {{ Str::title($role) }}</h3>
|
||||||
|
<p class="text-muted small">
|
||||||
@if ($role == 'siswa')
|
@if ($role == 'siswa')
|
||||||
Masukan NISN dan kata sandi Anda.
|
Silakan masukkan <b>NISN</b> dan kata sandi.
|
||||||
@else
|
@else
|
||||||
Masukan NIP dan kata sandi Anda.
|
Silakan masukkan <b>NIP/NIK</b> dan kata sandi.
|
||||||
@endif
|
@endif
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Form dinamis --}}
|
{{-- INPUT USERNAME (NISN/NIP) --}}
|
||||||
@if ($role == 'siswa')
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="nisn" class="form-label">Nomor Induk Siswa Nasional (NISN)</label>
|
|
||||||
<input id="nisn" class="form-control" type="text" name="nisn" required autofocus />
|
|
||||||
<x-input-error :messages="$errors->get('nisn')" class="mt-2" />
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="nip" class="form-label">Nomor Induk Pegawai (NIP)</label>
|
|
||||||
<input id="nip" class="form-control" type="text" name="nip" required autofocus />
|
|
||||||
<x-input-error :messages="$errors->get('nip')" class="mt-2" />
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="password" class="form-label">Kata Sandi</label>
|
<label for="{{ $role == 'siswa' ? 'nisn' : 'nip' }}" class="form-label fw-semibold small">
|
||||||
|
{{ $role == 'siswa' ? 'Nomor Induk Siswa Nasional (NISN)' : 'NIP/NIK' }}
|
||||||
|
</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="password" class="form-control" type="password" name="password" required />
|
@if ($role == 'siswa')
|
||||||
<button class="btn btn-outline-secondary" type="button" id="togglePassword">
|
<input id="nisn" class="form-control" type="text" name="nisn" placeholder="Masukan NISN" required autofocus />
|
||||||
|
@else
|
||||||
|
<input id="nip" class="form-control" type="text" name="nip" placeholder="Masukan NIP/NIK" required autofocus />
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
{{-- Error Message --}}
|
||||||
|
@if ($role == 'siswa')
|
||||||
|
<x-input-error :messages="$errors->get('nisn')" class="mt-1 small text-danger" />
|
||||||
|
@else
|
||||||
|
<x-input-error :messages="$errors->get('nip')" class="mt-1 small text-danger" />
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- INPUT PASSWORD --}}
|
||||||
|
<div class="mb-4">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<label for="password" class="form-label fw-semibold small">Kata Sandi</label>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<input id="password" class="form-control border-end-0" type="password"
|
||||||
|
name="password" placeholder="Masukan kata sandi" required />
|
||||||
|
<button class="btn btn-light border border-start-0 text-muted" type="button" id="togglePassword">
|
||||||
<i class="bi bi-eye-slash-fill"></i>
|
<i class="bi bi-eye-slash-fill"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<x-input-error :messages="$errors->get('password')" class="mt-1 small text-danger" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-grid mt-4">
|
{{-- TOMBOL LOGIN --}}
|
||||||
<button type="submit" class="btn btn-primary">Masuk</button>
|
<div class="d-grid mb-4">
|
||||||
|
<button type="submit" class="btn btn-primary py-2 fw-medium shadow-sm">
|
||||||
|
Masuk
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- BANTUAN / LUPA PASSWORD --}}
|
||||||
|
<div class="bg-light p-3 rounded-3 text-center border border-dashed">
|
||||||
|
<p class="text-muted small mb-1">Mengalami kendala login?</p>
|
||||||
|
<a href="https://wa.me/6281234567890?text=Halo%20Admin,%20saya%20lupa%20kata%20sandi%20akun%20saya."
|
||||||
|
target="_blank" class="text-decoration-none fw-bold text-success d-inline-flex align-items-center">
|
||||||
|
<i class="bi bi-whatsapp me-1"></i> Hubungi Petugas via WA
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Link href untuk ke Register --}}
|
|
||||||
<p class="mt-4 text-center text-muted small">
|
<p class="mt-4 text-center text-muted small">
|
||||||
@if ($role == 'siswa')
|
|
||||||
Belum punya akun?
|
|
||||||
<a href="{{ route('register', ['role' => 'siswa']) }}" class="fw-semibold text-decoration-none">Daftar sebagai Siswa</a>
|
|
||||||
@else
|
|
||||||
Belum punya akun?
|
|
||||||
<a href="{{ route('register', ['role' => 'guru']) }}" class="fw-semibold text-decoration-none">Daftar sebagai Guru</a>
|
|
||||||
@endif
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p class="mt-3 text-center text-muted small">
|
|
||||||
Kembali ke <a href="/" class="fw-semibold text-decoration-none">halaman utama</a>.
|
Kembali ke <a href="/" class="fw-semibold text-decoration-none">halaman utama</a>.
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const togglePassword = document.querySelector('#togglePassword');
|
||||||
|
const password = document.querySelector('#password');
|
||||||
|
const icon = togglePassword.querySelector('i');
|
||||||
|
|
||||||
|
if (togglePassword && password) {
|
||||||
|
togglePassword.addEventListener('click', function(e) {
|
||||||
|
const type = password.getAttribute('type') === 'password' ? 'text' : 'password';
|
||||||
|
password.setAttribute('type', type);
|
||||||
|
|
||||||
|
if (type === 'password') {
|
||||||
|
icon.classList.remove('bi-eye-fill');
|
||||||
|
icon.classList.add('bi-eye-slash-fill');
|
||||||
|
} else {
|
||||||
|
icon.classList.remove('bi-eye-slash-fill');
|
||||||
|
icon.classList.add('bi-eye-fill');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</x-guest-layout>
|
</x-guest-layout>
|
||||||
|
|
@ -1,69 +1,87 @@
|
||||||
<x-guest-layout>
|
<x-guest-layout>
|
||||||
|
<div class="mb-4 text-center">
|
||||||
|
<h4 class="fw-bold text-primary">Daftar Akun {{ ucfirst($role) }}</h4>
|
||||||
|
<p class="text-muted small">
|
||||||
|
Silakan isi data diri lengkap untuk mendaftar.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form method="POST" action="{{ route('register') }}">
|
<form method="POST" action="{{ route('register') }}">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
{{-- Input tersembunyi untuk mengirimkan peran (role) ke backend --}}
|
|
||||||
<input type="hidden" name="role" value="{{ $role }}">
|
<input type="hidden" name="role" value="{{ $role }}">
|
||||||
|
|
||||||
<div class="text-center mb-4">
|
|
||||||
{{-- Judul dinamis --}}
|
|
||||||
<h3 class="fw-bold text-primary">Buat Akun {{ Str::title($role) }}</h3>
|
|
||||||
<p class="text-muted">Daftarkan diri Anda untuk mulai menjelajahi koleksi kami.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Form Nama Lengkap (Umum) --}}
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="name" class="form-label">Nama Lengkap</label>
|
<label class="form-label">Nama Lengkap</label>
|
||||||
<input id="name" class="form-control bg-body-tertiary @error('name') is-invalid @enderror" type="text" name="name" value="{{ old('name') }}" required autofocus autocomplete="name" />
|
<input type="text" name="name" class="form-control @error('name') is-invalid @enderror"
|
||||||
|
value="{{ old('name') }}" required autofocus placeholder="Nama sesuai absen">
|
||||||
@error('name')
|
@error('name')
|
||||||
<div class="invalid-feedback fw-semibold">
|
<div class="invalid-feedback fw-semibold">
|
||||||
<i class="bi bi-exclamation-circle-fill me-1"></i>
|
<i class="bi bi-exclamation-circle-fill me-1"></i>
|
||||||
{{ $message }}
|
{{ $message }}
|
||||||
</div>
|
</div>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Form dinamis (NISN untuk Siswa, NIP untuk Guru) --}}
|
<div class="mb-3">
|
||||||
@if ($role == 'siswa')
|
<label class="form-label">
|
||||||
<div class="mb-3">
|
@if ($role == 'siswa')
|
||||||
<label for="nisn" class="form-label">Nomor Induk Siswa Nasional (NISN)</label>
|
NISN (Nomor Induk Siswa)
|
||||||
<input id="nisn" class="form-control bg-body-tertiary @error('nisn') is-invalid @enderror" type="text" name="nisn" value="{{ old('nisn') }}" required autocomplete="username" />
|
@else
|
||||||
@error('nisn')
|
NIP / NIK Sekolah
|
||||||
<div class="invalid-feedback fw-semibold">
|
@endif
|
||||||
<i class="bi bi-exclamation-circle-fill me-1"></i>
|
</label>
|
||||||
{{ $message }}
|
|
||||||
</div>
|
<input type="number" name="{{ $role == 'siswa' ? 'nisn' : 'nip' }}"
|
||||||
@enderror
|
class="form-control @error($role == 'siswa' ? 'nisn' : 'nip') is-invalid @enderror"
|
||||||
</div>
|
value="{{ old($role == 'siswa' ? 'nisn' : 'nip') }}" required placeholder="Cth: 1234567890">
|
||||||
@else
|
|
||||||
<div class="mb-3">
|
@error($role == 'siswa' ? 'nisn' : 'nip')
|
||||||
<label for="nip" class="form-label">Nomor Induk Pegawai (NIP)</label>
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
<input id="nip" class="form-control bg-body-tertiary @error('nip') is-invalid @enderror" type="text" name="nip" value="{{ old('nip') }}" required autocomplete="username" />
|
@enderror
|
||||||
@error('nip')
|
</div>
|
||||||
<div class="invalid-feedback fw-semibold">
|
|
||||||
<i class="bi bi-exclamation-circle-fill me-1"></i>
|
<div class="mb-3">
|
||||||
{{ $message }}
|
<label class="form-label">Email Aktif</label>
|
||||||
</div>
|
<input type="email" name="email" class="form-control @error('email') is-invalid @enderror"
|
||||||
@enderror
|
value="{{ old('email') }}" required placeholder="contoh@gmail.com">
|
||||||
</div>
|
|
||||||
@endif
|
<div class="form-text text-muted small">
|
||||||
|
<i class="bi bi-bell me-1"></i>
|
||||||
|
Notifikasi denda & peminjaman akan dikirim ke email ini.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@error('email')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- Form Password (Umum) --}}
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="password" class="form-label">Password</label>
|
<label for="password" class="form-label">Password</label>
|
||||||
<input id="password" class="form-control bg-body-tertiary @error('password') is-invalid @enderror" type="password" name="password" required autocomplete="new-password" />
|
<div class="input-group">
|
||||||
|
<input id="password" class="form-control bg-body-tertiary @error('password') is-invalid @enderror"
|
||||||
|
type="password" name="password" required autocomplete="new-password" />
|
||||||
|
<button class="btn btn-outline-secondary" type="button" id="togglePassword">
|
||||||
|
<i class="bi bi-eye-slash-fill"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
@error('password')
|
@error('password')
|
||||||
<div class="invalid-feedback fw-semibold">
|
<div class="invalid-feedback fw-semibold">
|
||||||
<i class="bi bi-exclamation-circle-fill me-1"></i>
|
<i class="bi bi-exclamation-circle-fill me-1"></i>
|
||||||
{{ $message }}
|
{{ $message }}
|
||||||
</div>
|
</div>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Form Konfirmasi Password (Umum) --}}
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="password_confirmation" class="form-label">Konfirmasi Password</label>
|
<label for="password_confirmation" class="form-label">Konfirmasi Password</label>
|
||||||
<input id="password_confirmation" class="form-control bg-body-tertiary" type="password" name="password_confirmation" required autocomplete="new-password" />
|
<div class="input-group">
|
||||||
|
<input id="password_confirmation" class="form-control bg-body-tertiary" type="password"
|
||||||
|
name="password_confirmation" required autocomplete="new-password" />
|
||||||
|
<button class="btn btn-outline-secondary" type="button" id="togglePassword">
|
||||||
|
<i class="bi bi-eye-slash-fill"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-grid mt-4">
|
<div class="d-grid mt-4">
|
||||||
|
|
@ -75,7 +93,8 @@
|
||||||
{{-- Link Login dinamis --}}
|
{{-- Link Login dinamis --}}
|
||||||
<p class="mt-4 text-center text-muted small">
|
<p class="mt-4 text-center text-muted small">
|
||||||
Sudah punya akun?
|
Sudah punya akun?
|
||||||
<a href="{{ route('login', ['role' => $role]) }}" class="fw-semibold text-decoration-none">Masuk di sini</a>
|
<a href="{{ route('login', ['role' => $role]) }}" class="fw-semibold text-decoration-none">Masuk di
|
||||||
|
sini</a>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</x-guest-layout>
|
</x-guest-layout>
|
||||||
|
|
@ -1,11 +1,6 @@
|
||||||
@section('page-title', 'Beranda')
|
@section('page-title', 'Beranda')
|
||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
|
|
||||||
{{-- <button type="button" class="btn btn-sm btn-primary end-0">
|
|
||||||
<i class="bi bi-plus-circle me-1"></i>
|
|
||||||
Pinjam Buku Baru
|
|
||||||
</button> --}}
|
|
||||||
|
|
||||||
{{-- CEK STATUS BANNED --}}
|
{{-- CEK STATUS BANNED --}}
|
||||||
@if (Auth::user()->is_banned)
|
@if (Auth::user()->is_banned)
|
||||||
<div class="alert alert-danger border-0 shadow-sm d-flex align-items-center mb-4" role="alert">
|
<div class="alert alert-danger border-0 shadow-sm d-flex align-items-center mb-4" role="alert">
|
||||||
|
|
@ -28,6 +23,7 @@
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
{{-- HERO SECTION --}}
|
||||||
<div class="card border-0 shadow-sm rounded-4 my-4 p-4 position-relative" style="background-color: #CEDEFF;">
|
<div class="card border-0 shadow-sm rounded-4 my-4 p-4 position-relative" style="background-color: #CEDEFF;">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-md-8 p-4 p-md-5" style="z-index: 2;">
|
<div class="col-12 col-md-8 p-4 p-md-5" style="z-index: 2;">
|
||||||
|
|
@ -38,7 +34,7 @@
|
||||||
|
|
||||||
<div class="position-absolute d-none d-md-block"
|
<div class="position-absolute d-none d-md-block"
|
||||||
style="top: -35px; right: 40px; width: 30%; max-width: 300px; z-index: 1;">
|
style="top: -35px; right: 40px; width: 30%; max-width: 300px; z-index: 1;">
|
||||||
<img src="{{ asset('images/assets/vector-dashboard.svg') }}" alt="Ilustrasi Dashboard" class="img-fluid">
|
<img src="{{ asset('images/assets/vector-dashboard.svg') }}" alt="Ilustrasi Beranda" class="img-fluid">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -214,11 +210,17 @@ class="badge bg-{{ $item['type'] }}-soft text-{{ $item['type'] }} rounded-pill p
|
||||||
@forelse($bukuPinjamOffline as $buku)
|
@forelse($bukuPinjamOffline as $buku)
|
||||||
<div class="col-xl-4 col-md-6" x-show="expanded || {{ $loop->index }} < 3" x-transition>
|
<div class="col-xl-4 col-md-6" x-show="expanded || {{ $loop->index }} < 3" x-transition>
|
||||||
<x-book-card :buku="$buku">
|
<x-book-card :buku="$buku">
|
||||||
<div
|
@if($buku['sisa_hari'] < 0)
|
||||||
class="d-flex align-items-center text-danger bg-white bg-opacity-75 rounded-2 px-2 py-1">
|
<div class="d-flex align-items-center text-danger bg-danger-subtle rounded-2 px-2 py-1">
|
||||||
<i class="bi bi-clock-fill me-2 shadow-md"></i>
|
<i class="bi bi-exclamation-circle-fill me-2 shadow-md"></i>
|
||||||
<span class="fw-bold small">Sisa: {{ $buku['sisa_hari'] }} hari</span>
|
<span class="fw-bold small">Terlambat: {{ abs($buku['sisa_hari']) }} hari</span>
|
||||||
</div>
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="d-flex align-items-center text-primary bg-primary-subtle rounded-2 px-2 py-1">
|
||||||
|
<i class="bi bi-clock-fill me-2 shadow-md"></i>
|
||||||
|
<span class="fw-bold small">Sisa: {{ $buku['sisa_hari'] }} hari</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
</x-book-card>
|
</x-book-card>
|
||||||
</div>
|
</div>
|
||||||
@empty
|
@empty
|
||||||
|
|
@ -312,7 +314,6 @@ class="d-flex gap-3 text-decoration-none text-dark mb-3">
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<!-- Modals untuk Pengumuman-->
|
|
||||||
<div class="modal fade" id="pengumumanModal" tabindex="-1" aria-labelledby="pengumumanModalLabel"
|
<div class="modal fade" id="pengumumanModal" tabindex="-1" aria-labelledby="pengumumanModalLabel"
|
||||||
aria-hidden="true">
|
aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-scrollable modal-lg">
|
<div class="modal-dialog modal-dialog-scrollable modal-lg">
|
||||||
|
|
@ -345,7 +346,6 @@ class="d-flex gap-3 text-decoration-none text-dark mb-3">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Modals untuk Pemberitahuan-->
|
|
||||||
<div class="modal fade" id="pemberitahuanModal" tabindex="-1" aria-labelledby="pemberitahuanModalLabel"
|
<div class="modal fade" id="pemberitahuanModal" tabindex="-1" aria-labelledby="pemberitahuanModalLabel"
|
||||||
aria-hidden="true">
|
aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-scrollable modal-lg">
|
<div class="modal-dialog modal-dialog-scrollable modal-lg">
|
||||||
|
|
@ -386,7 +386,6 @@ class="badge bg-{{ $item['type'] }}-soft text-{{ $item['type'] }} rounded-pill p
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Modals untuk Rekomendasi Pembelajaran-->
|
|
||||||
<div class="modal fade" id="rekomendasiModal" tabindex="-1" aria-labelledby="rekomendasiModalLabel"
|
<div class="modal fade" id="rekomendasiModal" tabindex="-1" aria-labelledby="rekomendasiModalLabel"
|
||||||
aria-hidden="true">
|
aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-scrollable modal-lg">
|
<div class="modal-dialog modal-dialog-scrollable modal-lg">
|
||||||
|
|
@ -429,4 +428,4 @@ class="badge fw-normal text-primary border me-1">{{ $item['kategori'] }}</span>
|
||||||
</script>
|
</script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
<script src="{{ asset('js/dashboard-charts.js') }}"></script>
|
<script src="{{ asset('js/dashboard-charts.js') }}"></script>
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
@ -63,7 +63,6 @@
|
||||||
const password = document.querySelector('#password');
|
const password = document.querySelector('#password');
|
||||||
|
|
||||||
if (togglePassword && password) {
|
if (togglePassword && password) {
|
||||||
// Tambahkan ikon awal jika belum ada
|
|
||||||
const initialIcon = togglePassword.querySelector('i');
|
const initialIcon = togglePassword.querySelector('i');
|
||||||
if (!initialIcon.classList.contains('bi-eye-fill') && !initialIcon.classList.contains('bi-eye-slash-fill')) {
|
if (!initialIcon.classList.contains('bi-eye-fill') && !initialIcon.classList.contains('bi-eye-slash-fill')) {
|
||||||
initialIcon.classList.add('bi-eye-slash-fill');
|
initialIcon.classList.add('bi-eye-slash-fill');
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,13 @@ class="notification-item my-1 rounded-pill dropdown-item @if (!$item['read']) un
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item" href="{{ route('profile.index') }}">
|
<a class="dropdown-item" href="{{ route('profile.index') }}">
|
||||||
<i class="bi bi-person-circle"></i>
|
<i class="bi bi-person-circle"></i>
|
||||||
<span>{{ __('Profile') }}</span>
|
<span>{{ __('Profil') }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item" href="{{ route('profile.edit') }}">
|
||||||
|
<i class="bi bi-gear"></i>
|
||||||
|
<span>{{ __('Pengaturan') }}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
|
||||||
|
|
@ -13,33 +13,71 @@
|
||||||
|
|
||||||
<h1 class="h2 fw-semibold mb-5 text-center">Form Peminjaman Offline</h1>
|
<h1 class="h2 fw-semibold mb-5 text-center">Form Peminjaman Offline</h1>
|
||||||
|
|
||||||
{{-- Informasi Peminjam --}}
|
<div class="card border-0 shadow-sm mb-4">
|
||||||
<div class="mb-5">
|
<div class="card-body p-4">
|
||||||
<div class="card border-0 shadow-sm">
|
{{-- Header Section: Judul & Tombol Edit --}}
|
||||||
<div class="card-header bg-white py-3 d-flex justify-content-between align-items-center">
|
<div class="d-flex justify-content-between align-items-center mb-4 border-bottom pb-3">
|
||||||
<h5 class="fw-bold m-0">Informasi Peminjam</h5>
|
<h5 class="fw-bold text-primary m-0">
|
||||||
<a href="{{ route('profile.edit') }}" class="btn btn-sm btn-outline-secondary ">Edit
|
<i class="bi bi-person-lines-fill me-2"></i>Informasi Peminjam
|
||||||
Profil</a>
|
</h5>
|
||||||
|
<a href="{{ route('profile.edit') }}" class="btn btn-sm btn-primary rounded-pill px-3">
|
||||||
|
<i class="bi bi-pencil-square me-2"></i>Edit Profil
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-4">
|
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-6">
|
{{-- Nama Lengkap (Semua Role) --}}
|
||||||
<label class="form-label text-muted small">Nama Lengkap</label>
|
<div class="col-md-6">
|
||||||
<p class="fw-semibold">{{ $user['nama_lengkap'] }}</p>
|
<label class="form-label text-muted small text-uppercase fw-bold">Nama
|
||||||
</div>
|
Lengkap</label>
|
||||||
<div class="col-md-6">
|
<p class="fw-semibold text-dark fs-5">{{ $user->nama_lengkap ?? $user->name }}</p>
|
||||||
<label class="form-label text-muted small">Nomor Handphone</label>
|
|
||||||
<p class="fw-semibold">{{ $user->phone ?? 'N/A' }}</p>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label text-muted small">Kelas</label>
|
|
||||||
<p class="fw-semibold">{{ $user['kelas'] }}</p>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label text-muted small">Golongan</label>
|
|
||||||
<p class="fw-semibold">{{ $user['golongan'] }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- KONDISI UNTUK GURU / PETUGAS --}}
|
||||||
|
@if(in_array($user->role, ['guru', 'penjaga perpus']))
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label text-muted small text-uppercase fw-bold">NIP / NIK</label>
|
||||||
|
<p class="fw-semibold text-dark">{{ $user->nip ?? '-' }}</p>
|
||||||
|
</div>
|
||||||
|
{{-- KONDISI UNTUK SISWA --}}
|
||||||
|
@else
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label text-muted small text-uppercase fw-bold">NISN</label>
|
||||||
|
<p class="fw-semibold text-dark">{{ $user->nisn ?? '-' }}</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- Email (Semua Role) --}}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label text-muted small text-uppercase fw-bold">Email</label>
|
||||||
|
<p class="fw-semibold text-dark">{{ $user->email }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Nomor HP (Semua Role) --}}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label text-muted small text-uppercase fw-bold">Nomor Handphone
|
||||||
|
(WA)</label>
|
||||||
|
<p class="fw-semibold text-dark">
|
||||||
|
@if($user->no_hp)
|
||||||
|
<span>{{ $user->no_hp
|
||||||
|
}}</span>
|
||||||
|
@else
|
||||||
|
<span class="text-muted fst-italic">- Belum diatur -</span>
|
||||||
|
@endif
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Info Tambahan Khusus Siswa --}}
|
||||||
|
@if($user->role == 'siswa')
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label text-muted small text-uppercase fw-bold">Kelas</label>
|
||||||
|
<p class="fw-semibold text-dark">{{ $user->kelas ?? '-' }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label text-muted small text-uppercase fw-bold">Golongan</label>
|
||||||
|
<p class="fw-semibold text-dark">{{ $user->golongan ?? '-' }}</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -54,7 +92,7 @@
|
||||||
<div class="mb-5">
|
<div class="mb-5">
|
||||||
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-3">
|
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-3">
|
||||||
<h5 class="fw-bold m-0">Buku yang Dipinjam</h5>
|
<h5 class="fw-bold m-0">Buku yang Dipinjam</h5>
|
||||||
<button type="button" class="btn btn-sm btn-primary " data-bs-toggle="modal"
|
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal"
|
||||||
data-bs-target="#pilihBukuModal" id="btnTambahBuku">
|
data-bs-target="#pilihBukuModal" id="btnTambahBuku">
|
||||||
<i class="bi bi-plus-circle me-1"></i>Tambah Buku
|
<i class="bi bi-plus-circle me-1"></i>Tambah Buku
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -158,56 +196,55 @@ class="rounded me-3 form-book-cover">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Daftar Buku -->
|
|
||||||
<div id="daftarBukuModal" class="row g-3">
|
<div id="daftarBukuModal" class="row g-3">
|
||||||
@foreach ($semuaBuku as $bukuItem)
|
@foreach ($semuaBuku as $bukuItem)
|
||||||
@if ($bukuItem['status'] == 'Tersedia' || $bukuItem['id'] == $buku['id'])
|
@if ($bukuItem['status'] == 'Tersedia' || $bukuItem['id'] == $buku['id'])
|
||||||
<div class="col-12 book-option" data-book-id="{{ $bukuItem['id'] }}"
|
<div class="col-12 book-option" data-book-id="{{ $bukuItem['id'] }}"
|
||||||
data-book-title="{{ strtolower($bukuItem['judul']) }}"
|
data-book-title="{{ strtolower($bukuItem['judul']) }}"
|
||||||
data-book-author="{{ strtolower($bukuItem['penulis']) }}">
|
data-book-author="{{ strtolower($bukuItem['penulis']) }}">
|
||||||
|
|
||||||
<div class="card book-card h-100 border-0 shadow-sm hover-shadow transition"
|
<div class="card book-card h-100 border-0 shadow-sm hover-shadow transition"
|
||||||
onclick="toggleBookSelection({{ $bukuItem['id'] }})">
|
onclick="toggleBookSelection({{ $bukuItem['id'] }})">
|
||||||
|
|
||||||
<div class="card-body p-3">
|
<div class="card-body p-3">
|
||||||
<div class="d-flex align-items-start">
|
<div class="d-flex align-items-start">
|
||||||
|
|
||||||
<img src="{{ asset($bukuItem['cover']) }}" alt="Cover"
|
<img src="{{ asset($bukuItem['cover']) }}" alt="Cover"
|
||||||
class="rounded me-3 form-book-cover"
|
class="rounded me-3 form-book-cover"
|
||||||
style="width: 60px; height: 80px; object-fit: cover;">
|
style="width: 60px; height: 80px; object-fit: cover;">
|
||||||
|
|
||||||
<!-- Detail Buku -->
|
<div class="flex-grow-1">
|
||||||
<div class="flex-grow-1">
|
<h6 class="fw-bold mb-1">{{ $bukuItem['judul'] }}</h6>
|
||||||
<h6 class="fw-bold mb-1">{{ $bukuItem['judul'] }}</h6>
|
<p class="text-muted small mb-1">{{ $bukuItem['penulis'] }}</p>
|
||||||
<p class="text-muted small mb-1">{{ $bukuItem['penulis'] }}</p>
|
<div class="d-flex align-items-center flex-wrap gap-2">
|
||||||
<div class="d-flex align-items-center flex-wrap gap-2">
|
<span class="badge bg-info">{{ $bukuItem['kategori'] }}</span>
|
||||||
<span class="badge bg-info">{{ $bukuItem['kategori'] }}</span>
|
<span class="badge bg-success"><i
|
||||||
<span class="badge bg-success"><i
|
class="bi bi-check-circle me-1"></i>Tersedia</span>
|
||||||
class="bi bi-check-circle me-1"></i>Tersedia</span>
|
@if ($bukuItem['id'] == $buku['id'])
|
||||||
@if ($bukuItem['id'] == $buku['id'])
|
<span class="badge bg-primary"><i class="bi bi-star-fill me-1"></i>Buku
|
||||||
<span class="badge bg-primary"><i
|
Utama</span>
|
||||||
class="bi bi-star-fill me-1"></i>Buku Utama</span>
|
@endif
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-check ms-2">
|
|
||||||
<input class="form-check-input book-checkbox" type="checkbox"
|
|
||||||
value="{{ $bukuItem['id'] }}" id="book{{ $bukuItem['id'] }}"
|
|
||||||
@if ($bukuItem['id'] == $buku['id']) checked disabled @endif
|
|
||||||
onclick="event.stopPropagation()">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- PERBAIKAN: Checkbox tag dirapikan agar @if nya satu baris --}}
|
||||||
|
<div class="form-check ms-2">
|
||||||
|
<input class="form-check-input book-checkbox" type="checkbox"
|
||||||
|
value="{{ $bukuItem['id'] }}" id="book{{ $bukuItem['id'] }}"
|
||||||
|
@if($bukuItem['id']==$buku['id']) checked disabled @endif
|
||||||
|
onclick="event.stopPropagation()">
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Counter Buku Terpilih -->
|
|
||||||
<div class="p-3 bg-light">
|
<div class="p-3 bg-light">
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<span class="fw-semibold">
|
<span class="fw-semibold">
|
||||||
|
|
@ -220,13 +257,11 @@ class="bi bi-star-fill me-1"></i>Buku Utama</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<div class="modal-footer bg-light">
|
<div class="modal-footer bg-light">
|
||||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">
|
||||||
<i class="bi bi-x-circle me-1"></i> Batal
|
<i class="bi bi-x-circle me-1"></i> Batal
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-primary" id="konfirmasiBuku"
|
<button type="button" class="btn btn-primary" id="konfirmasiBuku" onclick="konfirmasiPilihanBuku()">
|
||||||
onclick="konfirmasiPilihanBuku()">
|
|
||||||
<i class="bi bi-check2-circle me-1"></i> Konfirmasi Pilihan
|
<i class="bi bi-check2-circle me-1"></i> Konfirmasi Pilihan
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -309,7 +344,7 @@ class="bi bi-star-fill me-1"></i>Buku Utama</span>
|
||||||
if (selectedDates.length > 0) {
|
if (selectedDates.length > 0) {
|
||||||
const tglMulai = selectedDates[0];
|
const tglMulai = selectedDates[0];
|
||||||
const maxDateBaru = new Date(tglMulai).fp_incr(2);
|
const maxDateBaru = new Date(tglMulai).fp_incr(2);
|
||||||
const minDateBaru = new Date(tglMulai).fp_incr(1);
|
const minDateBaru = new Date(tglMulai).fp_incr(1);
|
||||||
|
|
||||||
fpKembali.set("minDate", minDateBaru);
|
fpKembali.set("minDate", minDateBaru);
|
||||||
fpKembali.set("maxDate", maxDateBaru);
|
fpKembali.set("maxDate", maxDateBaru);
|
||||||
|
|
@ -322,7 +357,7 @@ class="bi bi-star-fill me-1"></i>Buku Utama</span>
|
||||||
const form = document.getElementById('formPeminjaman');
|
const form = document.getElementById('formPeminjaman');
|
||||||
const arrayBuku = JSON.parse(form.dataset.semuaBuku);
|
const arrayBuku = JSON.parse(form.dataset.semuaBuku);
|
||||||
const bukuUtama = JSON.parse(form.dataset.bukuAwal);
|
const bukuUtama = JSON.parse(form.dataset.bukuAwal);
|
||||||
|
|
||||||
let selectedIds = [bukuUtama.id];
|
let selectedIds = [bukuUtama.id];
|
||||||
const MAX_BOOKS = 2;
|
const MAX_BOOKS = 2;
|
||||||
|
|
||||||
|
|
@ -330,7 +365,7 @@ class="bi bi-star-fill me-1"></i>Buku Utama</span>
|
||||||
window.toggleBookSelection = function(id) {
|
window.toggleBookSelection = function(id) {
|
||||||
const index = selectedIds.indexOf(id);
|
const index = selectedIds.indexOf(id);
|
||||||
const checkbox = document.getElementById('book' + id);
|
const checkbox = document.getElementById('book' + id);
|
||||||
|
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
if (id === bukuUtama.id) return;
|
if (id === bukuUtama.id) return;
|
||||||
selectedIds.splice(index, 1);
|
selectedIds.splice(index, 1);
|
||||||
|
|
@ -363,7 +398,7 @@ function renderDaftarBuku() {
|
||||||
const container = document.getElementById('daftarBukuPinjam');
|
const container = document.getElementById('daftarBukuPinjam');
|
||||||
const hiddenInputs = document.getElementById('hiddenInputs');
|
const hiddenInputs = document.getElementById('hiddenInputs');
|
||||||
const ringkasan = document.getElementById('ringkasanBuku');
|
const ringkasan = document.getElementById('ringkasanBuku');
|
||||||
|
|
||||||
if (!container || !hiddenInputs || !ringkasan) return;
|
if (!container || !hiddenInputs || !ringkasan) return;
|
||||||
|
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
|
|
@ -375,7 +410,7 @@ function renderDaftarBuku() {
|
||||||
if (!buku) return;
|
if (!buku) return;
|
||||||
|
|
||||||
const isUtama = id === (typeof bukuUtama.id === 'string' ? parseInt(bukuUtama.id) : bukuUtama.id);
|
const isUtama = id === (typeof bukuUtama.id === 'string' ? parseInt(bukuUtama.id) : bukuUtama.id);
|
||||||
|
|
||||||
const itemHtml = `
|
const itemHtml = `
|
||||||
<div class="book-item border rounded p-3 mb-3" data-book-id="${buku.id}">
|
<div class="book-item border rounded p-3 mb-3" data-book-id="${buku.id}">
|
||||||
<div class="d-flex align-items-start text-start">
|
<div class="d-flex align-items-start text-start">
|
||||||
|
|
@ -427,4 +462,4 @@ function renderDaftarBuku() {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
@ -1,32 +1,124 @@
|
||||||
@section('page-title', 'Profile')
|
|
||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
<div class="d-flex align-items-center mb-4">
|
@section('page-title', 'Pengaturan Akun')
|
||||||
<a href="{{ route('profile.index') }}" class="btn btn-outline-secondary me-3">
|
|
||||||
<i class="bi bi-arrow-left"></i>
|
|
||||||
</a>
|
|
||||||
<h1 class="h2 mb-0">Edit Profil</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row justify-content-center">
|
<div class="container py-4">
|
||||||
<div class="col-lg-10">
|
<div class="row gx-4">
|
||||||
<div class="card border-0 shadow-sm mb-4">
|
|
||||||
<div class="card-body p-4">
|
{{-- SIDEBAR MENU (KIRI) --}}
|
||||||
@include('profile.partials.update-profile-information-form')
|
<div class="col-md-3 mb-4">
|
||||||
|
<div class="card border-0 shadow-sm sticky-top" style="top: 80px; z-index: 1;">
|
||||||
|
<div class="card-body p-0">
|
||||||
|
<div class="list-group list-group-flush rounded-3">
|
||||||
|
{{-- Header --}}
|
||||||
|
<div class="p-3 border-bottom bg-light">
|
||||||
|
<h6 class="m-0 fw-bold text-dark">
|
||||||
|
<i class="bi bi-gear-fill me-2 text-primary"></i>Pengaturan
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Menu Tabs --}}
|
||||||
|
<div class="nav flex-column nav-pills p-2" id="v-pills-tab" role="tablist" aria-orientation="vertical">
|
||||||
|
{{-- Tab Profil --}}
|
||||||
|
<button class="nav-link active d-flex align-items-center mb-1 py-3 px-3" id="v-pills-profile-tab"
|
||||||
|
data-bs-toggle="pill" data-bs-target="#v-pills-profile" type="button" role="tab">
|
||||||
|
<i class="bi bi-person-badge me-3 fs-5"></i>
|
||||||
|
<div class="text-start">
|
||||||
|
<div class="fw-bold">Profil Saya</div>
|
||||||
|
<div class="small opacity-75">Nama, Email, & Hapus Akun</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{{-- Tab Keamanan --}}
|
||||||
|
<button class="nav-link d-flex align-items-center py-3 px-3" id="v-pills-security-tab"
|
||||||
|
data-bs-toggle="pill" data-bs-target="#v-pills-security" type="button" role="tab">
|
||||||
|
<i class="bi bi-shield-lock me-3 fs-5"></i>
|
||||||
|
<div class="text-start">
|
||||||
|
<div class="fw-bold">Keamanan</div>
|
||||||
|
<div class="small opacity-75">Kata Sandi & Proteksi</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="security" class="card border-0 shadow-sm mb-4">
|
{{-- KONTEN KANAN (FORM) --}}
|
||||||
<div class="card-body p-4">
|
<div class="col-md-9">
|
||||||
@include('profile.partials.update-password-form')
|
<div class="tab-content" id="v-pills-tabContent" style="min-height: 500px;">
|
||||||
</div>
|
{{-- PROFIL & HAPUS AKUN --}}
|
||||||
</div>
|
<div class="tab-pane fade show active" id="v-pills-profile" role="tabpanel">
|
||||||
|
|
||||||
|
{{-- Form Edit Profil --}}
|
||||||
|
<div class="card border-0 shadow-sm mb-4">
|
||||||
|
<div class="card-header bg-white py-3 border-bottom">
|
||||||
|
<h6 class="m-0 fw-bold text-primary">Informasi Profil</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
@include('profile.partials.update-profile-information-form')
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Form Hapus Akun --}}
|
||||||
|
<div class="card border-0 shadow-sm border-danger-subtle">
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="d-flex align-items-start">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<i class="bi bi-exclamation-triangle-fill text-danger fs-3 me-3"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h6 class="fw-bold text-danger">Hapus Akun Permanen</h6>
|
||||||
|
<p class="text-muted small mb-3">
|
||||||
|
Tindakan ini tidak dapat dibatalkan. Semua data Anda akan hilang.
|
||||||
|
</p>
|
||||||
|
@include('profile.partials.delete-user-form')
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- KEAMANAN (PASSWORD) --}}
|
||||||
|
<div class="tab-pane fade" id="v-pills-security" role="tabpanel">
|
||||||
|
<div class="card border-0 shadow-sm h-100">
|
||||||
|
<div class="card-header bg-white py-3 border-bottom">
|
||||||
|
<h6 class="m-0 fw-bold text-primary">Ganti Kata Sandi</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="alert alert-info border-0 d-flex align-items-center mb-4">
|
||||||
|
<i class="bi bi-info-circle-fill me-2 fs-5"></i>
|
||||||
|
<div>
|
||||||
|
Gunakan password minimal 8 karakter dengan kombinasi huruf dan angka agar akun lebih aman.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@include('profile.partials.update-password-form')
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card border-danger shadow-sm">
|
|
||||||
<div class="card-body p-4">
|
|
||||||
@include('profile.partials.delete-user-form')
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@push('styles')
|
||||||
|
<style>
|
||||||
|
.nav-pills .nav-link {
|
||||||
|
color: #495057;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
.nav-pills .nav-link:hover {
|
||||||
|
background-color: #e9ecef;
|
||||||
|
color: #0d6efd;
|
||||||
|
}
|
||||||
|
.nav-pills .nav-link.active {
|
||||||
|
background-color: #0d6efd;
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 4px 6px rgba(13, 110, 253, 0.15);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@endpush
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
@ -3,110 +3,102 @@
|
||||||
|
|
||||||
<div class="row g-3 g-md-4 min-vh-100 pb-4">
|
<div class="row g-3 g-md-4 min-vh-100 pb-4">
|
||||||
|
|
||||||
{{-- =================================================================== --}}
|
|
||||||
{{-- TAMPILAN PROFIL UNTUK PENJAGA PERPUSTAKAAN --}}
|
|
||||||
{{-- =================================================================== --}}
|
|
||||||
@if (Auth::user()->role == 'penjaga perpus')
|
@if (Auth::user()->role == 'penjaga perpus')
|
||||||
|
<div class="row g-3 g-md-4 h-100">
|
||||||
<div class="row g-3 g-md-4 h-100">
|
<div class="col-lg-8 d-flex flex-column">
|
||||||
{{-- Kolom Kiri: Info & Statistik Global --}}
|
<div class="card border-0 mb-3 mb-md-4">
|
||||||
<div class="col-lg-8 d-flex flex-column">
|
<div
|
||||||
{{-- Info Petugas --}}
|
class="card-body p-3 p-md-4 d-flex flex-column flex-sm-row align-items-center text-center text-sm-start">
|
||||||
<div class="card border-0 mb-3 mb-md-4">
|
<img src="https://ui-avatars.com/api/?name={{ urlencode($user->name) }}&background=435ebe&color=fff&size=80&rounded=true"
|
||||||
<div
|
alt="Foto Profil" class="rounded-circle profile-avatar-lg mb-3 mb-sm-0">
|
||||||
class="card-body p-3 p-md-4 d-flex flex-column flex-sm-row align-items-center text-center text-sm-start">
|
<div class="ms-sm-4 mb-3 mb-sm-0">
|
||||||
<img src="https://ui-avatars.com/api/?name={{ urlencode($user->name) }}&background=435ebe&color=fff&size=80&rounded=true"
|
<h4 class="fw-bold mb-1">{{ $user->name }}</h4>
|
||||||
alt="Foto Profil" class="rounded-circle profile-avatar-lg mb-3 mb-sm-0">
|
<span class="badge rounded-pill bg-success-subtle text-success-emphasis">{{
|
||||||
<div class="ms-sm-4">
|
Str::title($user->role) }}</span>
|
||||||
<h4 class="fw-bold mb-1">{{ $user->name }}</h4>
|
|
||||||
<span
|
|
||||||
class="badge rounded-pill bg-success-subtle text-success-emphasis">{{ Str::title($user->role) }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="ms-sm-auto">
|
||||||
|
|
||||||
{{-- Statistik Perpustakaan --}}
|
|
||||||
<div class="mb-3 mb-md-4 flex-grow-1">
|
|
||||||
<h5 class="fw-bold mb-3">Statistik Perpustakaan</h5>
|
|
||||||
<div class="row g-3">
|
|
||||||
@foreach ($statistik as $stat)
|
|
||||||
<div class="col-sm-6 col-lg-3">
|
|
||||||
<div class="card border-0 h-100">
|
|
||||||
<div class="card-body p-3 p-md-4 text-center">
|
|
||||||
<div class="icon-circle bg-{{ $stat['color'] }}-light mx-auto mb-3"
|
|
||||||
style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; border-radius: 15px;">
|
|
||||||
<i class="bi {{ $stat['icon'] }} fs-2 text-{{ $stat['color'] }}"></i>
|
|
||||||
</div>
|
|
||||||
<h3 class="fw-bold mb-2">{{ $stat['value'] }}</h3>
|
|
||||||
<p class="text-muted mb-0 small">{{ $stat['label'] }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Kolom Kanan: Pintasan & Aktivitas --}}
|
|
||||||
<div class="col-lg-4 d-flex flex-column">
|
|
||||||
{{-- Pintasan Manajemen --}}
|
|
||||||
<div class="card border-0 mb-3 mb-md-4 flex-grow-1">
|
|
||||||
<div class="card-body p-3 p-md-4 d-flex flex-column h-100">
|
|
||||||
<h5 class="fw-bold mb-4">Pintasan Manajemen</h5>
|
|
||||||
<div class="d-grid gap-3 flex-grow-1">
|
|
||||||
<a href="{{ route('admin.buku.index') }}"
|
|
||||||
class="btn btn-light text-start py-3 d-flex align-items-center">
|
|
||||||
<i class="bi bi-book-fill me-3 fs-4"></i>
|
|
||||||
<span>Kelola Buku</span>
|
|
||||||
</a>
|
|
||||||
<a href="{{ route('admin.pengguna.index') }}"
|
|
||||||
class="btn btn-light text-start py-3 d-flex align-items-center">
|
|
||||||
<i class="bi bi-people-fill me-3 fs-4"></i>
|
|
||||||
<span>Kelola Pengguna</span>
|
|
||||||
</a>
|
|
||||||
<a href="{{ route('admin.pengumuman.index') }}"
|
|
||||||
class="btn btn-light text-start py-3 d-flex align-items-center">
|
|
||||||
<i class="bi bi-megaphone-fill me-3 fs-4"></i>
|
|
||||||
<span>Kelola Pengumuman</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Keamanan Akun --}}
|
|
||||||
<div class="card border-0">
|
|
||||||
<div class="card-body p-3 p-md-4">
|
|
||||||
<h5 class="fw-bold mb-3">Keamanan Akun</h5>
|
|
||||||
<p class="small text-muted mb-3">Ubah password Anda secara berkala untuk menjaga keamanan
|
|
||||||
akun.</p>
|
|
||||||
<a href="{{ route('profile.edit') }}"
|
<a href="{{ route('profile.edit') }}"
|
||||||
class="btn btn-outline-secondary rounded-pill w-100 py-2">
|
class="btn btn-outline-primary rounded-pill w-100 w-sm-auto">
|
||||||
<i class="bi bi-shield-lock me-2"></i>Ubah Password
|
<i class="bi bi-pencil-square me-2"></i>Edit Profil
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
@elseif (Auth::user()->role == 'guru')
|
<div class="mb-3 mb-md-4 flex-grow-1">
|
||||||
{{-- =================================================================== --}}
|
<h5 class="fw-bold mb-3">Statistik Perpustakaan</h5>
|
||||||
{{-- TAMPILAN PROFIL UNTUK GURU --}}
|
<div class="row g-3">
|
||||||
{{-- =================================================================== --}}
|
@foreach ($statistik as $stat)
|
||||||
<div class="row g-3 g-md-4 h-100">
|
<div class="col-sm-6 col-lg-3">
|
||||||
{{-- Kolom Kiri: Info & Ringkasan Laporan --}}
|
<div class="card border-0 h-100">
|
||||||
<div class="col-lg-8 d-flex flex-column">
|
<div class="card-body p-3 p-md-4 text-center">
|
||||||
{{-- Info Guru --}}
|
<div class="icon-circle bg-{{ $stat['color'] }}-light mx-auto mb-3"
|
||||||
<div class="card border-0 mb-3 mb-md-4">
|
style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; border-radius: 15px;">
|
||||||
<div
|
<i class="bi {{ $stat['icon'] }} fs-2 text-{{ $stat['color'] }}"></i>
|
||||||
class="card-body p-3 p-md-4 d-flex flex-column flex-md-row align-items-center text-center text-md-start">
|
</div>
|
||||||
<img src="https://ui-avatars.com/api/?name={{ urlencode($user->name) }}&background=198754&color=fff&size=80&rounded=true"
|
<h3 class="fw-bold mb-2">{{ $stat['value'] }}</h3>
|
||||||
alt="Foto Profil" class="rounded-circle profile-avatar-lg mb-3 mb-md-0">
|
<p class="text-muted mb-0 small">{{ $stat['label'] }}</p>
|
||||||
<div class="ms-md-4 mb-3 mb-md-0">
|
</div>
|
||||||
<h4 class="fw-bold mb-1">{{ $user->name }}</h4>
|
|
||||||
<span
|
|
||||||
class="badge rounded-pill bg-success-subtle text-success-emphasis">{{ Str::title($user->role) }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-4 d-flex flex-column">
|
||||||
|
<div class="card border-0 mb-3 mb-md-4 flex-grow-1">
|
||||||
|
<div class="card-body p-3 p-md-4 d-flex flex-column h-100">
|
||||||
|
<h5 class="fw-bold mb-4">Pintasan Manajemen</h5>
|
||||||
|
<div class="d-grid gap-3 flex-grow-1">
|
||||||
|
<a href="{{ route('admin.buku.index') }}"
|
||||||
|
class="btn btn-light text-start py-3 d-flex align-items-center">
|
||||||
|
<i class="bi bi-book-fill me-3 fs-4"></i>
|
||||||
|
<span>Kelola Buku</span>
|
||||||
|
</a>
|
||||||
|
<a href="{{ route('admin.pengguna.index') }}"
|
||||||
|
class="btn btn-light text-start py-3 d-flex align-items-center">
|
||||||
|
<i class="bi bi-people-fill me-3 fs-4"></i>
|
||||||
|
<span>Kelola Pengguna</span>
|
||||||
|
</a>
|
||||||
|
<a href="{{ route('admin.pengumuman.index') }}"
|
||||||
|
class="btn btn-light text-start py-3 d-flex align-items-center">
|
||||||
|
<i class="bi bi-megaphone-fill me-3 fs-4"></i>
|
||||||
|
<span>Kelola Pengumuman</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- <div class="card border-0">
|
||||||
|
<div class="card-body p-3 p-md-4">
|
||||||
|
<h5 class="fw-bold mb-3">Keamanan Akun</h5>
|
||||||
|
<p class="small text-muted mb-3">Ubah password Anda secara berkala untuk menjaga keamanan akun.
|
||||||
|
</p>
|
||||||
|
<a href="{{ route('profile.edit') }}" class="btn btn-outline-secondary rounded-pill w-100 py-2">
|
||||||
|
<i class="bi bi-shield-lock me-2"></i>Ubah Password
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div> --}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@elseif (Auth::user()->role == 'guru')
|
||||||
|
<div class="row g-3 g-md-4 h-100">
|
||||||
|
<div class="col-lg-8 d-flex flex-column">
|
||||||
|
<div class="card border-0 mb-3 mb-md-4">
|
||||||
|
<div class="card-body p-3 p-md-4">
|
||||||
|
<div class="d-flex flex-column flex-sm-row align-items-center text-center text-sm-start">
|
||||||
|
<img src="https://ui-avatars.com/api/?name={{ urlencode($user->name) }}&background=198754&color=fff&size=80&rounded=true"
|
||||||
|
alt="Foto Profil" class="rounded-circle profile-avatar-lg mb-3 mb-sm-0">
|
||||||
|
<div class="ms-sm-4 mb-3 mb-sm-0">
|
||||||
|
<h4 class="fw-bold mb-1">{{ $user->name }}</h4>
|
||||||
|
<span class="badge rounded-pill bg-success-subtle text-success-emphasis">{{
|
||||||
|
Str::title($user->role) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="ms-sm-auto">
|
||||||
<a href="{{ route('profile.edit') }}"
|
<a href="{{ route('profile.edit') }}"
|
||||||
class="btn btn-outline-primary rounded-pill w-100 w-md-auto ms-md-auto">
|
class="btn btn-outline-primary rounded-pill ms-sm-auto w-100 w-sm-auto">
|
||||||
<i class="bi bi-pencil-square me-2"></i>Edit Profil
|
<i class="bi bi-pencil-square me-2"></i>Edit Profil
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -128,135 +120,147 @@ class="btn btn-outline-primary rounded-pill w-100 w-md-auto ms-md-auto">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Ringkasan Laporan Minat Baca --}}
|
<hr class="my-3 my-md-4">
|
||||||
<div class="card border-0 flex-grow-1">
|
<h5 class="fw-bold mb-3">Informasi Personal</h5>
|
||||||
<div class="card-body p-3 p-md-4 d-flex flex-column h-100">
|
<div class="row g-3">
|
||||||
<div
|
<div class="col-sm-6">
|
||||||
class="d-flex flex-column flex-sm-row justify-content-between align-items-start align-items-sm-center mb-4 gap-2">
|
<small class="text-muted d-block mb-1">NIP/NIK</small>
|
||||||
<h5 class="fw-bold mb-0">Ringkasan Laporan Minat Baca</h5>
|
<p class="fw-semibold mb-0">{{ $user->nip ?? $user->nisn ?? '-' }}</p>
|
||||||
<a href="{{ route('guru.laporan.index') }}"
|
</div>
|
||||||
class="btn btn-sm btn-outline-primary rounded-pill w-100 w-sm-auto">
|
<div class="col-sm-6">
|
||||||
Lihat Laporan Lengkap
|
<small class="text-muted d-block mb-1">Email</small>
|
||||||
</a>
|
<p class="fw-semibold mb-0 text-break">{{ $user->email }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="row flex-grow-1">
|
<div class="col-sm-6">
|
||||||
<div class="col-md-6 mb-3 mb-md-0">
|
<small class="text-muted d-block mb-1">Nomor HP</small>
|
||||||
<h6 class="small text-muted mb-3 text-uppercase fw-semibold">Buku Terpopuler</h6>
|
<p class="fw-semibold mb-0">{{ $user->no_hp ?? '-' }}</p>
|
||||||
<ul class="list-group list-group-flush laporan-list">
|
|
||||||
@foreach ($laporan['buku_terpopuler'] as $buku)
|
|
||||||
<li
|
|
||||||
class="list-group-item px-0 py-3 d-flex justify-content-between align-items-center">
|
|
||||||
<span class="text-truncate me-2">{{ $buku['judul'] }}</span>
|
|
||||||
<span
|
|
||||||
class="badge bg-primary rounded-pill">{{ $buku['total_pembaca'] }}</span>
|
|
||||||
</li>
|
|
||||||
@endforeach
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h6 class="small text-muted mb-3 text-uppercase fw-semibold">Kategori Terpopuler
|
|
||||||
</h6>
|
|
||||||
<ul class="list-group list-group-flush laporan-list">
|
|
||||||
@foreach ($laporan['kategori_populer'] as $kategori)
|
|
||||||
<li
|
|
||||||
class="list-group-item px-0 py-3 d-flex justify-content-between align-items-center">
|
|
||||||
<span class="text-truncate me-2">{{ $kategori['nama'] }}</span>
|
|
||||||
<span
|
|
||||||
class="badge bg-success rounded-pill">{{ $kategori['total_pembaca'] }}</span>
|
|
||||||
</li>
|
|
||||||
@endforeach
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Kolom Kanan: Aktivitas Personal Guru --}}
|
|
||||||
<div class="col-lg-4">
|
|
||||||
@include('profile.partials.personal-activities', [
|
|
||||||
'bukuOffline' => $bukuOffline,
|
|
||||||
'bukuOnline' => $bukuOnline,
|
|
||||||
])
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
@else
|
|
||||||
{{-- =================================================================== --}}
|
<div class="card border-0 flex-grow-1">
|
||||||
{{-- TAMPILAN PROFIL UNTUK SISWA (DEFAULT) --}}
|
<div class="card-body p-3 p-md-4 d-flex flex-column h-100">
|
||||||
{{-- =================================================================== --}}
|
<div
|
||||||
<div class="row g-3 g-md-4 h-100">
|
class="d-flex flex-column flex-sm-row justify-content-between align-items-center mb-4 gap-3">
|
||||||
{{-- Kolom Kiri: Info & Statistik Siswa --}}
|
<h5 class="fw-bold mb-0">Ringkasan Laporan Minat Baca</h5>
|
||||||
<div class="col-lg-8 d-flex flex-column">
|
<div class="ms-sm-auto">
|
||||||
{{-- Info Siswa --}}
|
<a href="{{ route('guru.laporan.index') }}"
|
||||||
<div class="card border-0 mb-3 mb-md-4">
|
class="btn btn-sm btn-outline-primary rounded-pill w-100 w-sm-auto">
|
||||||
<div class="card-body p-3 p-md-4">
|
Lihat Laporan Lengkap
|
||||||
<div class="d-flex flex-column flex-md-row align-items-center text-center text-md-start">
|
</a>
|
||||||
<img src="https://ui-avatars.com/api/?name={{ urlencode($user->name) }}&background=435ebe&color=fff&size=80&rounded=true"
|
|
||||||
alt="Foto Profil" class="rounded-circle profile-avatar-lg mb-3 mb-md-0">
|
|
||||||
<div class="ms-md-4 mb-3 mb-md-0">
|
|
||||||
<h4 class="fw-bold mb-1">{{ $user->name }}</h4>
|
|
||||||
<span
|
|
||||||
class="badge rounded-pill bg-primary-subtle text-primary-emphasis">{{ Str::title($user->role) }}</span>
|
|
||||||
</div>
|
|
||||||
<a href="{{ route('profile.edit') }}"
|
|
||||||
class="btn btn-outline-primary rounded-pill ms-md-auto">
|
|
||||||
<i class="bi bi-pencil-square me-2"></i>Edit Profil
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<hr class="my-3 my-md-4">
|
|
||||||
<h5 class="fw-bold mb-3">Informasi Personal</h5>
|
|
||||||
<div class="row g-3">
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<small class="text-muted d-block mb-1">NISN</small>
|
|
||||||
<p class="fw-semibold mb-0">{{ $user->nomor_induk ?? 'N/A' }}</p>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<small class="text-muted d-block mb-1">Email</small>
|
|
||||||
<p class="fw-semibold mb-0 text-break">{{ $user->email }}</p>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<small class="text-muted d-block mb-1">Nomor HP</small>
|
|
||||||
<p class="fw-semibold mb-0">{{ $user->phone ?? 'N/A' }}</p>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<small class="text-muted d-block mb-1">Kelas</small>
|
|
||||||
<p class="fw-semibold mb-0">{{ $user->kelas ?? 'N/A' }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row flex-grow-1">
|
||||||
|
<div class="col-md-6 mb-3 mb-md-0">
|
||||||
|
<h6 class="small text-muted mb-3 text-uppercase fw-semibold">Buku Terpopuler</h6>
|
||||||
|
<ul class="list-group list-group-flush laporan-list">
|
||||||
|
@foreach ($laporan['buku_terpopuler'] as $buku)
|
||||||
|
<li
|
||||||
|
class="list-group-item px-0 py-3 d-flex justify-content-between align-items-center">
|
||||||
|
<span class="text-truncate me-2">{{ $buku['judul'] }}</span>
|
||||||
|
<span class="badge bg-primary rounded-pill">{{ $buku['total_pembaca'] }}</span>
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h6 class="small text-muted mb-3 text-uppercase fw-semibold">Kategori Terpopuler</h6>
|
||||||
|
<ul class="list-group list-group-flush laporan-list">
|
||||||
|
@foreach ($laporan['kategori_populer'] as $kategori)
|
||||||
|
<li
|
||||||
|
class="list-group-item px-0 py-3 d-flex justify-content-between align-items-center">
|
||||||
|
<span class="text-truncate me-2">{{ $kategori['nama'] }}</span>
|
||||||
|
<span class="badge bg-success rounded-pill">{{ $kategori['total_pembaca']
|
||||||
|
}}</span>
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- Statistik Personal Siswa --}}
|
<div class="col-lg-4">
|
||||||
<div class="mb-3 mb-md-4 flex-grow-1">
|
@include('profile.partials.personal-activities', [
|
||||||
<h5 class="fw-bold mb-3">Statistik Saya</h5>
|
'bukuOffline' => $bukuOffline,
|
||||||
|
'bukuOnline' => $bukuOnline,
|
||||||
|
])
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@else
|
||||||
|
<div class="row g-3 g-md-4 h-100">
|
||||||
|
<div class="col-lg-8 d-flex flex-column">
|
||||||
|
<div class="card border-0 mb-3 mb-md-4">
|
||||||
|
<div class="card-body p-3 p-md-4">
|
||||||
|
<div class="d-flex flex-column flex-sm-row align-items-center text-center text-sm-start">
|
||||||
|
<img src="https://ui-avatars.com/api/?name={{ urlencode($user->name) }}&background=435ebe&color=fff&size=80&rounded=true"
|
||||||
|
alt="Foto Profil" class="rounded-circle profile-avatar-lg mb-3 mb-sm-0">
|
||||||
|
<div class="ms-sm-4 mb-3 mb-sm-0">
|
||||||
|
<h4 class="fw-bold mb-1">{{ $user->name }}</h4>
|
||||||
|
<span class="badge rounded-pill bg-primary-subtle text-primary-emphasis">{{
|
||||||
|
Str::title($user->role) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="ms-sm-auto">
|
||||||
|
<a href="{{ route('profile.edit') }}"
|
||||||
|
class="btn btn-outline-primary rounded-pill ms-md-auto">
|
||||||
|
<i class="bi bi-pencil-square me-2"></i>Edit Profil
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<hr class="my-3 my-md-4">
|
||||||
|
<h5 class="fw-bold mb-3">Informasi Personal</h5>
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
@foreach ($statistik as $stat)
|
<div class="col-sm-6">
|
||||||
<div class="col-sm-6 col-lg-3">
|
<small class="text-muted d-block mb-1">NISN</small>
|
||||||
<div class="card border-0 h-100">
|
<p class="fw-semibold mb-0">{{ $user->nomor_induk ?? 'N/A' }}</p>
|
||||||
<div class="card-body p-3 p-md-4 text-center">
|
</div>
|
||||||
<div class="icon-circle bg-{{ $stat['color'] }}-light mx-auto mb-3"
|
<div class="col-sm-6">
|
||||||
style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; border-radius: 15px;">
|
<small class="text-muted d-block mb-1">Email</small>
|
||||||
<i class="bi {{ $stat['icon'] }} fs-2 text-{{ $stat['color'] }}"></i>
|
<p class="fw-semibold mb-0 text-break">{{ $user->email }}</p>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="fw-bold mb-2">{{ $stat['value'] }}</h3>
|
<div class="col-sm-6">
|
||||||
<p class="text-muted mb-0 small">{{ $stat['label'] }}</p>
|
<small class="text-muted d-block mb-1">Nomor HP</small>
|
||||||
</div>
|
<p class="fw-semibold mb-0">{{ $user->phone ?? 'N/A' }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-sm-6">
|
||||||
@endforeach
|
<small class="text-muted d-block mb-1">Kelas</small>
|
||||||
|
<p class="fw-semibold mb-0">{{ $user->kelas ?? 'N/A' }}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Kolom Kanan: Aktivitas Personal Siswa --}}
|
<div class="mb-3 mb-md-4 flex-grow-1">
|
||||||
<div class="col-lg-4">
|
<h5 class="fw-bold mb-3">Statistik Saya</h5>
|
||||||
@include('profile.partials.personal-activities', [
|
<div class="row g-3">
|
||||||
'bukuOffline' => $bukuOffline,
|
@foreach ($statistik as $stat)
|
||||||
'bukuOnline' => $bukuOnline,
|
<div class="col-sm-6 col-lg-3">
|
||||||
])
|
<div class="card border-0 h-100">
|
||||||
|
<div class="card-body p-3 p-md-4 text-center">
|
||||||
|
<div class="icon-circle bg-{{ $stat['color'] }}-light mx-auto mb-3"
|
||||||
|
style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; border-radius: 15px;">
|
||||||
|
<i class="bi {{ $stat['icon'] }} fs-2 text-{{ $stat['color'] }}"></i>
|
||||||
|
</div>
|
||||||
|
<h3 class="fw-bold mb-2">{{ $stat['value'] }}</h3>
|
||||||
|
<p class="text-muted mb-0 small">{{ $stat['label'] }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-4">
|
||||||
|
@include('profile.partials.personal-activities', [
|
||||||
|
'bukuOffline' => $bukuOffline,
|
||||||
|
'bukuOnline' => $bukuOnline,
|
||||||
|
])
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
@ -34,11 +34,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Card Keamanan Akun --}}
|
{{-- Card Keamanan Akun
|
||||||
<div class="card border-0">
|
<div class="card border-0">
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<h5 class="fw-bold mb-3">Keamanan Akun</h5>
|
<h5 class="fw-bold mb-3">Keamanan Akun</h5>
|
||||||
<p class="small text-muted">Ubah password Anda secara berkala.</p>
|
<p class="small text-muted">Ubah password Anda secara berkala.</p>
|
||||||
<a href="{{ route('profile.edit') }}" class="btn btn-outline-secondary rounded-pill">Ubah Password</a>
|
<a href="{{ route('profile.edit') }}" class="btn btn-outline-secondary rounded-pill">Ubah Password</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> --}}
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
<section>
|
<section>
|
||||||
<header>
|
<header>
|
||||||
<h2 class="h5 fw-bold">
|
<h2 class="h5 fw-bold text-dark">
|
||||||
{{ __('Update Password') }}
|
{{ __('Update Password') }}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p class="mt-1 text-muted small">
|
<p class="mt-1 text-muted small">
|
||||||
{{ __('Ensure your account is using a long, random password to stay secure.') }}
|
{{ __('Pastikan akun Anda menggunakan kata sandi yang panjang dan acak untuk menjaga keamanan.') }}
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
@ -15,43 +15,89 @@
|
||||||
|
|
||||||
{{-- Current Password --}}
|
{{-- Current Password --}}
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="update_password_current_password" class="form-label">{{ __('Current Password') }}</label>
|
<label for="update_password_current_password" class="form-label">{{ __('Kata Sandi Saat Ini') }}</label>
|
||||||
<input id="update_password_current_password" name="current_password" type="password"
|
<div class="input-group">
|
||||||
class="form-control @error('current_password', 'updatePassword') is-invalid @enderror"
|
<input id="update_password_current_password" name="current_password" type="password"
|
||||||
autocomplete="current-password">
|
class="form-control @error('current_password', 'updatePassword') is-invalid @enderror"
|
||||||
@error('current_password', 'updatePassword')
|
autocomplete="current-password">
|
||||||
<div class="invalid-feedback">{{ $message }}</div>
|
<button class="btn btn-outline-secondary toggle-password" type="button">
|
||||||
@enderror
|
<i class="bi bi-eye-slash"></i>
|
||||||
|
</button>
|
||||||
|
@error('current_password', 'updatePassword')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- New Password --}}
|
{{-- New Password --}}
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="update_password_password" class="form-label">{{ __('New Password') }}</label>
|
<label for="update_password_password" class="form-label">{{ __('Kata Sandi Baru') }}</label>
|
||||||
<input id="update_password_password" name="password" type="password"
|
<div class="input-group">
|
||||||
class="form-control @error('password', 'updatePassword') is-invalid @enderror"
|
<input id="update_password_password" name="password" type="password"
|
||||||
autocomplete="new-password">
|
class="form-control @error('password', 'updatePassword') is-invalid @enderror"
|
||||||
@error('password', 'updatePassword')
|
autocomplete="new-password">
|
||||||
<div class="invalid-feedback">{{ $message }}</div>
|
<button class="btn btn-outline-secondary toggle-password" type="button">
|
||||||
@enderror
|
<i class="bi bi-eye-slash"></i>
|
||||||
|
</button>
|
||||||
|
@error('password', 'updatePassword')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Confirm Password --}}
|
{{-- Confirm Password --}}
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="update_password_password_confirmation" class="form-label">{{ __('Confirm Password') }}</label>
|
<label for="update_password_password_confirmation" class="form-label">{{ __('Konfirmasi Kata Sandi') }}</label>
|
||||||
<input id="update_password_password_confirmation" name="password_confirmation" type="password"
|
<div class="input-group">
|
||||||
class="form-control @error('password_confirmation', 'updatePassword') is-invalid @enderror"
|
<input id="update_password_password_confirmation" name="password_confirmation" type="password"
|
||||||
autocomplete="new-password">
|
class="form-control @error('password_confirmation', 'updatePassword') is-invalid @enderror"
|
||||||
@error('password_confirmation', 'updatePassword')
|
autocomplete="new-password">
|
||||||
<div class="invalid-feedback">{{ $message }}</div>
|
<button class="btn btn-outline-secondary toggle-password" type="button">
|
||||||
@enderror
|
<i class="bi bi-eye-slash"></i>
|
||||||
|
</button>
|
||||||
|
@error('password_confirmation', 'updatePassword')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-flex align-items-center gap-3">
|
<div class="d-flex align-items-center gap-3 mt-4">
|
||||||
<button type="submit" class="btn btn-primary">{{ __('Save') }}</button>
|
<button type="submit" class="btn btn-primary px-4 shadow-sm">
|
||||||
|
<i class="bi bi-save me-1"></i> {{ __('Simpan Perubahan') }}
|
||||||
@if (session('status') === 'password-updated')
|
</button>
|
||||||
<span class="text-success fw-bold">{{ __('Saved.') }}</span>
|
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const toggleButtons = document.querySelectorAll('.toggle-password');
|
||||||
|
|
||||||
|
toggleButtons.forEach(button => {
|
||||||
|
button.addEventListener('click', function() {
|
||||||
|
const input = this.parentElement.querySelector('input');
|
||||||
|
const icon = this.querySelector('i');
|
||||||
|
|
||||||
|
if (input.type === 'password') {
|
||||||
|
input.type = 'text';
|
||||||
|
icon.classList.remove('bi-eye-slash');
|
||||||
|
icon.classList.add('bi-eye');
|
||||||
|
} else {
|
||||||
|
input.type = 'password';
|
||||||
|
icon.classList.remove('bi-eye');
|
||||||
|
icon.classList.add('bi-eye-slash');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@if (session('status') === 'password-updated')
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil!',
|
||||||
|
text: 'Kata sandi baru sudah berhasil diperbarui.',
|
||||||
|
showConfirmButton: false,
|
||||||
|
timer: 3000,
|
||||||
|
timerProgressBar: true
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</section>
|
||||||
|
|
@ -19,11 +19,11 @@
|
||||||
|
|
||||||
{{-- Bagian Nama Lengkap --}}
|
{{-- Bagian Nama Lengkap --}}
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="nama_lengkap" class="form-label">{{ __('Nama Lengkap') }}</label>
|
<label for="name" class="form-label">{{ __('Nama Lengkap') }}</label>
|
||||||
<input id="nama_lengkap" name="nama_lengkap" type="text" class="form-control @error('nama_lengkap') is-invalid @enderror"
|
<input id="name" name="name" type="text" class="form-control @error('name') is-invalid @enderror"
|
||||||
value="{{ old('nama_lengkap', $user->nama_lengkap) }}" required autofocus autocomplete="name">
|
value="{{ old('name', $user->name) }}" required autofocus autocomplete="name">
|
||||||
@error('nama_lengkap')
|
@error('name')
|
||||||
<div class="invalid-feedback">{{ $message }}</div>
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -34,63 +34,63 @@
|
||||||
class="form-control @error('email') is-invalid @enderror" value="{{ old('email', $user->email) }}"
|
class="form-control @error('email') is-invalid @enderror" value="{{ old('email', $user->email) }}"
|
||||||
required autocomplete="username">
|
required autocomplete="username">
|
||||||
@error('email')
|
@error('email')
|
||||||
<div class="invalid-feedback">{{ $message }}</div>
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
@enderror
|
@enderror
|
||||||
|
|
||||||
@if ($user instanceof \Illuminate\Contracts\Auth\MustVerifyEmail && !$user->hasVerifiedEmail())
|
@if ($user instanceof \Illuminate\Contracts\Auth\MustVerifyEmail && !$user->hasVerifiedEmail())
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<p class="small text-muted">
|
<p class="small text-muted">
|
||||||
{{ __('Alamat email Anda belum terverifikasi.') }}
|
{{ __('Alamat email Anda belum terverifikasi.') }}
|
||||||
<button form="send-verification" class="btn btn-link text-decoration-underline p-0 small">
|
<button form="send-verification" class="btn btn-link text-decoration-underline p-0 small">
|
||||||
{{ __('Klik di sini untuk mengirim ulang email verifikasi.') }}
|
{{ __('Klik di sini untuk mengirim ulang email verifikasi.') }}
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
@if (session('status') === 'verification-link-sent')
|
@if (session('status') === 'verification-link-sent')
|
||||||
<p class="mt-2 fw-medium small text-success">
|
<p class="mt-2 fw-medium small text-success">
|
||||||
{{ __('Tautan verifikasi baru telah dikirim ke alamat email Anda.') }}
|
{{ __('Tautan verifikasi baru telah dikirim ke alamat email Anda.') }}
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Bagian Nomor Telepon --}}
|
{{-- Bagian Nomor Telepon --}}
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="phone" class="form-label">{{ __('Nomor Telepon (WA)') }}</label>
|
<label for="phone" class="form-label">{{ __('Nomor Telepon (WA)') }}</label>
|
||||||
<input id="phone" name="phone" type="text" class="form-control @error('phone') is-invalid @enderror"
|
<input id="phone" name="phone" type="text" class="form-control @error('phone') is-invalid @enderror"
|
||||||
value="{{ old('phone', $user->phone) }}" required>
|
value="{{ old('phone', $user->phone) }}" required>
|
||||||
@error('phone')
|
@error('phone')
|
||||||
<div class="invalid-feedback">{{ $message }}</div>
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
@enderror
|
@enderror
|
||||||
<small class="text-muted">*Nomor telepon wajib diisi</small>
|
<small class="text-muted">*Nomor telepon wajib diisi</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class="my-4">
|
<hr class="my-4">
|
||||||
|
|
||||||
{{-- Bagian Info Spesifik Role (Tidak Dapat Diubah) --}}
|
{{-- Bagian Info Spesifik Role (Tidak Dapat Diubah) --}}
|
||||||
@if ($user->role == 'siswa')
|
@if ($user->role == 'siswa')
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="nomor_induk" class="form-label">NISN (Nomor Induk Siswa Nasional)</label>
|
<label for="nomor_induk" class="form-label">NISN (Nomor Induk Siswa Nasional)</label>
|
||||||
<input id="nomor_induk" type="text" class="form-control" value="{{ $user->nomor_induk }}" readonly disabled>
|
<input id="nomor_induk" type="text" class="form-control" value="{{ $user->nomor_induk }}" readonly disabled>
|
||||||
<small class="text-muted">NISN tidak dapat diubah.</small>
|
<small class="text-muted">NISN tidak dapat diubah.</small>
|
||||||
|
</div>
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="kelas" class="form-label">Kelas</label>
|
||||||
|
<input id="kelas" type="text" class="form-control" value="{{ $user->kelas }}" readonly disabled>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="col-md-6 mb-3">
|
||||||
<div class="col-md-6 mb-3">
|
<label for="golongan" class="form-label">Golongan</label>
|
||||||
<label for="kelas" class="form-label">Kelas</label>
|
<input id="golongan" type="text" class="form-control" value="{{ $user->golongan }}" readonly disabled>
|
||||||
<input id="kelas" type="text" class="form-control" value="{{ $user->kelas }}" readonly disabled>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6 mb-3">
|
|
||||||
<label for="golongan" class="form-label">Golongan</label>
|
|
||||||
<input id="golongan" type="text" class="form-control" value="{{ $user->golongan }}" readonly disabled>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
@else
|
@else
|
||||||
{{-- Untuk Guru atau Penjaga Perpus --}}
|
{{-- Untuk Guru atau Penjaga Perpus --}}
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="nuptk" class="form-label">NIP / NUPTK</label>
|
<label for="nuptk" class="form-label">NIP / NUPTK</label>
|
||||||
<input id="nuptk" type="text" class="form-control" value="{{ $user->nuptk }}" readonly disabled>
|
<input id="nuptk" type="text" class="form-control" value="{{ $user->nuptk }}" readonly disabled>
|
||||||
<small class="text-muted">ID Kepegawaian tidak dapat diubah.</small>
|
<small class="text-muted">ID Kepegawaian tidak dapat diubah.</small>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -98,7 +98,7 @@ class="form-control @error('email') is-invalid @enderror" value="{{ old('email',
|
||||||
<button type="submit" class="btn btn-primary">{{ __('Simpan') }}</button>
|
<button type="submit" class="btn btn-primary">{{ __('Simpan') }}</button>
|
||||||
|
|
||||||
@if (session('status') === 'profile-updated')
|
@if (session('status') === 'profile-updated')
|
||||||
<span class="text-success fw-bold">{{ __('Tersimpan.') }}</span>
|
<span class="text-success fw-bold">{{ __('Tersimpan.') }}</span>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,15 @@
|
||||||
<span
|
<span
|
||||||
class="badge rounded-pill bg-success-subtle text-success-emphasis">Dikembalikan</span>
|
class="badge rounded-pill bg-success-subtle text-success-emphasis">Dikembalikan</span>
|
||||||
@elseif($isTelat)
|
@elseif($isTelat)
|
||||||
<span class="badge rounded-pill bg-danger text-white">Terlambat</span>
|
{{-- LOGIC BADGE STATUS DI TABEL --}}
|
||||||
|
@if (Auth::user()->role == 'guru')
|
||||||
|
<span
|
||||||
|
class="badge rounded-pill bg-success-subtle text-success-emphasis">Bebas
|
||||||
|
Denda</span>
|
||||||
|
@else
|
||||||
|
<span
|
||||||
|
class="badge rounded-pill bg-danger text-white">Terlambat</span>
|
||||||
|
@endif
|
||||||
@else
|
@else
|
||||||
<span
|
<span
|
||||||
class="badge rounded-pill bg-warning-subtle text-warning-emphasis">Dipinjam</span>
|
class="badge rounded-pill bg-warning-subtle text-warning-emphasis">Dipinjam</span>
|
||||||
|
|
@ -105,6 +113,8 @@ class="badge rounded-pill bg-warning-subtle text-warning-emphasis">Dipinjam</spa
|
||||||
<script>
|
<script>
|
||||||
const riwayatOfflineData = @json($riwayatOffline);
|
const riwayatOfflineData = @json($riwayatOffline);
|
||||||
|
|
||||||
|
const currentUserRole = "{{ Auth::user()->role }}";
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('#riwayatOfflineTable').DataTable({
|
$('#riwayatOfflineTable').DataTable({
|
||||||
responsive: true,
|
responsive: true,
|
||||||
|
|
@ -156,24 +166,47 @@ class="badge rounded-pill bg-warning-subtle text-warning-emphasis">Dipinjam</spa
|
||||||
const buku = transaksiItem.books.find(b => b.id == bukuId);
|
const buku = transaksiItem.books.find(b => b.id == bukuId);
|
||||||
if (!buku) return;
|
if (!buku) return;
|
||||||
|
|
||||||
const dendaHtml = isTelat ? `
|
let dendaHtml = '';
|
||||||
<div class="card border-0 border-start border-4 border-danger bg-danger-subtle mb-3 shadow-sm">
|
|
||||||
<div class="card-body p-3 d-flex align-items-center">
|
|
||||||
<div class="flex-shrink-0 me-3">
|
|
||||||
<i class="bi bi-exclamation-octagon-fill text-danger fs-1"></i>
|
|
||||||
</div>
|
|
||||||
<div class="text-start">
|
|
||||||
<h6 class="fw-bold text-danger mb-1">Terlambat Pengembalian!</h6>
|
|
||||||
<p class="mb-0 small text-danger-emphasis">
|
|
||||||
Anda terlambat <span class="badge bg-danger text-white">${hariTelat} Hari</span>.
|
|
||||||
Denda yang harus dibayar:
|
|
||||||
<span class="fw-bold fs-6 d-block mt-1">Rp ${denda}</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>` : '';
|
|
||||||
|
|
||||||
const keteranganHtml = buku.keterangan ? `
|
if (isTelat) {
|
||||||
|
if (currentUserRole === 'guru') {
|
||||||
|
// JIKA GURU: Tampilkan Label Bebas Denda (Hijau)
|
||||||
|
dendaHtml = `
|
||||||
|
<div class="card border-0 border-start border-4 border-success bg-success-subtle mb-3 shadow-sm">
|
||||||
|
<div class="card-body p-3 d-flex align-items-center">
|
||||||
|
<div class="flex-shrink-0 me-3">
|
||||||
|
<i class="bi bi-check-circle-fill text-success fs-1"></i>
|
||||||
|
</div>
|
||||||
|
<div class="text-start">
|
||||||
|
<h6 class="fw-bold text-success mb-1">Bebas Denda</h6>
|
||||||
|
<p class="mb-0 small text-success-emphasis">
|
||||||
|
Sebagai Guru, Anda dibebaskan dari denda keterlambatan buku.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
} else {
|
||||||
|
// JIKA SISWA: Tampilkan Label Denda (Merah)
|
||||||
|
dendaHtml = `
|
||||||
|
<div class="card border-0 border-start border-4 border-danger bg-danger-subtle mb-3 shadow-sm">
|
||||||
|
<div class="card-body p-3 d-flex align-items-center">
|
||||||
|
<div class="flex-shrink-0 me-3">
|
||||||
|
<i class="bi bi-exclamation-octagon-fill text-danger fs-1"></i>
|
||||||
|
</div>
|
||||||
|
<div class="text-start">
|
||||||
|
<h6 class="fw-bold text-danger mb-1">Terlambat Pengembalian!</h6>
|
||||||
|
<p class="mb-0 small text-danger-emphasis">
|
||||||
|
Anda terlambat <span class="badge bg-danger text-white">${hariTelat} Hari</span>.
|
||||||
|
Denda yang harus dibayar:
|
||||||
|
<span class="fw-bold fs-6 d-block mt-1">Rp ${denda}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const keteranganHtml = buku.keterangan ? `
|
||||||
<div class="card border-0 border-start border-4 border-warning bg-warning-subtle mb-4 shadow-sm">
|
<div class="card border-0 border-start border-4 border-warning bg-warning-subtle mb-4 shadow-sm">
|
||||||
<div class="card-body p-3 d-flex align-items-start">
|
<div class="card-body p-3 d-flex align-items-start">
|
||||||
<div class="flex-shrink-0 me-3">
|
<div class="flex-shrink-0 me-3">
|
||||||
|
|
@ -188,8 +221,8 @@ class="badge rounded-pill bg-warning-subtle text-warning-emphasis">Dipinjam</spa
|
||||||
</div>
|
</div>
|
||||||
</div>` : '';
|
</div>` : '';
|
||||||
|
|
||||||
// RENDER HTML
|
// RENDER HTML
|
||||||
modalBody.innerHTML = `
|
modalBody.innerHTML = `
|
||||||
<div class="text-center mb-4">
|
<div class="text-center mb-4">
|
||||||
<img src="{{ asset('') }}${buku.cover}" class="img-fluid rounded shadow-sm" style="max-width: 140px;">
|
<img src="{{ asset('') }}${buku.cover}" class="img-fluid rounded shadow-sm" style="max-width: 140px;">
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,14 @@
|
||||||
<body data-bs-spy="scroll" data-bs-target="#mainNav" data-bs-offset="56">
|
<body data-bs-spy="scroll" data-bs-target="#mainNav" data-bs-offset="56">
|
||||||
|
|
||||||
@php
|
@php
|
||||||
// Dummy data untuk landing page (Hanya contoh)
|
// Dummy data untuk landing page (Hanya contoh)
|
||||||
$buku_unggulan = \App\Services\DummyDataService::getAllBooks()->take(6);
|
$buku_unggulan = \App\Services\DummyDataService::getAllBooks()->take(6);
|
||||||
$stats = [
|
$stats = [
|
||||||
['label' => 'Koleksi Buku', 'value' => 12500, 'icon' => 'bi-bookshelf'],
|
['label' => 'Koleksi Buku', 'value' => 12500, 'icon' => 'bi-bookshelf'],
|
||||||
['label' => 'Pengguna Aktif', 'value' => 4500, 'icon' => 'bi-person-lines-fill'],
|
['label' => 'Pengguna Aktif', 'value' => 4500, 'icon' => 'bi-person-lines-fill'],
|
||||||
['label' => 'Total Dibaca', 'value' => '900K+', 'icon' => 'bi-hand-thumbs-up-fill'],
|
['label' => 'Total Dibaca', 'value' => '900K+', 'icon' => 'bi-hand-thumbs-up-fill'],
|
||||||
['label' => 'Tahun Berdiri', 'value' => 2018, 'icon' => 'bi-clock-fill'],
|
['label' => 'Tahun Berdiri', 'value' => 2018, 'icon' => 'bi-clock-fill'],
|
||||||
];
|
];
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
{{-- Navbar --}}
|
{{-- Navbar --}}
|
||||||
|
|
@ -61,7 +61,7 @@ class="btn btn-primary dropdown-toggle fw-semibold w-100 d-flex align-items-cent
|
||||||
type="button" data-bs-toggle="dropdown" aria-expanded="false"
|
type="button" data-bs-toggle="dropdown" aria-expanded="false"
|
||||||
style="border-radius: 0.6rem; padding: 0.5rem 1.25rem;">
|
style="border-radius: 0.6rem; padding: 0.5rem 1.25rem;">
|
||||||
<i class="bi bi-person-circle me-2"></i>
|
<i class="bi bi-person-circle me-2"></i>
|
||||||
<span>Masuk / Daftar</span>
|
<span>Masuk</span>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu dropdown-menu-end shadow-sm border-0 mt-2 p-2"
|
<ul class="dropdown-menu dropdown-menu-end shadow-sm border-0 mt-2 p-2"
|
||||||
style="border-radius: 12px; min-width: 250px;">
|
style="border-radius: 12px; min-width: 250px;">
|
||||||
|
|
@ -85,8 +85,8 @@ class="btn btn-primary dropdown-toggle fw-semibold w-100 d-flex align-items-cent
|
||||||
<i class="bi bi-person-workspace text-success" style="font-size: 1.25rem;"></i>
|
<i class="bi bi-person-workspace text-success" style="font-size: 1.25rem;"></i>
|
||||||
<div>
|
<div>
|
||||||
<div class="fw-semibold">Guru</div>
|
<div class="fw-semibold">Guru</div>
|
||||||
<small class="text-muted d-block" style="font-size: 0.75rem;">Kelola
|
<small class="text-muted d-block" style="font-size: 0.75rem;">Pinjam, Baca &
|
||||||
Buku</small>
|
Pantau Laporan</small>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -149,24 +149,24 @@ class="img-fluid" style="max-width: 100%; height: auto;">
|
||||||
<h2 class="text-center fw-bold mb-5">Koleksi Unggulan Terbaru</h2>
|
<h2 class="text-center fw-bold mb-5">Koleksi Unggulan Terbaru</h2>
|
||||||
<div class="row g-4 mb-4 justify-content-center">
|
<div class="row g-4 mb-4 justify-content-center">
|
||||||
@foreach ($buku_unggulan as $buku)
|
@foreach ($buku_unggulan as $buku)
|
||||||
<div class="col-6 col-md-4 col-lg-2">
|
<div class="col-6 col-md-4 col-lg-2">
|
||||||
<div class="card h-100 border-0 shadow-sm">
|
<div class="card h-100 border-0 shadow-sm">
|
||||||
<img src="{{ asset($buku['cover']) }}" class="card-img-top"
|
<img src="{{ asset($buku['cover']) }}" class="card-img-top"
|
||||||
alt="Cover {{ $buku['judul'] }}">
|
alt="Cover {{ $buku['judul'] }}">
|
||||||
<div class="card-body p-3">
|
<div class="card-body p-3">
|
||||||
<span
|
<span class="badge bg-primary-soft text-primary small mb-2">{{ $buku['kategori']
|
||||||
class="badge bg-primary-soft text-primary small mb-2">{{ $buku['kategori'] }}</span>
|
}}</span>
|
||||||
<h6 class="card-title fw-bold mb-1">{{ $buku['judul'] }}</h6>
|
<h6 class="card-title fw-bold mb-1">{{ $buku['judul'] }}</h6>
|
||||||
<p class="card-text small text-muted mb-1">{{ $buku['penulis'] }}</p>
|
<p class="card-text small text-muted mb-1">{{ $buku['penulis'] }}</p>
|
||||||
<div class="small text-warning">
|
<div class="small text-warning">
|
||||||
<i class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i><i
|
<i class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i><i
|
||||||
class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i><i
|
class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i><i
|
||||||
class="bi bi-star-half"></i>
|
class="bi bi-star-half"></i>
|
||||||
(4.5)
|
(4.5)
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -262,9 +262,9 @@ class="bi bi-star-half"></i>
|
||||||
|
|
||||||
{{-- Bagian Logo (Kolom Kanan) --}}
|
{{-- Bagian Logo (Kolom Kanan) --}}
|
||||||
<div class="col-lg-6 order-lg-2 text-center">
|
<div class="col-lg-6 order-lg-2 text-center">
|
||||||
<img src="{{ asset('images/assets/logo-smp.png') }}" alt="Logo SMPN 1 Bagor"
|
<img src="{{ asset('images/assets/logo-smp.png') }}" alt="Logo SMPN 1 Bagor" class="img-fluid"
|
||||||
class="img-fluid" style="max-width: 250px; height: auto;">
|
style="max-width: 250px; height: auto;">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Bagian Teks (Kolom Kiri) --}}
|
{{-- Bagian Teks (Kolom Kiri) --}}
|
||||||
<div class="col-lg-6 order-lg-1">
|
<div class="col-lg-6 order-lg-1">
|
||||||
|
|
@ -301,13 +301,13 @@ class="img-fluid" style="max-width: 250px; height: auto;">
|
||||||
<h2 class="text-center fw-bold mb-5 text-dark">DIGIPUS.GO Dalam Angka</h2>
|
<h2 class="text-center fw-bold mb-5 text-dark">DIGIPUS.GO Dalam Angka</h2>
|
||||||
<div class="row g-4 text-center">
|
<div class="row g-4 text-center">
|
||||||
@foreach ($stats as $stat)
|
@foreach ($stats as $stat)
|
||||||
<div class="col-sm-6 col-md-3">
|
<div class="col-sm-6 col-md-3">
|
||||||
<div class="p-4 bg-white shadow-sm h-100 landing-stat-card" style="border-radius: 1rem;">
|
<div class="p-4 bg-white shadow-sm h-100 landing-stat-card" style="border-radius: 1rem;">
|
||||||
<i class="bi {{ $stat['icon'] }} display-5 text-primary mb-3"></i>
|
<i class="bi {{ $stat['icon'] }} display-5 text-primary mb-3"></i>
|
||||||
<h2 class="fw-bold text-dark mb-1">{{ $stat['value'] }}</h2>
|
<h2 class="fw-bold text-dark mb-1">{{ $stat['value'] }}</h2>
|
||||||
<p class="text-muted fw-semibold mb-0">{{ $stat['label'] }}</p>
|
<p class="text-muted fw-semibold mb-0">{{ $stat['label'] }}</p>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -358,8 +358,8 @@ class="img-fluid" style="max-width: 250px; height: auto;">
|
||||||
</li>
|
</li>
|
||||||
<li class="mb-2"><a href="#fitur" class="text-decoration-none text-white-50">Fitur</a>
|
<li class="mb-2"><a href="#fitur" class="text-decoration-none text-white-50">Fitur</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="mb-2"><a href="#statistik"
|
<li class="mb-2"><a href="#statistik" class="text-decoration-none text-white-50">Statistik</a>
|
||||||
class="text-decoration-none text-white-50">Statistik</a></li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -378,10 +378,10 @@ class="text-decoration-none text-white-50">Statistik</a></li>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<h6 class="text-white fw-bold mb-3">Hubungi Kami</h6>
|
<h6 class="text-white fw-bold mb-3">Hubungi Kami</h6>
|
||||||
<ul class="list-unstyled small">
|
<ul class="list-unstyled small">
|
||||||
<li class="mb-2 text-white-50"><i class="bi bi-envelope-fill me-2"></i> admin@digipus.go.id
|
<li class="mb-2 text-white-50"><i class="bi bi-envelope-fill me-2"></i> smpn1bagor@yahoo.co.id
|
||||||
</li>
|
</li>
|
||||||
<li class="mb-2 text-white-50"><i class="bi bi-telephone-fill me-2"></i> (021) 1234 5678</li>
|
<li class="mb-2 text-white-50"><i class="bi bi-telephone-fill me-2"></i> (+62) 856-0642-8357</li>
|
||||||
<li class="mb-2 text-white-50"><i class="bi bi-geo-alt-fill me-2"></i> [Alamat Pustaka Anda]
|
<li class="mb-2 text-white-50"><i class="bi bi-geo-alt-fill me-2"></i> Banaran Kulon, Kec. Bagor, Kabupaten Nganjuk, Jawa Timur 64461
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -408,4 +408,4 @@ class="text-decoration-none text-white-50">Statistik</a></li>
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -12,10 +12,10 @@
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
Route::middleware('guest')->group(function () {
|
Route::middleware('guest')->group(function () {
|
||||||
Route::get('register', [RegisteredUserController::class, 'create'])
|
// Route::get('register', [RegisteredUserController::class, 'create'])
|
||||||
->name('register');
|
// ->name('register');
|
||||||
|
|
||||||
Route::post('register', [RegisteredUserController::class, 'store']);
|
// Route::post('register', [RegisteredUserController::class, 'store']);
|
||||||
|
|
||||||
Route::get('login', [AuthenticatedSessionController::class, 'create'])
|
Route::get('login', [AuthenticatedSessionController::class, 'create'])
|
||||||
->name('login');
|
->name('login');
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
// Admin Controllers
|
// Admin Controllers
|
||||||
use App\Http\Controllers\Admin\DashboardController as AdminDashboardController;
|
use App\Http\Controllers\Admin\DashboardController as AdminDashboardController;
|
||||||
use App\Http\Controllers\Admin\BookController as AdminBookController;
|
use App\Http\Controllers\Admin\BookController as AdminBookController;
|
||||||
|
use App\Http\Controllers\Admin\MasterIndukController;
|
||||||
use App\Http\Controllers\Admin\UserController as AdminUserController;
|
use App\Http\Controllers\Admin\UserController as AdminUserController;
|
||||||
use App\Http\Controllers\Admin\PengumumanController as AdminPengumumanController;
|
use App\Http\Controllers\Admin\PengumumanController as AdminPengumumanController;
|
||||||
use App\Http\Controllers\Admin\MasterIndukController as AdminMasterIndukController;
|
use App\Http\Controllers\Admin\MasterIndukController as AdminMasterIndukController;
|
||||||
|
|
@ -86,14 +87,12 @@
|
||||||
Route::get('/buku/tambah', [AdminBookController::class, 'create'])->name('buku.create');
|
Route::get('/buku/tambah', [AdminBookController::class, 'create'])->name('buku.create');
|
||||||
Route::post('/buku', [AdminBookController::class, 'store'])->name('buku.store');
|
Route::post('/buku', [AdminBookController::class, 'store'])->name('buku.store');
|
||||||
Route::get('/buku/{id}/edit', [AdminBookController::class, 'edit'])->name('buku.edit');
|
Route::get('/buku/{id}/edit', [AdminBookController::class, 'edit'])->name('buku.edit');
|
||||||
Route::put('/buku/{id}', [AdminBookController::class, 'update'])->name('buku.update');
|
|
||||||
Route::delete('/buku/{id}', [AdminBookController::class, 'destroy'])->name('buku.destroy');
|
|
||||||
|
|
||||||
Route::get('/pengguna', [AdminUserController::class, 'index'])->name('pengguna.index');
|
Route::get('/pengguna', [AdminUserController::class, 'index'])->name('pengguna.index');
|
||||||
Route::get('/pengguna/tambah', [AdminUserController::class, 'create'])->name('pengguna.create');
|
Route::get('/pengguna/tambah', [AdminUserController::class, 'create'])->name('pengguna.create');
|
||||||
Route::post('/pengguna', [AdminUserController::class, 'store'])->name('pengguna.store');
|
Route::post('/pengguna', [AdminUserController::class, 'store'])->name('pengguna.store');
|
||||||
Route::get('/pengguna/{id}/edit', [AdminUserController::class, 'edit'])->name('pengguna.edit');
|
Route::get('/pengguna/{id}/edit', [AdminUserController::class, 'edit'])->name('pengguna.edit');
|
||||||
Route::put('/pengguna/{id}', [AdminUserController::class, 'update'])->name('pengguna.update');
|
Route::patch('/pengguna/{id}', [AdminUserController::class, 'update'])->name('pengguna.update');
|
||||||
Route::delete('/pengguna/{id}', [AdminUserController::class, 'destroy'])->name('pengguna.destroy');
|
Route::delete('/pengguna/{id}', [AdminUserController::class, 'destroy'])->name('pengguna.destroy');
|
||||||
|
|
||||||
Route::get('/pengumuman', [AdminPengumumanController::class, 'index'])->name('pengumuman.index');
|
Route::get('/pengumuman', [AdminPengumumanController::class, 'index'])->name('pengumuman.index');
|
||||||
|
|
@ -103,7 +102,11 @@
|
||||||
Route::put('/pengumuman/{id}', [AdminPengumumanController::class, 'update'])->name('pengumuman.update');
|
Route::put('/pengumuman/{id}', [AdminPengumumanController::class, 'update'])->name('pengumuman.update');
|
||||||
Route::delete('/pengumuman/{id}', [AdminPengumumanController::class, 'destroy'])->name('pengumuman.destroy');
|
Route::delete('/pengumuman/{id}', [AdminPengumumanController::class, 'destroy'])->name('pengumuman.destroy');
|
||||||
|
|
||||||
Route::get('/rekomendasi', [AdminRekomendasiController::class, 'index'])->name('rekomendasi.index');
|
Route::get('/rekomendasi', [
|
||||||
|
AdminRekomendasiController
|
||||||
|
::class,
|
||||||
|
'index'
|
||||||
|
])->name('rekomendasi.index');
|
||||||
Route::get('/rekomendasi/tambah', [AdminRekomendasiController::class, 'create'])->name('rekomendasi.create');
|
Route::get('/rekomendasi/tambah', [AdminRekomendasiController::class, 'create'])->name('rekomendasi.create');
|
||||||
Route::post('/rekomendasi', [AdminRekomendasiController::class, 'store'])->name('rekomendasi.store');
|
Route::post('/rekomendasi', [AdminRekomendasiController::class, 'store'])->name('rekomendasi.store');
|
||||||
Route::get('/rekomendasi/{id}/edit', [AdminRekomendasiController::class, 'edit'])->name('rekomendasi.edit');
|
Route::get('/rekomendasi/{id}/edit', [AdminRekomendasiController::class, 'edit'])->name('rekomendasi.edit');
|
||||||
|
|
@ -112,21 +115,23 @@
|
||||||
|
|
||||||
Route::get('/peminjaman', [AdminPeminjamanController::class, 'index'])->name('peminjaman.index');
|
Route::get('/peminjaman', [AdminPeminjamanController::class, 'index'])->name('peminjaman.index');
|
||||||
Route::get('/peminjaman/tambah', [AdminPeminjamanController::class, 'create'])->name('peminjaman.create');
|
Route::get('/peminjaman/tambah', [AdminPeminjamanController::class, 'create'])->name('peminjaman.create');
|
||||||
Route::post('/peminjaman', [AdminPeminjamanController::class, 'store'])->name('peminjaman.store');
|
|
||||||
Route::post('/peminjaman/kembali', [AdminPeminjamanController::class, 'kembalikan'])->name('peminjaman.kembali');
|
|
||||||
|
|
||||||
Route::get('/denda', [AdminPeminjamanController::class, 'dendaIndex'])->name('denda.index');
|
Route::get('/denda', [AdminPeminjamanController::class, 'dendaIndex'])->name('denda.index');
|
||||||
Route::post('/denda/sanksi', [AdminPeminjamanController::class, 'berikanSanksi'])->name('denda.sanksi');
|
Route::post('/denda/sanksi', [AdminPeminjamanController::class, 'berikanSanksi'])->name('denda.sanksi');
|
||||||
|
|
||||||
// Master Induk / Whitelist
|
Route::post('/master-induk', [MasterIndukController::class, 'store'])->name('master-induk.store');
|
||||||
Route::post('/master-induk', [AdminMasterIndukController::class, 'store'])->name('master-induk.store');
|
Route::delete('/master-induk/{id}', [MasterIndukController::class, 'destroy'])->name('master-induk.destroy');
|
||||||
Route::delete('/master-induk/{id}', [AdminMasterIndukController::class, 'destroy'])->name('master-induk.destroy');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- RUTE LOGIN KHUSUS ADMIN ---
|
// --- RUTE LOGIN KHUSUS ADMIN ---
|
||||||
Route::middleware('guest')->group(function() {
|
Route::middleware('guest')->group(function () {
|
||||||
Route::get('/admin/login', [AdminLoginController::class, 'create'])->name('admin.login');
|
Route::get('/admin/login', [AdminLoginController::class, 'create'])->name('admin.login');
|
||||||
Route::post('/admin/login', [AdminLoginController::class, 'store'])->name('admin.login.store');
|
Route::post('/admin/login', [AdminLoginController::class, 'store'])->name('admin.login.store');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -- RUTE RESET PASSWORD --
|
||||||
|
Route::get('/reset-password', function () {
|
||||||
|
return view('auth.reset-password-request');
|
||||||
|
})->name('reset.password-request');
|
||||||
|
|
||||||
require __DIR__ . '/auth.php';
|
require __DIR__ . '/auth.php';
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue