feat: Implement Master Induk (whitelist) for user registration and add return receipt email functionality.
This commit is contained in:
parent
4c6a2f9a57
commit
bf12a38ccb
|
|
@ -9,6 +9,9 @@
|
|||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Mail\ReturnReceipt;
|
||||
|
||||
class AdminPeminjamanController extends Controller
|
||||
{
|
||||
|
|
@ -301,6 +304,7 @@ public function kembalikan(Request $request)
|
|||
'returns.*.fine_damage' => 'required|integer',
|
||||
'returns.*.fine_overdue' => 'required|integer',
|
||||
'returns.*.notes' => 'nullable|string',
|
||||
'send_email' => 'nullable|boolean',
|
||||
]);
|
||||
|
||||
\DB::beginTransaction();
|
||||
|
|
@ -331,6 +335,36 @@ public function kembalikan(Request $request)
|
|||
|
||||
\DB::commit();
|
||||
|
||||
// Send email if requested
|
||||
if ($request->send_email && $request->user_id) {
|
||||
$user = User::findOrFail($request->user_id);
|
||||
$totalDenda = 0;
|
||||
$emailReturns = [];
|
||||
|
||||
foreach ($validated['returns'] as $item) {
|
||||
$book = Book::find($item['book_id']);
|
||||
$emailReturns[] = [
|
||||
'judul' => $book->judul ?? 'Buku Unknown',
|
||||
'condition' => $item['condition'],
|
||||
'fine_damage' => $item['fine_damage'],
|
||||
'fine_overdue' => $item['fine_overdue'],
|
||||
];
|
||||
$totalDenda += ($item['fine_damage'] + $item['fine_overdue']);
|
||||
}
|
||||
|
||||
try {
|
||||
Mail::to($user->email)->send(new ReturnReceipt($user, $emailReturns, $totalDenda));
|
||||
} catch (\Exception $e) {
|
||||
// Log the error but don't fail the return process
|
||||
\Log::error('Gagal mengirim email pengembalian: ' . $e->getMessage());
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Buku berhasil dikembalikan, namun gagal mengirim email.',
|
||||
'email_error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(['status' => 'success', 'message' => 'Buku berhasil dikembalikan.']);
|
||||
} catch (\Exception $e) {
|
||||
\DB::rollBack();
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ public function index()
|
|||
$query->where('role', request('role'));
|
||||
}
|
||||
|
||||
$users = $query->paginate(10)->appends(request()->query());
|
||||
$users = $query->paginate(10, ['*'], 'page')->appends(request()->query());
|
||||
|
||||
$whitelists = MasterInduk::orderBy('created_at', 'desc')->get();
|
||||
$whitelists = MasterInduk::orderBy('created_at', 'desc')->paginate(10, ['*'], 'whitelist_page')->appends(request()->query());
|
||||
|
||||
return view('admin.pengguna.index', [
|
||||
'pageTitle' => 'Daftar Pengguna',
|
||||
|
|
@ -29,9 +29,17 @@ public function index()
|
|||
]);
|
||||
}
|
||||
|
||||
public function create()
|
||||
public function create(Request $request)
|
||||
{
|
||||
return view('admin.pengguna.create', ['pageTitle' => 'Tambah Pengguna Baru']);
|
||||
$prefilledData = null;
|
||||
if ($request->has('nomor_induk')) {
|
||||
$prefilledData = MasterInduk::where('nomor_induk', $request->nomor_induk)->first();
|
||||
}
|
||||
|
||||
return view('admin.pengguna.create', [
|
||||
'pageTitle' => 'Tambah Pengguna Baru',
|
||||
'prefilledData' => $prefilledData
|
||||
]);
|
||||
}
|
||||
|
||||
public function edit($id)
|
||||
|
|
@ -48,7 +56,7 @@ public function store(Request $request)
|
|||
$validated = $request->validate([
|
||||
'nama_lengkap' => 'required|string|max:255',
|
||||
'email' => 'required|email|unique:users,email',
|
||||
'nomor_induk' => 'nullable|string|max:50',
|
||||
'nomor_induk' => 'required|string|max:50|unique:users,nomor_induk',
|
||||
'phone' => 'nullable|string|max:20',
|
||||
'role' => 'required|in:siswa,guru,penjaga perpus',
|
||||
'kelas' => 'nullable|string|max:50',
|
||||
|
|
@ -56,6 +64,17 @@ public function store(Request $request)
|
|||
'password' => 'required|string|min:8|confirmed',
|
||||
]);
|
||||
|
||||
// Validasi Whitelist untuk Siswa & Guru
|
||||
if (in_array($validated['role'], ['siswa', 'guru'])) {
|
||||
$isWhitelisted = MasterInduk::where('nomor_induk', $validated['nomor_induk'])
|
||||
->where('role', $validated['role'])
|
||||
->exists();
|
||||
|
||||
if (!$isWhitelisted) {
|
||||
return back()->withErrors(['nomor_induk' => 'Nomor Induk ini tidak terdaftar dalam Data Induk (Whitelist) atau Role tidak sesuai.'])->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
$validated['password'] = Hash::make($validated['password']);
|
||||
$validated['name'] = $validated['nama_lengkap']; // Set name field for compatibility
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public function index(Request $request): \Illuminate\View\View|\Illuminate\Http\
|
|||
$viewData['bukuOffline'] = $loans->map(fn($loan) => [
|
||||
'judul' => $loan->book->judul,
|
||||
'penulis' => $loan->book->penulis,
|
||||
'sisa_hari' => (int) now()->diffInDays(Carbon::parse($loan->due_at), false),
|
||||
'sisa_hari' => (int) now()->startOfDay()->diffInDays(Carbon::parse($loan->due_at)->startOfDay(), false),
|
||||
'cover' => $loan->book->cover,
|
||||
]);
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ public function index(Request $request): \Illuminate\View\View|\Illuminate\Http\
|
|||
$viewData['bukuOffline'] = $loans->map(fn($loan) => [
|
||||
'judul' => $loan->book->judul,
|
||||
'penulis' => $loan->book->penulis,
|
||||
'sisa_hari' => (int) now()->diffInDays(Carbon::parse($loan->due_at), false),
|
||||
'sisa_hari' => (int) now()->startOfDay()->diffInDays(Carbon::parse($loan->due_at)->startOfDay(), false),
|
||||
'cover' => $loan->book->cover,
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ReturnReceipt extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public $user;
|
||||
public $returns;
|
||||
public $totalDenda;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct($user, $returns, $totalDenda)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->returns = $returns;
|
||||
$this->totalDenda = $totalDenda;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
subject: 'Bukti Pengembalian Buku - ' . config('app.name'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
return new Content(
|
||||
view: 'emails.return_receipt',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
class Book extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'judul', 'penulis', 'cover', 'kode_buku',
|
||||
'judul', 'penulis', 'cover', 'kode_buku', 'stok',
|
||||
'category_id', 'tahun', 'status', 'is_new', 'tipe_akses', 'file_pdf', 'is_arsip'
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
use App\Models\Loan;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
|
@ -28,6 +29,8 @@ public function boot(): void
|
|||
URL::forceScheme('https');
|
||||
}
|
||||
|
||||
Paginator::useBootstrapFive();
|
||||
|
||||
// View Composer untuk semua view (*)
|
||||
View::composer('*', function ($view) {
|
||||
if (Auth::check()) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\MasterInduk>
|
||||
*/
|
||||
class MasterIndukFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'nomor_induk' => fake()->unique()->numerify('##########'),
|
||||
'role' => 'siswa',
|
||||
'nama_pemilik' => fake()->name(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -96,6 +96,7 @@ public function run()
|
|||
AnnouncementSeeder::class,
|
||||
RecommendationSeeder::class,
|
||||
LoanSeeder::class,
|
||||
UserSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,5 +49,30 @@ public function run(): void
|
|||
'role' => 'penjaga perpus',
|
||||
]
|
||||
);
|
||||
|
||||
// Generate 95 additional users to reach around 100 total
|
||||
$additionalCount = 95;
|
||||
for ($i = 0; $i < $additionalCount; $i++) {
|
||||
$nomorInduk = fake()->unique()->numerify('##########');
|
||||
$name = fake()->name();
|
||||
|
||||
\App\Models\MasterInduk::create([
|
||||
'nomor_induk' => $nomorInduk,
|
||||
'role' => 'siswa',
|
||||
'nama_pemilik' => $name,
|
||||
]);
|
||||
|
||||
User::create([
|
||||
'name' => $name,
|
||||
'nama_lengkap' => $name,
|
||||
'email' => fake()->unique()->safeEmail(),
|
||||
'password' => Hash::make('password'),
|
||||
'nomor_induk' => $nomorInduk,
|
||||
'role' => 'siswa',
|
||||
'phone' => fake()->phoneNumber(),
|
||||
'kelas' => fake()->randomElement(['X RPL', 'XI RPL', 'XII RPL', 'X TKJ', 'XI TKJ', 'XII TKJ']),
|
||||
'golongan' => fake()->randomElement(['A', 'B', 'C']),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,31 +376,29 @@ function hitungTotalDenda(modal) {
|
|||
// Loading Kirim Email flow
|
||||
if (isEmailChecked) {
|
||||
modernSwal.fire({
|
||||
title: 'Mengirim Email...',
|
||||
title: 'Memproses...',
|
||||
html: `Mengirim nota ke: <b>${userEmail}</b>`,
|
||||
timer: 2000,
|
||||
timerProgressBar: true,
|
||||
didOpen: () => Swal.showLoading()
|
||||
}).then(() => {
|
||||
finishTransaction(returnsData, userId, waLink);
|
||||
didOpen: () => Swal.showLoading(),
|
||||
allowOutsideClick: false
|
||||
});
|
||||
} else {
|
||||
finishTransaction(returnsData, userId, waLink);
|
||||
}
|
||||
|
||||
finishTransaction(returnsData, userId, waLink, isEmailChecked);
|
||||
});
|
||||
} else {
|
||||
modalInstance.show();
|
||||
}
|
||||
});
|
||||
|
||||
function finishTransaction(returnsData, userId, waLink) {
|
||||
function finishTransaction(returnsData, userId, waLink, isEmailChecked) {
|
||||
$.ajax({
|
||||
url: "{{ route('admin.peminjaman.kembali') }}",
|
||||
method: 'POST',
|
||||
data: {
|
||||
_token: '{{ csrf_token() }}',
|
||||
user_id: userId,
|
||||
returns: returnsData
|
||||
returns: returnsData,
|
||||
send_email: isEmailChecked ? 1 : 0
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.status === 'success') {
|
||||
|
|
@ -408,11 +406,19 @@ function finishTransaction(returnsData, userId, waLink) {
|
|||
window.open(waLink, '_blank');
|
||||
}
|
||||
|
||||
Toast.fire({
|
||||
icon: 'success',
|
||||
title: 'Berhasil',
|
||||
text: 'Buku berhasil dikembalikan.'
|
||||
});
|
||||
if (response.email_error) {
|
||||
Toast.fire({
|
||||
icon: 'warning',
|
||||
title: 'Berhasil (Email Gagal)',
|
||||
text: response.message
|
||||
});
|
||||
} else {
|
||||
Toast.fire({
|
||||
icon: 'success',
|
||||
title: 'Berhasil',
|
||||
text: 'Buku berhasil dikembalikan.'
|
||||
});
|
||||
}
|
||||
setTimeout(() => location.reload(), 1500);
|
||||
} else {
|
||||
modernSwal.fire('Gagal', response.message, 'error');
|
||||
|
|
|
|||
|
|
@ -7,6 +7,15 @@
|
|||
<h3 class="my-0 fw-bold">Formulir Tambah Pengguna</h3>
|
||||
</div>
|
||||
|
||||
@if($prefilledData)
|
||||
<div class="alert alert-success border-0 shadow-sm d-flex align-items-center mb-4" role="alert">
|
||||
<i class="bi bi-person-check-fill fs-4 me-3"></i>
|
||||
<div>
|
||||
Mendaftarkan user dari Data Induk: <strong>{{ $prefilledData->nama_pemilik }}</strong> ({{ $prefilledData->nomor_induk }})
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-10">
|
||||
<div class="card border-0 shadow-sm">
|
||||
|
|
@ -16,6 +25,14 @@
|
|||
|
||||
<div class="mb-3">
|
||||
<label for="role" class="form-label">Role <span class="text-danger">*</span></label>
|
||||
@if($prefilledData)
|
||||
<input type="hidden" name="role" value="{{ $prefilledData->role }}">
|
||||
<select class="form-select" id="role" disabled>
|
||||
<option value="siswa" {{ $prefilledData->role == 'siswa' ? 'selected' : '' }}>Siswa</option>
|
||||
<option value="guru" {{ $prefilledData->role == 'guru' ? 'selected' : '' }}>Guru</option>
|
||||
<option value="penjaga perpus" {{ $prefilledData->role == 'penjaga perpus' ? 'selected' : '' }}>Penjaga Perpustakaan</option>
|
||||
</select>
|
||||
@else
|
||||
<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>
|
||||
|
|
@ -27,22 +44,27 @@
|
|||
@error('role')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Bagian Form Dinamis --}}
|
||||
<div id="dynamic-form" class="d-none">
|
||||
<div id="dynamic-form" class="{{ $prefilledData ? '' : 'd-none' }}">
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="nama_lengkap" class="form-label">Nama Lengkap</label>
|
||||
<input type="text" class="form-control @error('nama_lengkap') is-invalid @enderror"
|
||||
id="nama_lengkap" name="nama_lengkap" value="{{ old('nama_lengkap') }}" required>
|
||||
id="nama_lengkap" name="nama_lengkap" value="{{ old('nama_lengkap', $prefilledData->nama_pemilik ?? '') }}" required
|
||||
{{ $prefilledData ? 'readonly' : '' }}>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="nomor_induk" class="form-label" id="label_nomor_induk">NISN / NIP</label>
|
||||
@if($prefilledData)
|
||||
<input type="hidden" name="nomor_induk" value="{{ $prefilledData->nomor_induk }}">
|
||||
@endif
|
||||
<input type="number" class="form-control @error('nomor_induk') is-invalid @enderror"
|
||||
id="nomor_induk" name="nomor_induk" value="{{ old('nomor_induk') }}"
|
||||
placeholder="Masukkan Nomor Induk">
|
||||
id="nomor_induk" name="{{ $prefilledData ? '' : 'nomor_induk' }}" value="{{ old('nomor_induk', $prefilledData->nomor_induk ?? '') }}"
|
||||
placeholder="Masukkan Nomor Induk" {{ $prefilledData ? 'readonly' : '' }}>
|
||||
@error('nomor_induk')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
|
|
@ -64,7 +86,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" id="field_siswa_only" style="display: none;">
|
||||
<div class="row" id="field_siswa_only" style="{{ ($prefilledData && $prefilledData->role == 'siswa') || old('role') == 'siswa' ? 'display: flex;' : 'display: none;' }}">
|
||||
<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"
|
||||
|
|
@ -122,7 +144,10 @@ class="form-control @error('password') is-invalid @enderror" id="password"
|
|||
@push('scripts')
|
||||
<script>
|
||||
function toggleFields() {
|
||||
const role = document.getElementById('role').value;
|
||||
const roleSelect = document.getElementById('role');
|
||||
if (!roleSelect) return;
|
||||
|
||||
const role = roleSelect.value;
|
||||
const dynamicForm = document.getElementById('dynamic-form');
|
||||
const labelInduk = document.getElementById('label_nomor_induk');
|
||||
const inputInduk = document.getElementById('nomor_induk');
|
||||
|
|
|
|||
|
|
@ -6,9 +6,100 @@
|
|||
<h1 class="h3 text-gray-800">{{ $pageTitle ?? 'Manajemen Pengguna' }}</h1>
|
||||
</div>
|
||||
|
||||
{{-- BAGIAN DATA INDUK (WHITELIST) --}}
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<div>
|
||||
<h4 class="fw-bold text-success mb-1"><i class="bi bi-database-lock me-2"></i>1. Data Induk (Whitelist)
|
||||
</h4>
|
||||
<p class="text-muted mb-0">Daftar NIP/NISN/NIK yang <b>diizinkan</b> untuk mendaftar.</p>
|
||||
</div>
|
||||
<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
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="card shadow mb-4 border-left-success">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-bordered align-middle mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>NIP / NISN</th>
|
||||
<th>Nama Pemilik</th>
|
||||
<th class="text-center">Role</th>
|
||||
<th class="text-center">Status Akun</th>
|
||||
<th class="text-center">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($whitelists as $index => $item)
|
||||
<tr>
|
||||
<td>{{ $whitelists->firstItem() + $index }}</td>
|
||||
<td class="fw-bold font-monospace">{{ $item->nomor_induk }}</td>
|
||||
<td>{{ $item->nama_pemilik }}</td>
|
||||
<td class="text-center">
|
||||
@if($item->role == 'guru')
|
||||
<span class="badge bg-info text-dark">Guru</span>
|
||||
@elseif($item->role == 'siswa')
|
||||
<span class="badge bg-primary">Siswa</span>
|
||||
@else
|
||||
<span class="badge bg-secondary">Petugas</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-center">
|
||||
@php
|
||||
$isRegistered = \App\Models\User::where('nomor_induk', $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">
|
||||
<div class="d-flex justify-content-center gap-1">
|
||||
@if(!$isRegistered)
|
||||
<a href="{{ route('admin.pengguna.create', ['nomor_induk' => $item->nomor_induk]) }}"
|
||||
class="btn btn-sm btn-primary" title="Daftarkan Akun">
|
||||
<i class="bi bi-person-plus-fill me-1"></i>Daftarkan
|
||||
</a>
|
||||
@endif
|
||||
<form action="{{ route('admin.master-induk.destroy', $item->id) }}" method="POST"
|
||||
class="form-delete-whitelist" data-induk="{{ $item->nomor_induk }}">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="button" class="btn btn-sm btn-outline-danger btn-hapus-whitelist" title="Hapus Data Induk">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="text-center py-4 text-muted">Belum ada data whitelist. Silakan
|
||||
tambah data.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="mt-3">
|
||||
{{ $whitelists->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-5 border-4">
|
||||
|
||||
<h4 class="fw-bold text-primary mb-3"><i class="bi bi-people-fill me-2"></i>2. Daftar Pengguna Aktif</h4>
|
||||
|
||||
<div class="card shadow mb-5">
|
||||
<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">List Pengguna Terdaftar</h6>
|
||||
|
||||
<div class="d-flex align-items-center">
|
||||
<form action="{{ route('admin.pengguna.index') }}" method="GET" class="me-2 mb-0">
|
||||
|
|
@ -22,7 +113,7 @@
|
|||
</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
|
||||
<i class="bi bi-plus-circle-fill me-1"></i>Tambah Manual
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -48,7 +139,7 @@
|
|||
<td>
|
||||
<div>{{ $user->email }}</div>
|
||||
<div class="small text-muted"><i class="bi bi-telephone me-1"></i>{{ $user->phone ??
|
||||
'-' }}</div>
|
||||
'-' }}</div>
|
||||
</td>
|
||||
<td>
|
||||
@if($user->role == 'guru')
|
||||
|
|
@ -106,86 +197,6 @@ class="form-delete-user" data-nama="{{ $user->name }}">
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-5 border-4">
|
||||
|
||||
{{-- BAGIAN DATA INDUK (WHITELIST) --}}
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<div>
|
||||
<h4 class="fw-bold text-success mb-1"><i class="bi bi-database-lock me-2"></i>Data Induk (Whitelist)
|
||||
</h4>
|
||||
<p class="text-muted mb-0">Daftar NIP/NISN/NIK yang <b>diizinkan</b> untuk mendaftar.</p>
|
||||
</div>
|
||||
<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
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="card shadow mb-4 border-left-success">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-bordered align-middle mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>NIP / NISN</th>
|
||||
<th>Nama Pemilik</th>
|
||||
<th class="text-center">Role</th>
|
||||
<th class="text-center">Status Akun</th>
|
||||
<th class="text-center">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($whitelists as $index => $item)
|
||||
<tr>
|
||||
<td>{{ $index + 1 }}</td>
|
||||
<td class="fw-bold font-monospace">{{ $item->nomor_induk }}</td>
|
||||
<td>{{ $item->nama_pemilik }}</td>
|
||||
<td class="text-center">
|
||||
@if($item->role == 'guru')
|
||||
<span class="badge bg-info text-dark">Guru</span>
|
||||
@elseif($item->role == 'siswa')
|
||||
<span class="badge bg-primary">Siswa</span>
|
||||
@else
|
||||
<span class="badge bg-secondary">Petugas</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-center">
|
||||
@php
|
||||
$isRegistered = \App\Models\User::where('nomor_induk', $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">
|
||||
<div class="d-flex justify-content-center">
|
||||
<form action="{{ route('admin.master-induk.destroy', $item->id) }}" method="POST"
|
||||
class="form-delete-whitelist" data-induk="{{ $item->nomor_induk }}">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="button" class="btn btn-sm btn-outline-danger btn-hapus-whitelist" title="Hapus Data Induk">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="text-center py-4 text-muted">Belum ada data whitelist. Silakan
|
||||
tambah data.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- MODAL TAMBAH DATA INDUK --}}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bukti Pengembalian Buku</title>
|
||||
<style>
|
||||
body { font-family: sans-serif; line-height: 1.6; color: #333; }
|
||||
.container { width: 100%; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #eee; border-radius: 8px; }
|
||||
.header { text-align: center; margin-bottom: 20px; border-bottom: 2px solid #0d6efd; padding-bottom: 10px; }
|
||||
.header h2 { color: #0d6efd; margin: 0; }
|
||||
.content { margin-bottom: 20px; }
|
||||
.item-list { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
|
||||
.item-list th, .item-list td { padding: 10px; border: 1px solid #ddd; text-align: left; }
|
||||
.item-list th { background-color: #f8f9fa; }
|
||||
.footer { text-align: center; font-size: 0.8em; color: #777; margin-top: 30px; border-top: 1px solid #eee; padding-top: 10px; }
|
||||
.denda { font-weight: bold; color: #dc3545; }
|
||||
.success { color: #198754; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h2>BUKTI PENGEMBALIAN BUKU</h2>
|
||||
<p>{{ config('app.name') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<p>Halo, <strong>{{ $user->nama_lengkap }}</strong>,</p>
|
||||
<p>Terima kasih telah mengembalikan buku tepat waktu atau telah menyelesaikan denda yang berlaku. Berikut adalah rincian buku yang Anda kembalikan:</p>
|
||||
|
||||
<table class="item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Judul Buku</th>
|
||||
<th>Kondisi</th>
|
||||
<th>Denda</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($returns as $item)
|
||||
<tr>
|
||||
<td>{{ $item['judul'] }}</td>
|
||||
<td>{{ ucfirst($item['condition']) }}</td>
|
||||
<td>Rp {{ number_format($item['fine_damage'] + $item['fine_overdue'], 0, ',', '.') }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th colspan="2">TOTAL DENDA</th>
|
||||
<th class="denda">Rp {{ number_format($totalDenda, 0, ',', '.') }}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<p>Status: <span class="success">Berhasil Dikembalikan</span></p>
|
||||
<p>Pesan ini dikirim secara otomatis sebagai bukti sah bahwa Anda telah mengembalikan buku di atas ke perpustakaan.</p>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>© {{ date('Y') }} {{ config('app.name') }}. Semua Hak Dilindungi.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -37,13 +37,13 @@
|
|||
@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>
|
||||
<p class="fw-semibold text-dark">{{ $user->nomor_induk ?? '-' }}</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>
|
||||
<p class="fw-semibold text-dark">{{ $user->nomor_induk ?? '-' }}</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
|
@ -58,8 +58,8 @@
|
|||
<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
|
||||
@if($user->phone)
|
||||
<span>{{ $user->phone
|
||||
}}</span>
|
||||
@else
|
||||
<span class="text-muted fst-italic">- Belum diatur -</span>
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ class="btn btn-outline-primary rounded-pill w-100 w-sm-auto">
|
|||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<small class="text-muted d-block mb-1">Nomor HP</small>
|
||||
<p class="fw-semibold mb-0">{{ $user->no_hp ?? '-' }}</p>
|
||||
<p class="fw-semibold mb-0">{{ $user->phone ?? '-' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@
|
|||
<li class="list-group-item px-0">
|
||||
<h6 class="fw-semibold mb-1">{{ $buku['judul'] }}</h6>
|
||||
<small class="text-muted">{{ $buku['penulis'] }}</small>
|
||||
<span class="badge bg-danger-subtle text-danger-emphasis float-end">Sisa {{ $buku['sisa_hari'] }} hari</span>
|
||||
@if($buku['sisa_hari'] < 0)
|
||||
<span class="badge bg-danger-subtle text-danger-emphasis float-end">Terlambat {{ abs($buku['sisa_hari']) }} hari</span>
|
||||
@else
|
||||
<span class="badge bg-success-subtle text-success-emphasis float-end">Sisa {{ $buku['sisa_hari'] }} hari</span>
|
||||
@endif
|
||||
</li>
|
||||
@empty
|
||||
<li class="list-group-item px-0 text-center text-muted small py-3">Tidak ada buku yang sedang dipinjam.</li>
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ class="form-control @error('email') is-invalid @enderror" value="{{ old('email',
|
|||
@else
|
||||
{{-- Untuk Guru atau Penjaga Perpus --}}
|
||||
<div class="mb-3">
|
||||
<label for="nuptk" class="form-label">NIP / NUPTK</label>
|
||||
<input id="nuptk" type="text" class="form-control" value="{{ $user->nuptk }}" readonly disabled>
|
||||
<label for="nomor_induk" class="form-label">NIP / NUPTK</label>
|
||||
<input id="nomor_induk" type="text" class="form-control" value="{{ $user->nomor_induk }}" readonly disabled>
|
||||
<small class="text-muted">ID Kepegawaian tidak dapat diubah.</small>
|
||||
</div>
|
||||
@endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue