genarate spp serta update anggota
This commit is contained in:
parent
06f672b441
commit
9c68d4b734
|
|
@ -56,35 +56,52 @@ public function create()
|
||||||
return view('spp.pengurus.create', compact('data_anggota'));
|
return view('spp.pengurus.create', compact('data_anggota'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
// 1. Validasi Input
|
||||||
'anggota_id' => 'required|exists:anggotas,id',
|
$request->validate([
|
||||||
'bulan' => 'required',
|
'anggota_id' => 'required|exists:anggotas,id',
|
||||||
'tahun' => 'required',
|
'bulan' => 'required',
|
||||||
'nominal' => 'required|numeric',
|
'tahun' => 'required',
|
||||||
'jatuh_tempo' => 'required|date',
|
'nominal' => 'required|numeric',
|
||||||
]);
|
'jatuh_tempo' => 'required|date',
|
||||||
|
]);
|
||||||
|
|
||||||
try {
|
// 2. PENJAGA: Cek apakah tagihan untuk anggota, bulan, dan tahun tersebut sudah ada
|
||||||
$anggota = Anggota::findOrFail($request->anggota_id);
|
$cekDuplikat = Spp::where('anggota_id', $request->anggota_id)
|
||||||
|
->where('bulan', $request->bulan)
|
||||||
|
->where('tahun', $request->tahun)
|
||||||
|
->exists();
|
||||||
|
|
||||||
Spp::create([
|
// Jika sudah ada, langsung tendang balik ke form dengan pesan error
|
||||||
'anggota_id' => $request->anggota_id,
|
if ($cekDuplikat) {
|
||||||
'kolat_id' => $anggota->kolat_id,
|
return redirect()->back()
|
||||||
'bulan' => $request->bulan,
|
->withInput() // withInput menjaga agar form tidak kosong lagi
|
||||||
'tahun' => $request->tahun,
|
->with('error', "Gagal! Tagihan untuk bulan {$request->bulan} {$request->tahun} sudah terdaftar untuk anggota ini.");
|
||||||
'nominal' => $request->nominal,
|
|
||||||
'jatuh_tempo' => $request->jatuh_tempo,
|
|
||||||
'status' => 'belum_bayar',
|
|
||||||
]);
|
|
||||||
|
|
||||||
return redirect()->route('spp.index')->with('success', 'Tagihan berhasil dibuat!');
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return redirect()->back()->withInput()->with('error', 'Gagal menyimpan: '.$e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. Proses Penyimpanan (Jika lolos penjagaan)
|
||||||
|
try {
|
||||||
|
$anggota = Anggota::findOrFail($request->anggota_id);
|
||||||
|
|
||||||
|
Spp::create([
|
||||||
|
'anggota_id' => $request->anggota_id,
|
||||||
|
'kolat_id' => $anggota->kolat_id,
|
||||||
|
'bulan' => $request->bulan,
|
||||||
|
'tahun' => $request->tahun,
|
||||||
|
'nominal' => $request->nominal,
|
||||||
|
'jatuh_tempo' => $request->jatuh_tempo,
|
||||||
|
// Catatan Kecil: Pastikan penulisan 'belum_bayar' ini sama persis
|
||||||
|
// dengan filter yang dipakai di Dashboard Anggota ya!
|
||||||
|
'status' => 'pending',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('spp.index')->with('success', 'Tagihan manual berhasil dibuat!');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->back()->withInput()->with('error', 'Gagal menyimpan: '.$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
public function bayar(Request $request, $id)
|
public function bayar(Request $request, $id)
|
||||||
{
|
{
|
||||||
$spp = Spp::with('anggota')->findOrFail($id);
|
$spp = Spp::with('anggota')->findOrFail($id);
|
||||||
|
|
@ -127,43 +144,57 @@ public function bayar(Request $request, $id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateTagihan(Request $request)
|
public function generateTagihan(Request $request)
|
||||||
{
|
{
|
||||||
$bulanIni = Carbon::now()->translatedFormat('F');
|
// PERBAIKAN BHS INDONESIA: Tambahkan ->locale('id') agar outputnya pasti "Juni"
|
||||||
$tahunIni = Carbon::now()->year;
|
$bulanIni = \Carbon\Carbon::now()->locale('id')->translatedFormat('F');
|
||||||
$jatuhTempo = Carbon::now()->day(10);
|
$tahunIni = \Carbon\Carbon::now()->year;
|
||||||
|
|
||||||
$anggota = Anggota::all();
|
// Sesuaikan format jatuh tempo ke Y-m-d agar aman saat masuk ke database
|
||||||
|
$jatuhTempo = \Carbon\Carbon::now()->day(10)->format('Y-m-d');
|
||||||
|
|
||||||
DB::beginTransaction();
|
// --- 1. PENJAGA: Cek apakah bulan dan tahun ini sudah pernah di-generate ---
|
||||||
try {
|
$cekSudahGenerate = Spp::where('bulan', $bulanIni)
|
||||||
foreach ($anggota as $agt) {
|
->where('tahun', $tahunIni)
|
||||||
$exists = Spp::where('anggota_id', $agt->id)
|
->exists();
|
||||||
->where('bulan', $bulanIni)
|
|
||||||
->where('tahun', $tahunIni)
|
|
||||||
->exists();
|
|
||||||
|
|
||||||
if (! $exists) {
|
if ($cekSudahGenerate) {
|
||||||
Spp::create([
|
// Jika sudah ada, langsung tolak dan kembalikan ke halaman index dengan pesan warning
|
||||||
'anggota_id' => $agt->id,
|
return redirect()->route('spp.index')->with('warning', "Tagihan SPP bulan {$bulanIni} {$tahunIni} sudah pernah dibuat!");
|
||||||
'kolat_id' => $agt->kolat_id,
|
|
||||||
'bulan' => $bulanIni,
|
|
||||||
'tahun' => $tahunIni,
|
|
||||||
'nominal' => 50000,
|
|
||||||
'jatuh_tempo' => $jatuhTempo,
|
|
||||||
'status' => 'belum_bayar',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DB::commit();
|
|
||||||
|
|
||||||
return redirect()->route('spp.index')->with('success', 'Tagihan berhasil dibuat!');
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
DB::rollback();
|
|
||||||
|
|
||||||
return redirect()->back()->with('error', 'Gagal: '.$e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
$anggota = Anggota::where('status', 'Aktif')->get(); // Pastikan hanya menagih yang aktif
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
try {
|
||||||
|
foreach ($anggota as $agt) {
|
||||||
|
// Pengecekan per-user untuk keamanan ekstra
|
||||||
|
$exists = Spp::where('anggota_id', $agt->id)
|
||||||
|
->where('bulan', $bulanIni)
|
||||||
|
->where('tahun', $tahunIni)
|
||||||
|
->exists();
|
||||||
|
|
||||||
|
if (! $exists) {
|
||||||
|
Spp::create([
|
||||||
|
'anggota_id' => $agt->id,
|
||||||
|
'kolat_id' => $agt->kolat_id,
|
||||||
|
'bulan' => $bulanIni,
|
||||||
|
'tahun' => $tahunIni,
|
||||||
|
'nominal' => 50000,
|
||||||
|
'jatuh_tempo' => $jatuhTempo,
|
||||||
|
'status' => 'belum_bayar', // PERBAIKAN STATUS: Disamakan menjadi 'belum_bayar'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
return redirect()->route('spp.index')->with('success', "Tagihan bulan {$bulanIni} berhasil dibuat!");
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollback();
|
||||||
|
return redirect()->back()->with('error', 'Gagal: '.$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function exportExcel(Request $request)
|
public function exportExcel(Request $request)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,19 @@ public function role()
|
||||||
return $this->belongsTo(Role::class, 'role_id');
|
return $this->belongsTo(Role::class, 'role_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function kolatLatihan()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Kolat::class, 'kolat_pelatih', 'anggota_id', 'kolat_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scope agar gampang memanggil data yang hanya ber-role Pelatih
|
||||||
|
public function scopeIsPelatih($query)
|
||||||
|
{
|
||||||
|
return $query->whereHas('role', function ($q) {
|
||||||
|
$q->where('nama_role', 'Pelatih');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Relasi: Mendapatkan riwayat kehadiran anggota
|
// Relasi: Mendapatkan riwayat kehadiran anggota
|
||||||
public function riwayatPresensi()
|
public function riwayatPresensi()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,4 +23,11 @@ public function anggota()
|
||||||
{
|
{
|
||||||
return $this->hasMany(Anggota::class, 'kolat_id');
|
return $this->hasMany(Anggota::class, 'kolat_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function pelatihs()
|
||||||
|
{
|
||||||
|
// Panggil relasi pivot, lalu sambungkan dengan scope isPelatih()
|
||||||
|
return $this->belongsToMany(Anggota::class, 'kolat_pelatih', 'kolat_id', 'anggota_id')
|
||||||
|
->isPelatih();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('kolat_pelatih', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
|
||||||
|
// Relasi ke anggota (yang bertindak sebagai pelatih) dan kolat
|
||||||
|
$table->foreignId('anggota_id')->constrained('anggotas')->onDelete('cascade');
|
||||||
|
$table->foreignId('kolat_id')->constrained('kolat')->onDelete('cascade');
|
||||||
|
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('kolat_pelatih');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -13,7 +13,7 @@ class DatabaseSeeder extends Seeder
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
$this->call([
|
$this->call([
|
||||||
// RoleSeeder::class,
|
RoleSeeder::class,
|
||||||
KolatSeeder::class,
|
KolatSeeder::class,
|
||||||
UserSeeder::class,
|
UserSeeder::class,
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class KolatSeeder extends Seeder
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
DB::table('kolat')->insert([
|
DB::table('kolat')->insert([
|
||||||
'id' => 2, // Kita paksa ID 1 biar nyambung sama UserSeeder tadi
|
'id' => 1, // Kita paksa ID 1 biar nyambung sama UserSeeder tadi
|
||||||
'nama_kolat' => 'Kolat Unej',
|
'nama_kolat' => 'Kolat Unej',
|
||||||
'created_at' => now(),
|
'created_at' => now(),
|
||||||
'updated_at' => now(),
|
'updated_at' => now(),
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,22 @@
|
||||||
</script>
|
</script>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Cari tombol dengan class toggle-sidebar-btn
|
||||||
|
const toggleBtn = document.querySelector('.toggle-sidebar-btn');
|
||||||
|
|
||||||
|
// Pastikan tombolnya ada
|
||||||
|
if (toggleBtn) {
|
||||||
|
// Berikan aksi ketika tombol diklik
|
||||||
|
toggleBtn.addEventListener('click', function(e) {
|
||||||
|
// Tambahkan atau hapus class 'toggle-sidebar' pada tag body
|
||||||
|
document.body.classList.toggle('toggle-sidebar');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||||
<title>Daftar Anggota - TapakMP</title>
|
<title>Daftar Anggota - TapakMP</title>
|
||||||
|
|
||||||
<link href="{{ asset('assets/img/favicon.png') }}" rel="icon">
|
<link href="{{ asset('assets/img/logo1.jpg') }}" rel="icon">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&family=Ubuntu:wght@400;500;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&family=Ubuntu:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
<link href="{{ asset('assets/vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
|
<link href="{{ asset('assets/vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Alert Notifikasi -->
|
<!-- Alert Notifikasi -->
|
||||||
@if(session('error'))
|
{{-- @if(session('error'))
|
||||||
<div class="alert alert-danger border-0 shadow-sm mb-4" style="border-radius: 12px;">
|
<div class="alert alert-danger border-0 shadow-sm mb-4" style="border-radius: 12px;">
|
||||||
{{ session('error') }}
|
{{ session('error') }}
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif --}}
|
||||||
|
|
||||||
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
|
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
|
|
@ -106,4 +106,34 @@
|
||||||
border: 1px solid #0d6efd !important;
|
border: 1px solid #0d6efd !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
|
||||||
|
// POP-UP JIKA DATA DUPLIKAT / ERROR
|
||||||
|
@if(session('error'))
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Data Sudah Ada!',
|
||||||
|
text: "{{ session('error') }}",
|
||||||
|
icon: 'warning', // Saya pakai icon warning agar kesannya "peringatan", bukan error sistem rusak
|
||||||
|
confirmButtonColor: '#f59e0b',
|
||||||
|
confirmButtonText: 'Oke, Ganti Data'
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
|
||||||
|
// POP-UP JIKA BERHASIL SIMPAN MANUAL (Sekalian aja wkwk)
|
||||||
|
@if(session('success'))
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Berhasil!',
|
||||||
|
text: "{{ session('success') }}",
|
||||||
|
icon: 'success',
|
||||||
|
confirmButtonColor: '#10b981',
|
||||||
|
confirmButtonText: 'Mantap!'
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -1,299 +1,422 @@
|
||||||
@extends('layout.app')
|
@extends('layout.app')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
@php
|
@php
|
||||||
$userRole = auth()->user()->role->nama_role ?? 'Anggota';
|
$userRole = auth()->user()->role->nama_role ?? 'Anggota';
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<div class="container-fluid py-4">
|
<div class="container-fluid py-4">
|
||||||
<!-- Header Section -->
|
<!-- Header Section -->
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-3">
|
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-3">
|
||||||
<div class="text-start">
|
<div class="text-start">
|
||||||
<h3 class="fw-bold text-dark mb-1">Manajemen SPP</h3>
|
<h3 class="fw-bold text-dark mb-1">Manajemen SPP</h3>
|
||||||
<p class="text-muted small mb-0">Kelola tagihan dan pembayaran SPP anggota Merpati Putih.</p>
|
<p class="text-muted small mb-0">Kelola tagihan dan pembayaran SPP anggota Merpati Putih.</p>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-wrap gap-2">
|
||||||
|
{{-- HANYA PENGURUS YANG BISA GENERATE MASAL --}}
|
||||||
|
@if ($userRole == 'Pengurus')
|
||||||
|
<form action="{{ route('spp.generate') }}" method="POST" class="m-0" id="formGenerateSpp">
|
||||||
|
@csrf
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-warning text-white px-3 py-2 shadow-sm d-flex align-items-center h-100"
|
||||||
|
style="border-radius: 10px;" onclick="konfirmasiGenerate()">
|
||||||
|
<i class="fas fa-cog me-2"></i> Generate
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<a href="{{ route('spp.export.excel', request()->all()) }}"
|
||||||
|
class="btn btn-success px-3 py-2 shadow-sm d-flex align-items-center"
|
||||||
|
style="border-radius: 10px; text-decoration: none;">
|
||||||
|
<i class="fas fa-file-excel me-2"></i> Excel
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="{{ route('spp.export.pdf', request()->all()) }}"
|
||||||
|
class="btn btn-danger px-3 py-2 shadow-sm d-flex align-items-center"
|
||||||
|
style="border-radius: 10px; text-decoration: none;">
|
||||||
|
<i class="fas fa-file-pdf me-2"></i> PDF
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="{{ route('spp.create') }}" class="btn btn-primary px-3 py-2 shadow-sm d-flex align-items-center"
|
||||||
|
style="border-radius: 10px; text-decoration: none;">
|
||||||
|
<i class="fas fa-plus me-2"></i> Tambah Manual
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-wrap gap-2">
|
|
||||||
{{-- HANYA PENGURUS YANG BISA GENERATE MASAL --}}
|
|
||||||
@if($userRole == 'Pengurus')
|
|
||||||
<form action="{{ route('spp.generate') }}" method="POST" class="m-0">
|
|
||||||
@csrf
|
|
||||||
<button type="submit" class="btn btn-warning text-white px-3 py-2 shadow-sm d-flex align-items-center h-100" style="border-radius: 10px;" onclick="return confirm('Generate tagihan otomatis untuk bulan ini?')">
|
|
||||||
<i class="fas fa-cog me-2"></i> Generate
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<a href="{{ route('spp.export.excel', request()->all()) }}" class="btn btn-success px-3 py-2 shadow-sm d-flex align-items-center" style="border-radius: 10px; text-decoration: none;">
|
<!-- Alert Notifikasi -->
|
||||||
<i class="fas fa-file-excel me-2"></i> Excel
|
@if (session('success'))
|
||||||
</a>
|
<div class="alert alert-success border-0 shadow-sm mb-4" style="border-radius: 10px;">
|
||||||
|
<i class="fas fa-check-circle me-1"></i> {{ session('success') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<a href="{{ route('spp.export.pdf', request()->all()) }}" class="btn btn-danger px-3 py-2 shadow-sm d-flex align-items-center" style="border-radius: 10px; text-decoration: none;">
|
<!-- Statistik Cards -->
|
||||||
<i class="fas fa-file-pdf me-2"></i> PDF
|
<div class="row g-3 mb-4">
|
||||||
</a>
|
<div class="col-md-3">
|
||||||
|
<div class="card border-0 shadow-sm border-start border-success border-4 h-100"
|
||||||
<a href="{{ route('spp.create') }}" class="btn btn-primary px-3 py-2 shadow-sm d-flex align-items-center" style="border-radius: 10px; text-decoration: none;">
|
style="border-radius: 15px;">
|
||||||
<i class="fas fa-plus me-2"></i> Tambah Manual
|
<div class="card-body p-4 d-flex justify-content-between align-items-center">
|
||||||
</a>
|
<div>
|
||||||
</div>
|
<p class="text-success small fw-bold mb-1 uppercase">SPP LUNAS</p>
|
||||||
</div>
|
<h3 class="fw-bold mb-0">{{ $stats['lunas'] }}</h3>
|
||||||
|
</div>
|
||||||
<!-- Alert Notifikasi -->
|
<i class="fas fa-check-circle text-success fs-1"></i>
|
||||||
@if(session('success'))
|
</div>
|
||||||
<div class="alert alert-success border-0 shadow-sm mb-4" style="border-radius: 10px;">
|
</div>
|
||||||
<i class="fas fa-check-circle me-1"></i> {{ session('success') }}
|
</div>
|
||||||
</div>
|
<div class="col-md-3">
|
||||||
@endif
|
<div class="card border-0 shadow-sm border-start border-warning border-4 h-100"
|
||||||
|
style="border-radius: 15px;">
|
||||||
<!-- Statistik Cards -->
|
<div class="card-body p-4 d-flex justify-content-between align-items-center">
|
||||||
<div class="row g-3 mb-4">
|
<div>
|
||||||
<div class="col-md-3">
|
<p class="text-warning small fw-bold mb-1 uppercase">PENDING</p>
|
||||||
<div class="card border-0 shadow-sm border-start border-success border-4 h-100" style="border-radius: 15px;">
|
<h3 class="fw-bold mb-0">{{ $stats['pending'] }}</h3>
|
||||||
<div class="card-body p-4 d-flex justify-content-between align-items-center">
|
</div>
|
||||||
<div>
|
<i class="fas fa-clock text-warning fs-1"></i>
|
||||||
<p class="text-success small fw-bold mb-1 uppercase">SPP LUNAS</p>
|
</div>
|
||||||
<h3 class="fw-bold mb-0">{{ $stats['lunas'] }}</h3>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card border-0 shadow-sm border-start border-danger border-4 h-100" style="border-radius: 15px;">
|
||||||
|
<div class="card-body p-4 d-flex justify-content-between align-items-center">
|
||||||
|
<div>
|
||||||
|
<p class="text-danger small fw-bold mb-1 uppercase">BELUM BAYAR</p>
|
||||||
|
<h3 class="fw-bold mb-0">{{ $stats['belum_bayar'] }}</h3>
|
||||||
|
</div>
|
||||||
|
<i class="fas fa-exclamation-triangle text-danger fs-1"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card border-0 shadow-sm border-start border-primary border-4 h-100"
|
||||||
|
style="border-radius: 15px;">
|
||||||
|
<div class="card-body p-4 d-flex justify-content-between align-items-center">
|
||||||
|
<div>
|
||||||
|
<p class="text-primary small fw-bold mb-1 uppercase">TOTAL MASUK</p>
|
||||||
|
<h3 class="fw-bold mb-0">Rp {{ number_format($stats['total_pemasukan'], 0, ',', '.') }}</h3>
|
||||||
|
</div>
|
||||||
|
<i class="fas fa-money-bill-wave text-primary fs-1"></i>
|
||||||
</div>
|
</div>
|
||||||
<i class="fas fa-check-circle text-success fs-1"></i>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="card border-0 shadow-sm border-start border-warning border-4 h-100" style="border-radius: 15px;">
|
<!-- Filter Data SPP -->
|
||||||
<div class="card-body p-4 d-flex justify-content-between align-items-center">
|
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px; overflow: hidden;">
|
||||||
<div>
|
<div class="card-header border-0 py-3 text-white" style="background-color: #0d6efd;">
|
||||||
<p class="text-warning small fw-bold mb-1 uppercase">PENDING</p>
|
<h6 class="mb-0 fw-bold"><i class="fas fa-filter me-2"></i>Filter Data SPP</h6>
|
||||||
<h3 class="fw-bold mb-0">{{ $stats['pending'] }}</h3>
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<form action="{{ route('spp.index') }}" method="GET" class="row g-3 align-items-end">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<label class="form-label small fw-bold">Tahun</label>
|
||||||
|
<select name="tahun" class="form-select border-0 bg-light">
|
||||||
|
<option value="2026" {{ request('tahun') == '2026' ? 'selected' : '' }}>2026</option>
|
||||||
|
<option value="2025" {{ request('tahun') == '2025' ? 'selected' : '' }}>2025</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<i class="fas fa-clock text-warning fs-1"></i>
|
<div class="col-md-3">
|
||||||
</div>
|
<label class="form-label small fw-bold">Bulan</label>
|
||||||
|
<select name="bulan" class="form-select border-0 bg-light">
|
||||||
|
<option value="">Semua Bulan</option>
|
||||||
|
@foreach (['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'] as $m)
|
||||||
|
<option value="{{ $m }}" {{ request('bulan') == $m ? 'selected' : '' }}>
|
||||||
|
{{ $m }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label small fw-bold">Status</label>
|
||||||
|
<select name="status" class="form-select border-0 bg-light">
|
||||||
|
<option value="">Semua Status</option>
|
||||||
|
<option value="lunas" {{ request('status') == 'lunas' ? 'selected' : '' }}>Lunas</option>
|
||||||
|
<option value="pending" {{ request('status') == 'pending' ? 'selected' : '' }}>Pending</option>
|
||||||
|
<option value="belum_bayar" {{ request('status') == 'belum_bayar' ? 'selected' : '' }}>Belum
|
||||||
|
Bayar</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label class="form-label small fw-bold">Cari Anggota</label>
|
||||||
|
<input type="text" name="cari" class="form-control border-0 bg-light"
|
||||||
|
placeholder="Nama anggota..." value="{{ request('cari') }}">
|
||||||
|
</div>
|
||||||
|
<div class="col-12 mt-3">
|
||||||
|
<button type="submit" class="btn btn-primary px-4 shadow-sm"
|
||||||
|
style="background-color: #0d6efd; border-radius: 10px;">
|
||||||
|
<i class="fas fa-search me-1"></i> Filter
|
||||||
|
</button>
|
||||||
|
<a href="{{ route('spp.index') }}" class="btn btn-light px-4 shadow-sm"
|
||||||
|
style="border-radius: 10px;">
|
||||||
|
<i class="fas fa-sync-alt me-1"></i> Reset
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="card border-0 shadow-sm border-start border-danger border-4 h-100" style="border-radius: 15px;">
|
<!-- Daftar Tagihan Section -->
|
||||||
<div class="card-body p-4 d-flex justify-content-between align-items-center">
|
<div class="card border-0 shadow-sm" style="border-radius: 20px; overflow: hidden;">
|
||||||
<div>
|
<div class="card-header border-0 py-3 text-white d-flex justify-content-between align-items-center"
|
||||||
<p class="text-danger small fw-bold mb-1 uppercase">BELUM BAYAR</p>
|
style="background-color: #0d6efd;">
|
||||||
<h3 class="fw-bold mb-0">{{ $stats['belum_bayar'] }}</h3>
|
<h6 class="mb-0 fw-bold"><i class="fas fa-money-check me-2"></i>Daftar Tagihan SPP</h6>
|
||||||
</div>
|
|
||||||
<i class="fas fa-exclamation-triangle text-danger fs-1"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="card-body p-0">
|
||||||
<div class="col-md-3">
|
@if ($data_spp->isEmpty())
|
||||||
<div class="card border-0 shadow-sm border-start border-primary border-4 h-100" style="border-radius: 15px;">
|
<div class="py-5 text-center">
|
||||||
<div class="card-body p-4 d-flex justify-content-between align-items-center">
|
<i class="fas fa-file-invoice-dollar text-muted mb-4" style="font-size: 80px; opacity: 0.2;"></i>
|
||||||
<div>
|
<h5 class="fw-bold text-muted">Belum ada data tagihan SPP</h5>
|
||||||
<p class="text-primary small fw-bold mb-1 uppercase">TOTAL MASUK</p>
|
<p class="text-muted small">Silakan tambah manual atau generate otomatis.</p>
|
||||||
<h3 class="fw-bold mb-0">Rp {{ number_format($stats['total_pemasukan'], 0, ',', '.') }}</h3>
|
<a href="{{ route('spp.create') }}" class="btn btn-danger text-white px-4 py-2 mt-2"
|
||||||
|
style="border-radius: 10px;">Tambah Manual</a>
|
||||||
</div>
|
</div>
|
||||||
<i class="fas fa-money-bill-wave text-primary fs-1"></i>
|
@else
|
||||||
</div>
|
<div class="table-responsive">
|
||||||
</div>
|
<table class="table table-hover align-middle mb-0">
|
||||||
</div>
|
<thead class="bg-light text-muted uppercase">
|
||||||
</div>
|
<tr>
|
||||||
|
<th class="ps-4" style="width: 30%;">Anggota</th>
|
||||||
<!-- Filter Data SPP -->
|
<th>Periode</th>
|
||||||
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px; overflow: hidden;">
|
<th>Nominal</th>
|
||||||
<div class="card-header border-0 py-3 text-white" style="background-color: #0d6efd;">
|
<th>Status</th>
|
||||||
<h6 class="mb-0 fw-bold"><i class="fas fa-filter me-2"></i>Filter Data SPP</h6>
|
<th class="text-center">Aksi</th>
|
||||||
</div>
|
</tr>
|
||||||
<div class="card-body p-4">
|
</thead>
|
||||||
<form action="{{ route('spp.index') }}" method="GET" class="row g-3 align-items-end">
|
<tbody>
|
||||||
<div class="col-md-2">
|
@foreach ($data_spp as $spp)
|
||||||
<label class="form-label small fw-bold">Tahun</label>
|
<tr>
|
||||||
<select name="tahun" class="form-select border-0 bg-light">
|
<td class="ps-4">
|
||||||
<option value="2026" {{ request('tahun') == '2026' ? 'selected' : '' }}>2026</option>
|
<div class="d-flex align-items-center">
|
||||||
<option value="2025" {{ request('tahun') == '2025' ? 'selected' : '' }}>2025</option>
|
<div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-center me-3 shadow-sm"
|
||||||
</select>
|
style="width: 40px; height: 40px; font-size: 14px; font-weight: bold; background: linear-gradient(45deg, #0d6efd, #0099bc);">
|
||||||
</div>
|
{{ strtoupper(substr($spp->anggota->nama_lengkap, 0, 1)) }}
|
||||||
<div class="col-md-3">
|
</div>
|
||||||
<label class="form-label small fw-bold">Bulan</label>
|
<div>
|
||||||
<select name="bulan" class="form-select border-0 bg-light">
|
<div class="fw-bold text-dark" style="font-size: 0.95rem;">
|
||||||
<option value="">Semua Bulan</option>
|
{{ $spp->anggota->nama_lengkap }}</div>
|
||||||
@foreach(['Januari','Februari','Maret','April','Mei','Juni','Juli','Agustus','September','Oktober','November','Desember'] as $m)
|
<span class="badge bg-light text-muted border fw-normal"
|
||||||
<option value="{{ $m }}" {{ request('bulan') == $m ? 'selected' : '' }}>{{ $m }}</option>
|
style="font-size: 0.75rem;">
|
||||||
@endforeach
|
ID: {{ $spp->anggota_id }}
|
||||||
</select>
|
</span>
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<label class="form-label small fw-bold">Status</label>
|
|
||||||
<select name="status" class="form-select border-0 bg-light">
|
|
||||||
<option value="">Semua Status</option>
|
|
||||||
<option value="lunas" {{ request('status') == 'lunas' ? 'selected' : '' }}>Lunas</option>
|
|
||||||
<option value="pending" {{ request('status') == 'pending' ? 'selected' : '' }}>Pending</option>
|
|
||||||
<option value="belum_bayar" {{ request('status') == 'belum_bayar' ? 'selected' : '' }}>Belum Bayar</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label class="form-label small fw-bold">Cari Anggota</label>
|
|
||||||
<input type="text" name="cari" class="form-control border-0 bg-light" placeholder="Nama anggota..." value="{{ request('cari') }}">
|
|
||||||
</div>
|
|
||||||
<div class="col-12 mt-3">
|
|
||||||
<button type="submit" class="btn btn-primary px-4 shadow-sm" style="background-color: #0d6efd; border-radius: 10px;">
|
|
||||||
<i class="fas fa-search me-1"></i> Filter
|
|
||||||
</button>
|
|
||||||
<a href="{{ route('spp.index') }}" class="btn btn-light px-4 shadow-sm" style="border-radius: 10px;">
|
|
||||||
<i class="fas fa-sync-alt me-1"></i> Reset
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Daftar Tagihan Section -->
|
|
||||||
<div class="card border-0 shadow-sm" style="border-radius: 20px; overflow: hidden;">
|
|
||||||
<div class="card-header border-0 py-3 text-white d-flex justify-content-between align-items-center" style="background-color: #0d6efd;">
|
|
||||||
<h6 class="mb-0 fw-bold"><i class="fas fa-money-check me-2"></i>Daftar Tagihan SPP</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body p-0">
|
|
||||||
@if($data_spp->isEmpty())
|
|
||||||
<div class="py-5 text-center">
|
|
||||||
<i class="fas fa-file-invoice-dollar text-muted mb-4" style="font-size: 80px; opacity: 0.2;"></i>
|
|
||||||
<h5 class="fw-bold text-muted">Belum ada data tagihan SPP</h5>
|
|
||||||
<p class="text-muted small">Silakan tambah manual atau generate otomatis.</p>
|
|
||||||
<a href="{{ route('spp.create') }}" class="btn btn-danger text-white px-4 py-2 mt-2" style="border-radius: 10px;">Tambah Manual</a>
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-hover align-middle mb-0">
|
|
||||||
<thead class="bg-light text-muted uppercase">
|
|
||||||
<tr>
|
|
||||||
<th class="ps-4" style="width: 30%;">Anggota</th>
|
|
||||||
<th>Periode</th>
|
|
||||||
<th>Nominal</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th class="text-center">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach($data_spp as $spp)
|
|
||||||
<tr>
|
|
||||||
<td class="ps-4">
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-center me-3 shadow-sm"
|
|
||||||
style="width: 40px; height: 40px; font-size: 14px; font-weight: bold; background: linear-gradient(45deg, #0d6efd, #0099bc);">
|
|
||||||
{{ strtoupper(substr($spp->anggota->nama_lengkap, 0, 1)) }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="fw-bold text-dark" style="font-size: 0.95rem;">{{ $spp->anggota->nama_lengkap }}</div>
|
|
||||||
<span class="badge bg-light text-muted border fw-normal" style="font-size: 0.75rem;">
|
|
||||||
ID: {{ $spp->anggota_id }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="text-dark fw-medium">{{ $spp->bulan }}</div>
|
|
||||||
<div class="small text-muted">{{ $spp->tahun }}</div>
|
|
||||||
</td>
|
|
||||||
<td class="fw-bold text-dark">
|
|
||||||
Rp {{ number_format($spp->nominal, 0, ',', '.') }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@if($spp->status == 'lunas')
|
|
||||||
<span class="badge bg-success-soft text-success rounded-pill px-3">
|
|
||||||
<i class="fas fa-check-circle me-1"></i> Lunas
|
|
||||||
</span>
|
|
||||||
@elseif($spp->status == 'pending')
|
|
||||||
<span class="badge bg-warning-soft text-warning rounded-pill px-3">
|
|
||||||
<i class="fas fa-hourglass-half me-1"></i> Menunggu Validasi
|
|
||||||
</span>
|
|
||||||
@elseif($spp->status == 'belum_bayar' && \Carbon\Carbon::parse($spp->jatuh_tempo)->isPast())
|
|
||||||
<span class="badge bg-danger-soft text-danger rounded-pill px-3">
|
|
||||||
<i class="fas fa-exclamation-circle me-1"></i> Terlambat
|
|
||||||
</span>
|
|
||||||
@else
|
|
||||||
<span class="badge bg-warning-soft text-warning rounded-pill px-3">
|
|
||||||
<i class="fas fa-clock me-1"></i> Belum Bayar
|
|
||||||
</span>
|
|
||||||
@endif
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
@if($spp->status == 'belum_bayar')
|
|
||||||
<form action="{{ route('spp.bayar', $spp->id) }}" method="POST" class="d-inline">
|
|
||||||
@csrf
|
|
||||||
<button type="submit" class="btn btn-sm btn-primary px-3 shadow-sm"
|
|
||||||
style="border-radius: 8px;"
|
|
||||||
onclick="return confirm('Konfirmasi pembayaran tunai untuk {{ $spp->anggota->nama_lengkap }}?')">
|
|
||||||
@if($userRole == 'Pelatih')
|
|
||||||
<i class="fas fa-hand-holding-usd me-1"></i> Terima Cash
|
|
||||||
@else
|
|
||||||
Bayar Tunai
|
|
||||||
@endif
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
@elseif($spp->status == 'pending')
|
|
||||||
<div class="d-flex justify-content-center gap-1">
|
|
||||||
<button type="button" class="btn btn-sm btn-info text-white px-2 shadow-sm"
|
|
||||||
style="border-radius: 8px;"
|
|
||||||
data-bs-toggle="modal" data-bs-target="#modalBukti{{ $spp->id }}">
|
|
||||||
<i class="fas fa-eye"></i> Bukti
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{{-- HANYA PENGURUS YANG BISA VALIDASI STATUS PENDING --}}
|
|
||||||
@if($userRole == 'Pengurus')
|
|
||||||
<form action="{{ route('spp.bayar', $spp->id) }}" method="POST" class="d-inline">
|
|
||||||
@csrf
|
|
||||||
<button type="submit" class="btn btn-sm btn-success px-2 shadow-sm"
|
|
||||||
style="border-radius: 8px;"
|
|
||||||
onclick="return confirm('Validasi bukti transfer dan nyatakan LUNAS?')">
|
|
||||||
<i class="fas fa-check"></i> Validasi
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- MODAL BUKTI TRANSFER -->
|
|
||||||
<div class="modal fade text-start" id="modalBukti{{ $spp->id }}" tabindex="-1" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
|
||||||
<div class="modal-content" style="border-radius: 15px;">
|
|
||||||
<div class="modal-header border-0 pb-0">
|
|
||||||
<h5 class="modal-title fw-bold">Bukti Transfer</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body text-center pt-3 pb-4">
|
|
||||||
<p class="text-muted small mb-3">Atas Nama: <strong>{{ $spp->anggota->nama_lengkap }}</strong></p>
|
|
||||||
@if($spp->bukti_pembayaran)
|
|
||||||
<img src="{{ asset('uploads/bukti_spp/' . $spp->bukti_pembayaran) }}" alt="Bukti Transfer" class="img-fluid rounded shadow-sm" style="max-height: 400px; object-fit: contain;">
|
|
||||||
@if($spp->tanggal_bayar)
|
|
||||||
<p class="text-muted small mt-3 mb-0">Diunggah pada: {{ \Carbon\Carbon::parse($spp->tanggal_bayar)->translatedFormat('d F Y H:i') }}</p>
|
|
||||||
@endif
|
|
||||||
@else
|
|
||||||
<div class="text-danger my-4">
|
|
||||||
<i class="fas fa-exclamation-triangle fs-1 mb-2"></i>
|
|
||||||
<h6>Bukti gambar tidak ditemukan.</h6>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text-dark fw-medium">{{ $spp->bulan }}</div>
|
||||||
|
<div class="small text-muted">{{ $spp->tahun }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="fw-bold text-dark">
|
||||||
|
Rp {{ number_format($spp->nominal, 0, ',', '.') }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if ($spp->status == 'lunas')
|
||||||
|
<span class="badge bg-success-soft text-success rounded-pill px-3">
|
||||||
|
<i class="fas fa-check-circle me-1"></i> Lunas
|
||||||
|
</span>
|
||||||
|
@elseif($spp->status == 'pending')
|
||||||
|
<span class="badge bg-warning-soft text-warning rounded-pill px-3">
|
||||||
|
<i class="fas fa-hourglass-half me-1"></i> Menunggu Validasi
|
||||||
|
</span>
|
||||||
|
@elseif($spp->status == 'belum_bayar' && \Carbon\Carbon::parse($spp->jatuh_tempo)->isPast())
|
||||||
|
<span class="badge bg-danger-soft text-danger rounded-pill px-3">
|
||||||
|
<i class="fas fa-exclamation-circle me-1"></i> Terlambat
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-warning-soft text-warning rounded-pill px-3">
|
||||||
|
<i class="fas fa-clock me-1"></i> Belum Bayar
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
@if ($spp->status == 'belum_bayar')
|
||||||
|
<form action="{{ route('spp.bayar', $spp->id) }}" method="POST"
|
||||||
|
class="d-inline">
|
||||||
|
@csrf
|
||||||
|
<button type="submit" class="btn btn-sm btn-primary px-3 shadow-sm"
|
||||||
|
style="border-radius: 8px;"
|
||||||
|
onclick="return confirm('Konfirmasi pembayaran tunai untuk {{ $spp->anggota->nama_lengkap }}?')">
|
||||||
|
@if ($userRole == 'Pelatih')
|
||||||
|
<i class="fas fa-hand-holding-usd me-1"></i> Terima Cash
|
||||||
|
@else
|
||||||
|
Bayar Tunai
|
||||||
|
@endif
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
@elseif($spp->status == 'pending')
|
||||||
|
<div class="d-flex justify-content-center gap-1">
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-sm btn-info text-white px-2 shadow-sm"
|
||||||
|
style="border-radius: 8px;" data-bs-toggle="modal"
|
||||||
|
data-bs-target="#modalBukti{{ $spp->id }}">
|
||||||
|
<i class="fas fa-eye"></i> Bukti
|
||||||
|
</button>
|
||||||
|
|
||||||
@else
|
{{-- HANYA PENGURUS YANG BISA VALIDASI STATUS PENDING --}}
|
||||||
<span class="text-success small fw-bold">
|
@if ($userRole == 'Pengurus')
|
||||||
<i class="fas fa-check-double me-1"></i> Terverifikasi
|
<form action="{{ route('spp.bayar', $spp->id) }}" method="POST"
|
||||||
</span>
|
class="d-inline">
|
||||||
@endif
|
@csrf
|
||||||
</td>
|
<button type="submit"
|
||||||
</tr>
|
class="btn btn-sm btn-success px-2 shadow-sm"
|
||||||
@endforeach
|
style="border-radius: 8px;"
|
||||||
</tbody>
|
onclick="return confirm('Validasi bukti transfer dan nyatakan LUNAS?')">
|
||||||
</table>
|
<i class="fas fa-check"></i> Validasi
|
||||||
</div>
|
</button>
|
||||||
@endif
|
</form>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- MODAL BUKTI TRANSFER -->
|
||||||
|
<div class="modal fade text-start" id="modalBukti{{ $spp->id }}"
|
||||||
|
tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content" style="border-radius: 15px;">
|
||||||
|
<div class="modal-header border-0 pb-0">
|
||||||
|
<h5 class="modal-title fw-bold">Bukti Transfer</h5>
|
||||||
|
<button type="button" class="btn-close"
|
||||||
|
data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-center pt-3 pb-4">
|
||||||
|
<p class="text-muted small mb-3">Atas Nama:
|
||||||
|
<strong>{{ $spp->anggota->nama_lengkap }}</strong></p>
|
||||||
|
@if ($spp->bukti_pembayaran)
|
||||||
|
<img src="{{ asset('uploads/bukti_spp/' . $spp->bukti_pembayaran) }}"
|
||||||
|
alt="Bukti Transfer"
|
||||||
|
class="img-fluid rounded shadow-sm"
|
||||||
|
style="max-height: 400px; object-fit: contain;">
|
||||||
|
@if ($spp->tanggal_bayar)
|
||||||
|
<p class="text-muted small mt-3 mb-0">Diunggah
|
||||||
|
pada:
|
||||||
|
{{ \Carbon\Carbon::parse($spp->tanggal_bayar)->translatedFormat('d F Y H:i') }}
|
||||||
|
</p>
|
||||||
|
@endif
|
||||||
|
@else
|
||||||
|
<div class="text-danger my-4">
|
||||||
|
<i
|
||||||
|
class="fas fa-exclamation-triangle fs-1 mb-2"></i>
|
||||||
|
<h6>Bukti gambar tidak ditemukan.</h6>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<span class="text-success small fw-bold">
|
||||||
|
<i class="fas fa-check-double me-1"></i> Terverifikasi
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.bg-light { background-color: #f8f9fa !important; }
|
.bg-light {
|
||||||
.uppercase { text-transform: uppercase; letter-spacing: 0.8px; font-size: 10px; font-weight: 700; }
|
background-color: #f8f9fa !important;
|
||||||
.fs-1 { font-size: 2.2rem !important; opacity: 0.2; }
|
}
|
||||||
.bg-success-soft { background-color: rgba(25, 135, 84, 0.12); }
|
|
||||||
.bg-danger-soft { background-color: rgba(220, 53, 69, 0.12); }
|
.uppercase {
|
||||||
.bg-warning-soft { background-color: rgba(255, 193, 7, 0.15); }
|
text-transform: uppercase;
|
||||||
.table-hover tbody tr:hover { background-color: rgba(13, 110, 253, 0.03); transition: 0.2s; }
|
letter-spacing: 0.8px;
|
||||||
.form-select, .form-control { border-radius: 10px; padding: 0.6rem 1rem; }
|
font-size: 10px;
|
||||||
</style>
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-1 {
|
||||||
|
font-size: 2.2rem !important;
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-success-soft {
|
||||||
|
background-color: rgba(25, 135, 84, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-danger-soft {
|
||||||
|
background-color: rgba(220, 53, 69, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-warning-soft {
|
||||||
|
background-color: rgba(255, 193, 7, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-hover tbody tr:hover {
|
||||||
|
background-color: rgba(13, 110, 253, 0.03);
|
||||||
|
transition: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-select,
|
||||||
|
.form-control {
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 2. Fungsi ini yang dipanggil saat tombol Generate diklik
|
||||||
|
function konfirmasiGenerate() {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Generate Tagihan?',
|
||||||
|
text: "Sistem akan membuat tagihan SPP untuk semua anggota aktif bulan ini.",
|
||||||
|
icon: 'question',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: '#f59e0b',
|
||||||
|
cancelButtonColor: '#6c757d',
|
||||||
|
confirmButtonText: '<i class="fas fa-cog"></i> Ya, Generate!',
|
||||||
|
cancelButtonText: 'Batal',
|
||||||
|
reverseButtons: true
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
// Jika user klik "Ya", submit form secara otomatis
|
||||||
|
document.getElementById('formGenerateSpp').submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Fungsi ini otomatis berjalan saat halaman selesai dimuat
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
|
||||||
|
// Menangkap Notifikasi Warning (Jika sudah pernah generate)
|
||||||
|
@if(session('warning'))
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Tidak Bisa Generate!',
|
||||||
|
text: "{{ session('warning') }}",
|
||||||
|
icon: 'warning',
|
||||||
|
confirmButtonColor: '#f59e0b',
|
||||||
|
confirmButtonText: 'Oke, Mengerti'
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
|
||||||
|
// Menangkap Notifikasi Sukses (Jika generate berhasil)
|
||||||
|
@if(session('success'))
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Berhasil!',
|
||||||
|
text: "{{ session('success') }}",
|
||||||
|
icon: 'success',
|
||||||
|
confirmButtonColor: '#10b981',
|
||||||
|
confirmButtonText: 'Sip!'
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
|
||||||
|
// Menangkap Notifikasi Error (Jika ada kegagalan sistem database)
|
||||||
|
@if(session('error'))
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Gagal!',
|
||||||
|
text: "{{ session('error') }}",
|
||||||
|
icon: 'error',
|
||||||
|
confirmButtonColor: '#ef4444',
|
||||||
|
confirmButtonText: 'Tutup'
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue