This commit is contained in:
SitiAfiah 2026-05-04 00:43:39 +07:00
commit 7027bdd847
23 changed files with 2633 additions and 84 deletions

View File

@ -0,0 +1,60 @@
<?php
namespace App\Exports;
use App\Models\Anggota;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
class AnggotaExport implements FromCollection, WithHeadings, WithMapping, ShouldAutoSize
{
public function collection()
{
// Ambil data Anggota dengan relasi kolat dan user (untuk email)
return Anggota::whereHas('role', function($query) {
$query->where('nama_role', 'Anggota');
})->with(['kolat', 'user'])->get();
}
public function headings(): array
{
return [
'No Induk',
'Nama Lengkap',
'Email',
'JK',
'Tempat Lahir',
'Tanggal Lahir',
'No HP',
'Kolat',
'Tingkatan',
'Jabatan',
'Tanggal Gabung',
'Status',
'Alamat',
'Catatan Medis'
];
}
public function map($anggota): array
{
return [
$anggota->no_induk,
$anggota->nama_lengkap,
$anggota->user->email ?? '-',
$anggota->jenis_kelamin,
$anggota->tempat_lahir,
$anggota->tgl_lahir,
$anggota->no_hp,
$anggota->kolat->nama_kolat ?? '-',
$anggota->tingkatan,
$anggota->jabatan,
$anggota->tgl_gabung,
$anggota->status,
$anggota->alamat,
$anggota->catatan_medis ?? '-'
];
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
class KasExport implements FromCollection, WithHeadings, WithMapping, ShouldAutoSize
{
protected $data;
// Kita terima data dari Controller lewat constructor
public function __construct($data)
{
$this->data = $data;
}
public function collection()
{
return $this->data;
}
public function headings(): array
{
return [
'Tanggal',
'Jenis',
'Kategori',
'Nominal',
'Keterangan',
'Saldo Akhir'
];
}
public function map($kas): array
{
return [
\Carbon\Carbon::parse($kas->tanggal)->format('d/m/Y'),
ucfirst($kas->jenis),
$kas->kategori,
$kas->nominal,
$kas->keterangan ?? '-',
$kas->saldo_akhir
];
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
class PresensiExport implements FromCollection, WithHeadings, WithMapping, ShouldAutoSize
{
protected $data;
public function __construct($data)
{
$this->data = $data;
}
public function collection()
{
return $this->data;
}
public function headings(): array
{
return [
'No',
'Nama Anggota',
'Kolat',
'Tanggal Latihan',
'Jam',
'Pelatih (Jadwal)',
'Status Kehadiran',
'Waktu Absen',
'Verifikator',
'Keterangan'
];
}
public function map($p): array
{
static $no = 0;
$no++;
return [
$no,
$p->anggota->nama_lengkap ?? '-',
$p->jadwal->kolat->nama_kolat ?? '-',
\Carbon\Carbon::parse($p->jadwal->tanggal)->format('d/m/Y'),
($p->jadwal->jam_mulai ?? '-') . ' - ' . ($p->jadwal->jam_selesai ?? '-'),
$p->jadwal->pelatih->nama_lengkap ?? '-',
$p->status,
$p->waktu_presensi ? \Carbon\Carbon::parse($p->waktu_presensi)->format('H:i') . ' WIB' : '-',
$p->pelatihVerifikator->nama_lengkap ?? 'Otomatis/Sistem',
$p->keterangan ?? '-'
];
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
class SppExport implements FromCollection, WithHeadings, WithMapping, ShouldAutoSize
{
protected $data;
public function __construct($data)
{
$this->data = $data;
}
public function collection()
{
return $this->data;
}
public function headings(): array
{
return [
'Nama Anggota',
'Kolat',
'Bulan',
'Tahun',
'Nominal (Rp)',
'Jatuh Tempo',
'Status',
'Keterangan'
];
}
public function map($spp): array
{
return [
$spp->anggota->nama_lengkap ?? '-', // Menggunakan nama_lengkap sesuai model Anggota
$spp->kolat->nama_kolat ?? '-',
$spp->bulan,
$spp->tahun,
$spp->nominal,
\Carbon\Carbon::parse($spp->jatuh_tempo)->format('d/m/Y'),
strtoupper(str_replace('_', ' ', $spp->status)), // Misal: "belum_bayar" jadi "BELUM BAYAR"
$spp->keterangan ?? '-'
];
}
}

View File

@ -2,14 +2,17 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Exports\AnggotaExport;
use App\Models\Anggota; use App\Models\Anggota;
use App\Models\Kolat; // Import model Kolat use App\Models\Kolat; // Import model Kolat
use App\Models\Role; use App\Models\Role;
use App\Models\User; use App\Models\User;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;
class AnggotaController extends Controller class AnggotaController extends Controller
{ {
@ -153,4 +156,25 @@ public function update(Request $request, $id)
} }
} }
public function exportExcel()
{
return Excel::download(new AnggotaExport, 'Data_Anggota_TapakMP.xlsx');
}
public function exportPdf()
{
$data_anggota = Anggota::whereHas('role', function($query) {
$query->where('nama_role', 'Anggota');
})->with(['kolat', 'user'])->get();
// Menggunakan view khusus PDF
$pdf = Pdf::loadView('anggota.export_pdf', compact('data_anggota'));
// Karena kolomnya banyak, set ke Landscape agar tidak berdesakan
$pdf->setPaper('a4', 'potrait');
return $pdf->download('Laporan_Anggota_TapakMP.pdf');
}
} }

View File

@ -2,9 +2,11 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Exports\KasExport;
use App\Models\Kas; use App\Models\Kas;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Carbon\Carbon; use Maatwebsite\Excel\Facades\Excel;
class KasController extends Controller class KasController extends Controller
{ {
@ -109,7 +111,7 @@ public function update(Request $request, $id)
'kategori' => $request->kategori, 'kategori' => $request->kategori,
'nominal' => $request->nominal, 'nominal' => $request->nominal,
'keterangan' => $request->keterangan, 'keterangan' => $request->keterangan,
'saldo_akhir' => $saldo_akhir_baru 'saldo_akhir' => $saldo_akhir_baru,
]); ]);
// Catatan: Idealnya setelah edit, semua baris setelahnya juga diupdate saldonya. // Catatan: Idealnya setelah edit, semua baris setelahnya juga diupdate saldonya.
@ -117,4 +119,43 @@ public function update(Request $request, $id)
return redirect()->back()->with('success', 'Transaksi berhasil diperbarui!'); return redirect()->back()->with('success', 'Transaksi berhasil diperbarui!');
} }
public function exportExcel(Request $request)
{
$query = Kas::query();
// Terapkan filter yang sama dengan index
if ($request->filled('jenis')) {
$query->where('jenis', $request->jenis);
}
if ($request->filled('dari') && $request->filled('sampai')) {
$query->whereBetween('tanggal', [$request->dari, $request->sampai]);
}
$data = $query->orderBy('tanggal', 'asc')->get();
return Excel::download(new KasExport($data), 'Laporan_Kas_TapakMP_'.date('Ymd').'.xlsx');
}
public function exportPdf(Request $request)
{
$query = Kas::query();
if ($request->filled('jenis')) {
$query->where('jenis', $request->jenis);
}
if ($request->filled('dari') && $request->filled('sampai')) {
$query->whereBetween('tanggal', [$request->dari, $request->sampai]);
}
$data_kas = $query->orderBy('tanggal', 'asc')->get();
// Hitung total untuk ringkasan di bawah tabel PDF
$total_masuk = $data_kas->where('jenis', 'masuk')->sum('nominal');
$total_keluar = $data_kas->where('jenis', 'keluar')->sum('nominal');
$pdf = Pdf::loadView('kas.export_pdf', compact('data_kas', 'total_masuk', 'total_keluar'));
return $pdf->download('Laporan_Kas_TapakMP_'.date('Ymd').'.pdf');
}
} }

View File

@ -0,0 +1,132 @@
<?php
namespace App\Http\Controllers;
use App\Exports\PresensiExport;
use App\Models\Anggota;
use App\Models\Kas;
use App\Models\Kolat;
use App\Models\Presensi;
use App\Models\Spp;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
class LaporanController extends Controller
{
// Halaman Laporan Anggota
public function anggota(Request $request)
{
$data_kolat = Kolat::all();
$query = Anggota::query();
if ($request->filled('kolat_id')) {
$query->where('kolat_id', $request->kolat_id);
}
if ($request->filled('status')) {
$query->where('status', $request->status);
}
$data_anggota = $query->with('kolat')->get();
return view('laporan.anggota', compact('data_anggota', 'data_kolat'));
}
// Halaman Laporan Keuangan (Kas)
public function kas(Request $request)
{
$query = Kas::query();
if ($request->filled('dari') && $request->filled('sampai')) {
$query->whereBetween('tanggal', [$request->dari, $request->sampai]);
}
$data_kas = $query->orderBy('tanggal', 'asc')->get();
return view('laporan.kas', compact('data_kas'));
}
// Halaman Laporan SPP
public function spp(Request $request)
{
// 1. Ambil semua Kolat untuk isi Dropdown Filter
$data_kolat = Kolat::all();
$query = Spp::with(['anggota', 'kolat']);
// 2. Logika Filter Kolat
if ($request->filled('kolat_id')) {
$query->where('kolat_id', $request->kolat_id);
}
// 3. Filter lainnya
if ($request->filled('bulan')) $query->where('bulan', $request->bulan);
if ($request->filled('tahun')) $query->where('tahun', $request->tahun);
if ($request->filled('status')) $query->where('status', $request->status);
$data_spp = $query->get();
return view('laporan.spp', compact('data_spp', 'data_kolat'));
}
public function presensi(Request $request)
{
$data_kolat = \App\Models\Kolat::all();
$query = Presensi::with(['anggota', 'jadwal.kolat', 'jadwal.pelatih', 'pelatihVerifikator']);
// Filter Kolat
if ($request->filled('kolat_id')) {
$query->whereHas('jadwal', function($q) use ($request) {
$q->where('kolat_id', $request->kolat_id);
});
}
// Filter Tanggal
if ($request->filled('dari') && $request->filled('sampai')) {
$query->whereHas('jadwal', function($q) use ($request) {
$q->whereBetween('tanggal', [$request->dari, $request->sampai]);
});
}
// Filter Status
if ($request->filled('status')) {
$query->where('status', $request->status);
}
$data_presensi = $query->orderBy('created_at', 'desc')->get();
return view('laporan.presensi', compact('data_presensi', 'data_kolat'));
}
public function presensiExcel(Request $request)
{
// Logika query yang sama dengan di atas
$query = Presensi::with(['anggota', 'jadwal.kolat', 'jadwal.pelatih', 'pelatihVerifikator']);
if ($request->filled('kolat_id')) {
$query->whereHas('jadwal', function($q) use ($request) { $q->where('kolat_id', $request->kolat_id); });
}
if ($request->filled('dari') && $request->filled('sampai')) {
$query->whereHas('jadwal', function($q) use ($request) { $q->whereBetween('tanggal', [$request->dari, $request->sampai]); });
}
$data = $query->get();
return Excel::download(new PresensiExport($data), 'Laporan_Presensi_TapakMP_' . date('Ymd') . '.xlsx');
}
public function presensiPdf(Request $request)
{
$query = Presensi::with(['anggota', 'jadwal.kolat', 'jadwal.pelatih', 'pelatihVerifikator']);
if ($request->filled('kolat_id')) {
$query->whereHas('jadwal', function($q) use ($request) { $q->where('kolat_id', $request->kolat_id); });
}
if ($request->filled('dari') && $request->filled('sampai')) {
$query->whereHas('jadwal', function($q) use ($request) { $q->whereBetween('tanggal', [$request->dari, $request->sampai]); });
}
$data_presensi = $query->get();
$pdf = Pdf::loadView('laporan.presensi_pdf', compact('data_presensi'));
$pdf->setPaper('a4', 'landscape');
return $pdf->download('Laporan_Presensi_TapakMP_' . date('Ymd') . '.pdf');
}
}

View File

@ -2,12 +2,15 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Exports\SppExport;
use App\Models\Anggota; use App\Models\Anggota;
use App\Models\Kas; use App\Models\Kas;
use App\Models\Spp; use App\Models\Spp;
use Barryvdh\DomPDF\Facade\Pdf;
use Carbon\Carbon;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Carbon\Carbon; use Maatwebsite\Excel\Facades\Excel;
class SppController extends Controller class SppController extends Controller
{ {
@ -39,7 +42,7 @@ public function index(Request $request)
'lunas' => Spp::where('status', 'lunas')->count(), 'lunas' => Spp::where('status', 'lunas')->count(),
'pending' => Spp::where('status', 'pending')->count(), 'pending' => Spp::where('status', 'pending')->count(),
'belum_bayar' => Spp::where('status', 'belum_bayar')->count(), 'belum_bayar' => Spp::where('status', 'belum_bayar')->count(),
'total_pemasukan' => Spp::where('status', 'lunas')->sum('nominal') 'total_pemasukan' => Spp::where('status', 'lunas')->sum('nominal'),
]; ];
return view('spp.pengurus.index', compact('data_spp', 'stats')); return view('spp.pengurus.index', compact('data_spp', 'stats'));
@ -49,6 +52,7 @@ public function create()
{ {
// Pastikan nama kolom di database adalah 'nama', bukan 'nama_lengkap' (sesuai diskusi sebelumnya) // Pastikan nama kolom di database adalah 'nama', bukan 'nama_lengkap' (sesuai diskusi sebelumnya)
$data_anggota = Anggota::orderBy('nama_lengkap', 'asc')->get(); $data_anggota = Anggota::orderBy('nama_lengkap', 'asc')->get();
return view('spp.pengurus.create', compact('data_anggota')); return view('spp.pengurus.create', compact('data_anggota'));
} }
@ -100,20 +104,22 @@ public function bayar(Request $request, $id)
'jenis' => 'masuk', 'jenis' => 'masuk',
'kategori' => 'SPP', 'kategori' => 'SPP',
'nominal' => $spp->nominal, 'nominal' => $spp->nominal,
'keterangan' => "Bayar SPP " . $spp->anggota->nama . " - " . $spp->bulan . " " . $spp->tahun, 'keterangan' => 'Bayar SPP '.$spp->anggota->nama.' - '.$spp->bulan.' '.$spp->tahun,
'saldo_akhir' => $saldo_baru 'saldo_akhir' => $saldo_baru,
]); ]);
$spp->update([ $spp->update([
'status' => 'lunas', 'status' => 'lunas',
'tanggal_bayar' => now(), 'tanggal_bayar' => now(),
'kas_id' => $kas->id 'kas_id' => $kas->id,
]); ]);
DB::commit(); DB::commit();
return redirect()->back()->with('success', 'Pembayaran SPP berhasil dicatat!'); return redirect()->back()->with('success', 'Pembayaran SPP berhasil dicatat!');
} catch (\Exception $e) { } catch (\Exception $e) {
DB::rollback(); DB::rollback();
return redirect()->back()->with('error', 'Terjadi kesalahan: '.$e->getMessage()); return redirect()->back()->with('error', 'Terjadi kesalahan: '.$e->getMessage());
} }
} }
@ -147,10 +153,64 @@ public function generateTagihan(Request $request)
} }
} }
DB::commit(); DB::commit();
return redirect()->route('spp.index')->with('success', "Tagihan berhasil dibuat!");
return redirect()->route('spp.index')->with('success', 'Tagihan berhasil dibuat!');
} catch (\Exception $e) { } catch (\Exception $e) {
DB::rollback(); DB::rollback();
return redirect()->back()->with('error', 'Gagal: '.$e->getMessage()); return redirect()->back()->with('error', 'Gagal: '.$e->getMessage());
} }
} }
public function exportExcel(Request $request)
{
$query = Spp::with(['anggota', 'kolat']);
// Terapkan filter yang sama dengan index
if ($request->filled('status')) {
$query->where('status', $request->status);
}
if ($request->filled('bulan')) {
$query->where('bulan', $request->bulan);
}
if ($request->filled('tahun')) {
$query->where('tahun', $request->tahun);
}
if ($request->filled('cari')) {
$query->whereHas('anggota', function ($q) use ($request) {
$q->where('nama_lengkap', 'like', '%'.$request->cari.'%');
});
}
$data = $query->orderBy('tahun', 'desc')->orderBy('bulan', 'desc')->get();
return Excel::download(new SppExport($data), 'Laporan_SPP_TapakMP_'.date('Ymd').'.xlsx');
}
public function exportPdf(Request $request)
{
$query = Spp::with(['anggota', 'kolat']);
if ($request->filled('status')) {
$query->where('status', $request->status);
}
if ($request->filled('bulan')) {
$query->where('bulan', $request->bulan);
}
if ($request->filled('tahun')) {
$query->where('tahun', $request->tahun);
}
if ($request->filled('cari')) {
$query->whereHas('anggota', function ($q) use ($request) {
$q->where('nama_lengkap', 'like', '%'.$request->cari.'%');
});
}
$data_spp = $query->orderBy('tahun', 'desc')->orderBy('bulan', 'desc')->get();
$pdf = Pdf::loadView('spp.pengurus.export_pdf', compact('data_spp'));
$pdf->setPaper('a4', 'landscape'); // Landscape agar tabel lega
return $pdf->download('Laporan_SPP_TapakMP_'.date('Ymd').'.pdf');
}
} }

View File

@ -6,10 +6,12 @@
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.1", "php": "^8.1",
"barryvdh/laravel-dompdf": "^3.1",
"guzzlehttp/guzzle": "^7.2", "guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.10", "laravel/framework": "^10.10",
"laravel/sanctum": "^3.3", "laravel/sanctum": "^3.3",
"laravel/tinker": "^2.8", "laravel/tinker": "^2.8",
"maatwebsite/excel": "^3.1",
"simplesoftwareio/simple-qrcode": "^4.2" "simplesoftwareio/simple-qrcode": "^4.2"
}, },
"require-dev": { "require-dev": {

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@
<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">
<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 class="text-start"> <div class="text-start">
<h5 class="card-title mb-0 fw-bold text-dark">Daftar Anggota PPS Merpati Putih</h5> <h5 class="card-title mb-0 fw-bold text-dark">Daftar Anggota PPS Merpati Putih</h5>
<p class="text-muted small mb-0">Cabang Jember - Kelola informasi induk anggota.</p> <p class="text-muted small mb-0">Cabang Jember - Kelola informasi induk anggota.</p>
@ -26,6 +26,32 @@
style="border-radius: 12px;"> style="border-radius: 12px;">
<i class="icon-plus me-1"></i> Tambah Anggota <i class="icon-plus me-1"></i> Tambah Anggota
</a> </a>
</div> --}}
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-3">
<div class="text-start">
<h5 class="card-title mb-0 fw-bold text-dark">Daftar Anggota PPS Merpati Putih</h5>
<p class="text-muted small mb-0">Cabang Jember - Kelola informasi induk anggota.</p>
</div>
<div class="d-flex flex-wrap gap-2">
<a href="{{ route('anggota.export.excel') }}"
class="btn btn-success px-3 py-2 shadow-sm d-flex align-items-center"
style="border-radius: 12px; font-size: 14px;">
<i class="bi bi-file-earmark-excel me-2"></i> Excel
</a>
<a href="{{ route('anggota.export.pdf') }}"
class="btn btn-danger px-3 py-2 shadow-sm d-flex align-items-center"
style="border-radius: 12px; font-size: 14px;">
<i class="bi bi-file-earmark-pdf me-2"></i> PDF
</a>
<a href="{{ route('anggota.create') }}"
class="btn btn-primary px-4 py-2 shadow-sm d-flex align-items-center"
style="border-radius: 12px; font-size: 14px;">
<i class="icon-plus me-2"></i> Tambah Anggota
</a>
</div>
</div> </div>
<div class="table-responsive"> <div class="table-responsive">

View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: sans-serif; font-size: 10px; }
table { width: 100%; border-collapse: collapse; margin-top: 10px; }
th, td { border: 1px solid #000; padding: 5px; text-align: left; }
th { background-color: #f2f2f2; font-weight: bold; text-align: center; }
.title { text-align: center; font-size: 16px; font-weight: bold; margin-bottom: 5px; }
.subtitle { text-align: center; font-size: 12px; margin-bottom: 20px; }
</style>
</head>
<body>
<div class="title">DAFTAR ANGGOTA PPS MERPATI PUTIH</div>
<div class="subtitle">Cabang Jember - Laporan Data Induk Keanggotaan</div>
<table>
<thead>
<tr>
<th>No</th>
<th>No Induk</th>
<th>Nama Lengkap</th>
<th>JK</th>
<th>TTL</th>
<th>No HP</th>
<th>Kolat</th>
<th>Tingkatan</th>
<th>Jabatan</th>
<th>Status</th>
<th>Alamat</th>
</tr>
</thead>
<tbody>
@foreach($data_anggota as $key => $item)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $item->no_induk }}</td>
<td>{{ $item->nama_lengkap }}</td>
<td style="text-align:center">{{ $item->jenis_kelamin }}</td>
<td>{{ $item->tempat_lahir }}, {{ \Carbon\Carbon::parse($item->tgl_lahir)->format('d/m/Y') }}</td>
<td>{{ $item->no_hp }}</td>
<td>{{ $item->kolat->nama_kolat ?? '-' }}</td>
<td>{{ $item->tingkatan }}</td>
<td>{{ $item->jabatan }}</td>
<td>{{ $item->status }}</td>
<td>{{ $item->alamat }}</td>
</tr>
@endforeach
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: sans-serif; font-size: 11px; }
table { width: 100%; border-collapse: collapse; margin-top: 15px; }
th, td { border: 1px solid #000; padding: 6px; text-align: left; }
th { background-color: #f2f2f2; text-align: center; }
.text-right { text-align: right; }
.header { text-align: center; margin-bottom: 20px; }
</style>
</head>
<body>
<div class="header">
<h2>LAPORAN KAS PPS MERPATI PUTIH</h2>
<p>Cabang Jember | Periode: {{ request('dari') ?? 'Semua' }} s/d {{ request('sampai') ?? 'Sekarang' }}</p>
</div>
<table>
<thead>
<tr>
<th>No</th>
<th>Tanggal</th>
<th>Kategori / Keterangan</th>
<th>Masuk (Rp)</th>
<th>Keluar (Rp)</th>
<th>Saldo (Rp)</th>
</tr>
</thead>
<tbody>
@foreach($data_kas as $key => $item)
<tr>
<td style="text-align:center">{{ $key + 1 }}</td>
<td>{{ \Carbon\Carbon::parse($item->tanggal)->format('d/m/Y') }}</td>
<td>
<strong>{{ $item->kategori }}</strong><br>
<small>{{ $item->keterangan }}</small>
</td>
<td class="text-right">{{ $item->jenis == 'masuk' ? number_format($item->nominal, 0, ',', '.') : '-' }}</td>
<td class="text-right">{{ $item->jenis == 'keluar' ? number_format($item->nominal, 0, ',', '.') : '-' }}</td>
<td class="text-right">{{ number_format($item->saldo_akhir, 0, ',', '.') }}</td>
</tr>
@endforeach
</tbody>
<tfoot>
<tr style="background-color: #eee; font-weight: bold;">
<td colspan="3" style="text-align:center">TOTAL</td>
<td class="text-right">{{ number_format($total_masuk, 0, ',', '.') }}</td>
<td class="text-right">{{ number_format($total_keluar, 0, ',', '.') }}</td>
<td class="text-right">Rp {{ number_format($data_kas->last()->saldo_akhir ?? 0, 0, ',', '.') }}</td>
</tr>
</tfoot>
</table>
</body>
</html>

View File

@ -76,7 +76,7 @@
<div class="card-body p-4"> <div class="card-body p-4">
<!-- Header Tabel --> <!-- Header Tabel -->
<div class="d-flex justify-content-between align-items-center mb-4 text-start"> {{-- <div class="d-flex justify-content-between align-items-center mb-4 text-start">
<div class="text-start"> <div class="text-start">
<h5 class="card-title mb-0 fw-bold text-dark">Buku Kas Utama</h5> <h5 class="card-title mb-0 fw-bold text-dark">Buku Kas Utama</h5>
<p class="text-muted small mb-0">Cabang Jember - Histori seluruh arus kas.</p> <p class="text-muted small mb-0">Cabang Jember - Histori seluruh arus kas.</p>
@ -125,6 +125,61 @@
<i class="icon-plus me-1"></i> Catat Transaksi <i class="icon-plus me-1"></i> Catat Transaksi
</button> </button>
</div> </div>
</div> --}}
<div class="d-flex justify-content-between align-items-center mb-4 text-start flex-wrap gap-3">
<div class="text-start">
<h5 class="card-title mb-0 fw-bold text-dark">Buku Kas Utama</h5>
<p class="text-muted small mb-0">Cabang Jember - Histori seluruh arus kas.</p>
</div>
<div class="d-flex flex-wrap align-items-center gap-2">
<div class="dropdown">
<button class="btn btn-light border px-4 py-2 dropdown-toggle shadow-sm d-flex align-items-center"
type="button" id="filterDropdown" data-bs-toggle="dropdown"
aria-expanded="false" style="border-radius: 12px;">
<i class="icon-filter me-2"></i> Filter
</button>
<div class="dropdown-menu dropdown-menu-end p-4 shadow-lg border-0"
aria-labelledby="filterDropdown" style="width: 300px; border-radius: 20px;">
<form action="{{ route('kas.index') }}" method="GET">
<h6 class="fw-bold mb-3">Saring Transaksi</h6>
<div class="mb-3 text-start">
<label class="form-label small fw-bold">Jenis Kas</label>
<select name="jenis" class="form-select border-0 bg-light" style="border-radius: 10px;">
<option value="">Semua Jenis</option>
<option value="masuk" {{ request('jenis') == 'masuk' ? 'selected' : '' }}>Pemasukan</option>
<option value="keluar" {{ request('jenis') == 'keluar' ? 'selected' : '' }}>Pengeluaran</option>
</select>
</div>
<div class="mb-3 text-start">
<label class="form-label small fw-bold">Dari Tanggal</label>
<input type="date" name="dari" value="{{ request('dari') }}" class="form-control border-0 bg-light" style="border-radius: 10px;">
</div>
<div class="mb-3 text-start">
<label class="form-label small fw-bold">Sampai Tanggal</label>
<input type="date" name="sampai" value="{{ request('sampai') }}" class="form-control border-0 bg-light" style="border-radius: 10px;">
</div>
<div class="d-grid gap-2 mt-4">
<button type="submit" class="btn btn-primary shadow-sm" style="border-radius: 10px;">Terapkan</button>
<a href="{{ route('kas.index') }}" class="btn btn-link btn-sm text-decoration-none text-muted">Hapus Filter</a>
</div>
</form>
</div>
</div>
<a href="{{ route('kas.export.excel', request()->all()) }}" class="btn btn-success px-3 py-2 shadow-sm d-flex align-items-center" style="border-radius: 12px;">
<i class="bi bi-file-earmark-excel me-1"></i> Excel
</a>
<a href="{{ route('kas.export.pdf', request()->all()) }}" class="btn btn-danger px-3 py-2 shadow-sm d-flex align-items-center" style="border-radius: 12px;">
<i class="bi bi-file-earmark-pdf me-1"></i> PDF
</a>
<button type="button" class="btn btn-primary px-4 py-2 shadow-sm pulse-button d-flex align-items-center"
style="border-radius: 12px;" data-bs-toggle="modal" data-bs-target="#modalTambahKas">
<i class="icon-plus me-1"></i> Catat Transaksi
</button>
</div>
</div> </div>
<!-- Label Filter Aktif --> <!-- Label Filter Aktif -->

View File

@ -0,0 +1,146 @@
@extends('layout.app')
@section('content')
<div class="container-fluid py-4">
<div class="page-header mb-4 text-start">
<nav aria-label="breadcrumb">
<ol class="breadcrumb bg-transparent p-0 mb-2">
<li class="breadcrumb-item"><a href="#" class="text-muted text-decoration-none small">Home</a></li>
<li class="breadcrumb-item"><a href="#" class="text-muted text-decoration-none small">Laporan</a></li>
<li class="breadcrumb-item active text-primary fw-bold small" aria-current="page">Laporan Anggota</li>
</ol>
</nav>
<h3 class="fw-bold text-dark">Laporan Keanggotaan</h3>
<p class="text-muted small">Rekapitulasi dan filter data anggota Merpati Putih Cabang Jember.</p>
</div>
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
<div class="card-body p-4">
<form action="{{ route('laporan.anggota') }}" method="GET" class="row g-3 align-items-end">
<div class="col-md-4 text-start">
<label class="form-label small fw-bold">Pilih Kolat</label>
<select name="kolat_id" class="form-select border-0 bg-light" style="border-radius: 12px; padding: 12px 15px;">
<option value="">Semua Kolat</option>
@foreach($data_kolat as $kolat)
<option value="{{ $kolat->id }}" {{ request('kolat_id') == $kolat->id ? 'selected' : '' }}>{{ $kolat->nama_kolat }}</option>
@endforeach
</select>
</div>
<div class="col-md-4 text-start">
<label class="form-label small fw-bold">Status Anggota</label>
<select name="status" class="form-select border-0 bg-light" style="border-radius: 12px; padding: 12px 15px;">
<option value="">Semua Status</option>
<option value="Aktif" {{ request('status') == 'Aktif' ? 'selected' : '' }}>Aktif</option>
<option value="Non-Aktif" {{ request('status') == 'Non-Aktif' ? 'selected' : '' }}>Non-Aktif</option>
</select>
</div>
<div class="col-md-4">
<button type="submit" class="btn btn-primary px-4 shadow-sm w-100" style="border-radius: 12px; padding: 12px;">
<i class="icon-magnifier me-2"></i> Tampilkan Data
</button>
</div>
</form>
</div>
</div>
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
<div class="card-body p-4 text-start">
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-3">
<div class="text-start">
<h6 class="fw-bold mb-0 text-dark">Hasil Pencarian</h6>
<p class="text-muted small mb-0">Menampilkan {{ $data_anggota->count() }} data anggota.</p>
</div>
<div class="d-flex flex-wrap gap-2">
<a href="{{ route('anggota.export.excel', request()->all()) }}" class="btn btn-success px-3 py-2 shadow-sm d-flex align-items-center" style="border-radius: 12px; font-size: 14px;">
<i class="bi bi-file-earmark-excel me-2"></i> Excel
</a>
<a href="{{ route('anggota.export.pdf', request()->all()) }}" class="btn btn-danger px-3 py-2 shadow-sm d-flex align-items-center" style="border-radius: 12px; font-size: 14px;">
<i class="bi bi-file-earmark-pdf me-2"></i> PDF
</a>
</div>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle main-table">
<thead>
<tr>
<th width="60" class="text-center">No</th>
<th>Identitas Anggota</th>
<th class="text-center">Tingkatan & Kolat</th>
<th class="text-center">Status</th>
</tr>
</thead>
<tbody>
@forelse($data_anggota as $no => $item)
<tr>
<td class="text-muted small text-center">{{ $no + 1 }}</td>
<td>
<div class="fw-bold text-dark text-start ps-3">{{ $item->nama_lengkap }}</div>
<small class="text-muted text-start ps-3 d-block">ID: {{ $item->no_induk }}</small>
</td>
<td class="text-center">
<span class="badge bg-info-soft text-info px-3 py-2 rounded-pill">{{ $item->tingkatan }}</span>
<div class="small text-muted mt-2" style="font-size: 10px;">
Kolat {{ $item->kolat->nama_kolat ?? '-' }}
</div>
</td>
<td class="text-center">
<span class="badge rounded-pill {{ $item->status == 'Aktif' ? 'bg-success-soft text-success border-success' : 'bg-secondary-soft text-secondary border-secondary' }} px-3 py-2 border">
{{ $item->status }}
</span>
</td>
</tr>
@empty
<tr>
<td colspan="4" class="text-center py-5">
<i class="icon-folder-alt text-muted mb-3 d-block" style="font-size: 40px; opacity: 0.5;"></i>
<span class="text-muted small">Data tidak ditemukan. Silakan sesuaikan filter Anda.</span>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
<style>
.main-table thead th {
background-color: #f8faff;
padding: 18px 10px;
font-size: 0.75rem;
color: #8c98a5;
letter-spacing: 1px;
text-transform: uppercase;
border-bottom: 2px solid #edf2f9;
}
.main-table tbody td {
padding: 20px 10px;
border-bottom: 1px solid #f1f4f8;
color: #495057;
font-size: 0.9rem;
}
.bg-success-soft {
background-color: #e6fffa;
color: #38b2ac;
}
.bg-info-soft {
background-color: #e0f2fe;
color: #0ea5e9;
}
.bg-secondary-soft {
background-color: #f3f4f6;
color: #6b7280;
}
.shadow-xs {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
</style>
@endsection

View File

@ -0,0 +1,136 @@
@extends('layout.app')
@section('content')
<div class="container-fluid py-4 text-start">
<div class="page-header mb-4">
<nav aria-label="breadcrumb">
<ol class="breadcrumb bg-transparent p-0 mb-2">
<li class="breadcrumb-item"><a href="#" class="text-muted text-decoration-none small">Home</a></li>
<li class="breadcrumb-item"><a href="#" class="text-muted text-decoration-none small">Laporan</a></li>
<li class="breadcrumb-item active text-primary fw-bold small" aria-current="page">Laporan Kas</li>
</ol>
</nav>
<h3 class="fw-bold text-dark">Laporan Keuangan (Kas)</h3>
<p class="text-muted small">Rekapitulasi dan filter arus kas masuk dan keluar organisasi.</p>
</div>
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
<div class="card-body p-4">
<form action="{{ route('laporan.kas') }}" method="GET" class="row g-3 align-items-end">
<div class="col-md-4 text-start">
<label class="form-label small fw-bold">Dari Tanggal</label>
<input type="date" name="dari" value="{{ request('dari') }}" class="form-control border-0 bg-light" style="border-radius: 12px; padding: 12px 15px;">
</div>
<div class="col-md-4 text-start">
<label class="form-label small fw-bold">Sampai Tanggal</label>
<input type="date" name="sampai" value="{{ request('sampai') }}" class="form-control border-0 bg-light" style="border-radius: 12px; padding: 12px 15px;">
</div>
<div class="col-md-4 text-start">
<button type="submit" class="btn btn-primary px-4 shadow-sm w-100" style="border-radius: 12px; padding: 12px;">
<i class="icon-magnifier me-2"></i> Filter Laporan
</button>
</div>
</form>
</div>
</div>
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
<div class="card-body p-4">
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-3">
<div class="text-start">
<h6 class="fw-bold mb-0 text-dark">Rincian Transaksi Keuangan</h6>
<p class="text-muted small mb-0">Menampilkan {{ $data_kas->count() }} catatan transaksi.</p>
</div>
<div class="d-flex flex-wrap gap-2">
<a href="{{ route('kas.export.excel', request()->all()) }}" class="btn btn-success px-3 py-2 shadow-sm d-flex align-items-center" style="border-radius: 12px; font-size: 14px;">
<i class="bi bi-file-earmark-excel me-2"></i> Excel
</a>
<a href="{{ route('kas.export.pdf', request()->all()) }}" class="btn btn-danger px-3 py-2 shadow-sm d-flex align-items-center" style="border-radius: 12px; font-size: 14px;">
<i class="bi bi-file-earmark-pdf me-2"></i> PDF
</a>
</div>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle main-table">
<thead>
<tr>
<th width="50" class="text-center">No</th>
<th width="130">Tanggal</th>
<th>Kategori & Keterangan</th>
<th class="text-end">Masuk (Rp)</th>
<th class="text-end">Keluar (Rp)</th>
<th class="text-end">Saldo Akhir</th>
</tr>
</thead>
<tbody>
@forelse($data_kas as $no => $kas)
<tr>
<td class="text-muted small text-center">{{ $no + 1 }}</td>
<td>
<div class="fw-bold text-dark">{{ \Carbon\Carbon::parse($kas->tanggal)->format('d M Y') }}</div>
</td>
<td>
<span class="badge {{ $kas->jenis == 'masuk' ? 'bg-success-soft text-success border-success' : 'bg-danger-soft text-danger border-danger' }} border px-3 py-1 mb-1 rounded-pill" style="font-size: 10px;">
{{ strtoupper($kas->kategori) }}
</span>
<div class="small text-muted mt-1">{{ $kas->keterangan ?? 'Tanpa keterangan' }}</div>
</td>
<td class="text-end text-success fw-bold">
{{ $kas->jenis == 'masuk' ? '+ ' . number_format($kas->nominal, 0, ',', '.') : '-' }}
</td>
<td class="text-end text-danger fw-bold">
{{ $kas->jenis == 'keluar' ? '- ' . number_format($kas->nominal, 0, ',', '.') : '-' }}
</td>
<td class="text-end fw-bold text-dark">
{{ number_format($kas->saldo_akhir, 0, ',', '.') }}
</td>
</tr>
@empty
<tr>
<td colspan="6" class="text-center py-5">
<i class="icon-wallet text-muted mb-3 d-block" style="font-size: 40px; opacity: 0.5;"></i>
<span class="text-muted small">Data transaksi tidak ditemukan untuk periode ini.</span>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
<style>
.main-table thead th {
background-color: #f8faff;
padding: 18px 10px;
font-size: 0.75rem;
color: #8c98a5;
letter-spacing: 1px;
text-transform: uppercase;
border-bottom: 2px solid #edf2f9;
}
.main-table tbody td {
padding: 18px 10px;
border-bottom: 1px solid #f1f4f8;
color: #495057;
font-size: 0.9rem;
}
.bg-success-soft {
background-color: #e6fffa;
color: #38b2ac;
}
.bg-danger-soft {
background-color: #fef2f2;
color: #ef4444;
}
.shadow-xs {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
</style>
@endsection

View File

@ -0,0 +1,127 @@
@extends('layout.app')
@section('content')
<div class="container-fluid py-4 text-start">
<div class="page-header mb-4">
<nav aria-label="breadcrumb">
<ol class="breadcrumb bg-transparent p-0 mb-2">
<li class="breadcrumb-item"><a href="#" class="text-muted text-decoration-none small">Home</a></li>
<li class="breadcrumb-item"><a href="#" class="text-muted text-decoration-none small">Laporan</a></li>
<li class="breadcrumb-item active text-primary fw-bold small" aria-current="page">Laporan Presensi</li>
</ol>
</nav>
<h3 class="fw-bold text-dark">Laporan Kehadiran Latihan</h3>
<p class="text-muted small">Rekapitulasi absensi anggota untuk bahan evaluasi rapat tahunan.</p>
</div>
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
<div class="card-body p-4">
<form action="{{ route('laporan.presensi') }}" method="GET" class="row g-3 align-items-end">
<div class="col-md-3">
<label class="form-label small fw-bold">Kolat</label>
<select name="kolat_id" class="form-select border-0 bg-light" style="border-radius: 12px; padding: 10px 15px;">
<option value="">Semua Kolat</option>
@foreach($data_kolat as $k)
<option value="{{ $k->id }}" {{ request('kolat_id') == $k->id ? 'selected' : '' }}>{{ $k->nama_kolat }}</option>
@endforeach
</select>
</div>
<div class="col-md-2">
<label class="form-label small fw-bold">Dari</label>
<input type="date" name="dari" value="{{ request('dari') }}" class="form-control border-0 bg-light" style="border-radius: 12px; padding: 10px 15px;">
</div>
<div class="col-md-2">
<label class="form-label small fw-bold">Sampai</label>
<input type="date" name="sampai" value="{{ request('sampai') }}" class="form-control border-0 bg-light" style="border-radius: 12px; padding: 10px 15px;">
</div>
<div class="col-md-2">
<label class="form-label small fw-bold">Status</label>
<select name="status" class="form-select border-0 bg-light" style="border-radius: 12px; padding: 10px 15px;">
<option value="">Semua</option>
<option value="Hadir" {{ request('status') == 'Hadir' ? 'selected' : '' }}>Hadir</option>
<option value="Izin" {{ request('status') == 'Izin' ? 'selected' : '' }}>Izin</option>
<option value="Sakit" {{ request('status') == 'Sakit' ? 'selected' : '' }}>Sakit</option>
<option value="Alfa" {{ request('status') == 'Alfa' ? 'selected' : '' }}>Alfa</option>
</select>
</div>
<div class="col-md-3">
<button type="submit" class="btn btn-primary px-4 shadow-sm w-100" style="border-radius: 12px; padding: 10px;">
<i class="icon-magnifier me-2"></i> Tampilkan
</button>
</div>
</form>
</div>
</div>
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
<div class="card-body p-4">
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-3">
<div class="text-start">
<h6 class="fw-bold mb-0 text-dark">Data Kehadiran</h6>
<p class="text-muted small mb-0">Ditemukan {{ $data_presensi->count() }} catatan presensi.</p>
</div>
<div class="d-flex flex-wrap gap-2">
<a href="{{ route('laporan.presensi.excel', request()->all()) }}" class="btn btn-success px-3 py-2 shadow-sm d-flex align-items-center" style="border-radius: 12px; font-size: 14px;">
<i class="bi bi-file-earmark-excel me-2"></i> Excel
</a>
<a href="{{ route('laporan.presensi.pdf', request()->all()) }}" class="btn btn-danger px-3 py-2 shadow-sm d-flex align-items-center" style="border-radius: 12px; font-size: 14px;">
<i class="bi bi-file-earmark-pdf me-2"></i> PDF
</a>
</div>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle main-table">
<thead>
<tr>
<th width="50">No</th>
<th>Anggota</th>
<th>Jadwal & Kolat</th>
<th class="text-center">Status</th>
<th>Verifikator</th>
</tr>
</thead>
<tbody>
@forelse($data_presensi as $no => $p)
<tr>
<td class="text-center text-muted small">{{ $no + 1 }}</td>
<td>
<div class="fw-bold text-dark">{{ $p->anggota->nama_lengkap ?? '-' }}</div>
<small class="text-muted">Waktu: {{ $p->waktu_presensi ? \Carbon\Carbon::parse($p->waktu_presensi)->format('H:i') : '-' }} WIB</small>
</td>
<td>
<div class="fw-medium text-dark">{{ \Carbon\Carbon::parse($p->jadwal->tanggal)->format('d M Y') }}</div>
<div class="small text-muted">Kolat: {{ $p->jadwal->kolat->nama_kolat ?? '-' }}</div>
</td>
<td class="text-center">
@php
$color = ['Hadir'=>'success', 'Izin'=>'info', 'Sakit'=>'warning', 'Alfa'=>'danger'][$p->status] ?? 'secondary';
@endphp
<span class="badge bg-{{$color}}-soft text-{{$color}} border-{{$color}} border px-3 py-2 rounded-pill" style="font-size: 11px;">
{{ strtoupper($p->status) }}
</span>
</td>
<td>
<div class="small fw-bold text-dark">{{ $p->pelatihVerifikator->nama_lengkap ?? 'Sistem' }}</div>
<small class="text-muted" style="font-size: 10px;">{{ $p->is_verified ? 'Terverifikasi' : 'Pending' }}</small>
</td>
</tr>
@empty
<tr><td colspan="5" class="text-center py-5 text-muted">Tidak ada data presensi.</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
<style>
.main-table thead th { background-color: #f8faff; padding: 18px 10px; font-size: 0.75rem; color: #8c98a5; letter-spacing: 1px; text-transform: uppercase; border-bottom: 2px solid #edf2f9; }
.main-table tbody td { padding: 15px 10px; border-bottom: 1px solid #f1f4f8; color: #495057; font-size: 0.85rem; }
.bg-success-soft { background-color: #f0fdf4; color: #16a34a; }
.bg-info-soft { background-color: #eff6ff; color: #3b82f6; }
.bg-warning-soft { background-color: #fffbeb; color: #ca8a04; }
.bg-danger-soft { background-color: #fef2f2; color: #ef4444; }
</style>
@endsection

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: sans-serif; font-size: 10px; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { border: 1px solid #000; padding: 5px; text-align: left; }
th { background-color: #f2f2f2; }
.header { text-align: center; margin-bottom: 20px; }
</style>
</head>
<body>
<div class="header">
<h2>LAPORAN KEHADIRAN ANGGOTA PPS MERPATI PUTIH</h2>
<p>Cabang Jember | Tanggal Cetak: {{ date('d/m/Y') }}</p>
</div>
<table>
<thead>
<tr>
<th>No</th>
<th>Nama Anggota</th>
<th>Kolat</th>
<th>Tanggal Latihan</th>
<th>Pelatih</th>
<th>Status</th>
<th>Verifikator</th>
<th>Ket</th>
</tr>
</thead>
<tbody>
@foreach($data_presensi as $key => $p)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $p->anggota->nama_lengkap ?? '-' }}</td>
<td>{{ $p->jadwal->kolat->nama_kolat ?? '-' }}</td>
<td>{{ \Carbon\Carbon::parse($p->jadwal->tanggal)->format('d/m/Y') }}</td>
<td>{{ $p->jadwal->pelatih->nama_lengkap ?? '-' }}</td>
<td>{{ $p->status }}</td>
<td>{{ $p->pelatihVerifikator->nama_lengkap ?? 'Sistem' }}</td>
<td>{{ $p->keterangan ?? '-' }}</td>
</tr>
@endforeach
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,198 @@
@extends('layout.app')
@section('content')
<div class="container-fluid py-4 text-start">
<div class="page-header mb-4">
<nav aria-label="breadcrumb">
<ol class="breadcrumb bg-transparent p-0 mb-2">
<li class="breadcrumb-item"><a href="#" class="text-muted text-decoration-none small">Home</a></li>
<li class="breadcrumb-item"><a href="#" class="text-muted text-decoration-none small">Laporan</a></li>
<li class="breadcrumb-item active text-primary fw-bold small" aria-current="page">Laporan SPP</li>
</ol>
</nav>
<h3 class="fw-bold text-dark">Laporan Pembayaran SPP</h3>
<p class="text-muted small">Rekapitulasi status tagihan iuran bulanan anggota Cabang Jember.</p>
</div>
{{-- <div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
<div class="card-body p-4">
<form action="{{ route('laporan.spp') }}" method="GET" class="row g-3 align-items-end">
<div class="col-md-3 text-start">
<label class="form-label small fw-bold">Pilih Bulan</label>
<select name="bulan" class="form-select border-0 bg-light" style="border-radius: 12px; padding: 12px 15px;">
<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 text-start">
<label class="form-label small fw-bold">Tahun</label>
<input type="number" name="tahun" value="{{ request('tahun', date('Y')) }}" class="form-control border-0 bg-light" style="border-radius: 12px; padding: 12px 15px;">
</div>
<div class="col-md-3 text-start">
<label class="form-label small fw-bold">Status Tagihan</label>
<select name="status" class="form-select border-0 bg-light" style="border-radius: 12px; padding: 12px 15px;">
<option value="">Semua Status</option>
<option value="lunas" {{ request('status') == 'lunas' ? 'selected' : '' }}>Lunas</option>
<option value="belum_bayar" {{ request('status') == 'belum_bayar' ? 'selected' : '' }}>Belum Bayar</option>
</select>
</div>
<div class="col-md-3">
<button type="submit" class="btn btn-primary px-4 shadow-sm w-100" style="border-radius: 12px; padding: 12px;">
<i class="icon-magnifier me-2"></i> Filter Laporan
</button>
</div>
</form>
</div>
</div> --}}
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
<div class="card-body p-4">
<form action="{{ route('laporan.spp') }}" method="GET" class="row g-3 align-items-end">
<div class="col-md-3 text-start">
<label class="form-label small fw-bold">Pilih Kolat</label>
<select name="kolat_id" class="form-select border-0 bg-light" style="border-radius: 12px; padding: 10px 15px;">
<option value="">Semua Kolat</option>
@foreach($data_kolat as $kolat)
<option value="{{ $kolat->id }}" {{ request('kolat_id') == $kolat->id ? 'selected' : '' }}>
{{ $kolat->nama_kolat }}
</option>
@endforeach
</select>
</div>
<div class="col-md-2 text-start">
<label class="form-label small fw-bold">Bulan</label>
<select name="bulan" class="form-select border-0 bg-light" style="border-radius: 12px; padding: 10px 15px;">
<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-2 text-start">
<label class="form-label small fw-bold">Tahun</label>
<input type="number" name="tahun" value="{{ request('tahun', date('Y')) }}" class="form-control border-0 bg-light" style="border-radius: 12px; padding: 10px 15px;">
</div>
<div class="col-md-2 text-start">
<label class="form-label small fw-bold">Status</label>
<select name="status" class="form-select border-0 bg-light" style="border-radius: 12px; padding: 10px 15px;">
<option value="">Semua Status</option>
<option value="lunas" {{ request('status') == 'lunas' ? 'selected' : '' }}>Lunas</option>
<option value="belum_bayar" {{ request('status') == 'belum_bayar' ? 'selected' : '' }}>Belum Bayar</option>
</select>
</div>
<div class="col-md-3">
<button type="submit" class="btn btn-primary px-4 shadow-sm w-100" style="border-radius: 12px; padding: 10px;">
<i class="icon-magnifier me-2"></i> Tampilkan
</button>
</div>
</form>
</div>
</div>
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
<div class="card-body p-4">
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-3">
<div class="text-start">
<h6 class="fw-bold mb-0 text-dark">Rekap Pembayaran SPP</h6>
<p class="text-muted small mb-0">Ditemukan {{ $data_spp->count() }} data tagihan.</p>
</div>
<div class="d-flex flex-wrap gap-2">
<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: 12px; font-size: 14px;">
<i class="bi bi-file-earmark-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: 12px; font-size: 14px;">
<i class="bi bi-file-earmark-pdf me-2"></i> PDF
</a>
</div>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle main-table">
<thead>
<tr>
<th width="50" class="text-center">No</th>
<th>Identitas Anggota</th>
<th class="text-center">Periode Tagihan</th>
<th class="text-end">Nominal (Rp)</th>
<th class="text-center">Status</th>
</tr>
</thead>
<tbody>
@forelse($data_spp as $no => $spp)
<tr>
<td class="text-muted small text-center">{{ $no + 1 }}</td>
<td>
<div class="fw-bold text-dark text-start">{{ $spp->anggota->nama_lengkap ?? '-' }}</div>
<small class="text-muted text-start d-block mt-1" style="font-size: 11px;">Kolat: {{ $spp->kolat->nama_kolat ?? '-' }}</small>
</td>
<td class="text-center">
<span class="badge bg-light text-dark border px-3 py-2 rounded-pill">{{ $spp->bulan }} {{ $spp->tahun }}</span>
</td>
<td class="text-end fw-bold text-dark">
{{ number_format($spp->nominal, 0, ',', '.') }}
</td>
<td class="text-center">
@if($spp->status == 'lunas')
<span class="badge bg-success-soft text-success border-success border px-3 py-2 rounded-pill">
<i class="bi bi-check-circle me-1"></i> LUNAS
</span>
@else
<span class="badge bg-warning-soft text-warning border-warning border px-3 py-2 rounded-pill">
<i class="bi bi-clock-history me-1"></i> BELUM BAYAR
</span>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5" class="text-center py-5">
<i class="icon-docs text-muted mb-3 d-block" style="font-size: 40px; opacity: 0.5;"></i>
<span class="text-muted small">Data SPP tidak ditemukan untuk filter tersebut.</span>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
<style>
.main-table thead th {
background-color: #f8faff;
padding: 18px 10px;
font-size: 0.75rem;
color: #8c98a5;
letter-spacing: 1px;
text-transform: uppercase;
border-bottom: 2px solid #edf2f9;
}
.main-table tbody td {
padding: 18px 10px;
border-bottom: 1px solid #f1f4f8;
color: #495057;
font-size: 0.9rem;
}
.bg-success-soft {
background-color: #f0fdf4;
color: #16a34a;
}
.bg-warning-soft {
background-color: #fefce8;
color: #ca8a04;
}
.shadow-xs {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
</style>
@endsection

View File

@ -94,9 +94,9 @@
<i class="bi bi-file-earmark-bar-graph"></i><span>Laporan</span><i class="bi bi-chevron-down ms-auto"></i> <i class="bi bi-file-earmark-bar-graph"></i><span>Laporan</span><i class="bi bi-chevron-down ms-auto"></i>
</a> </a>
<ul id="laporan-nav" class="nav-content collapse" data-bs-parent="#sidebar-nav"> <ul id="laporan-nav" class="nav-content collapse" data-bs-parent="#sidebar-nav">
<li><a href="#"><i class="bi bi-circle"></i><span>Laporan Anggota</span></a></li> <li><a href="{{ route('laporan.anggota') }}"><i class="bi bi-circle"></i><span>Laporan Anggota</span></a></li>
<li><a href="#"><i class="bi bi-circle"></i><span>Laporan Keuangan</span></a></li> <li><a href="{{ route('laporan.kas') }}"><i class="bi bi-circle"></i><span>Laporan Keuangan</span></a></li>
<li><a href="#"><i class="bi bi-circle"></i><span>Laporan Presensi</span></a></li> <li><a href="{{ route('laporan.presensi') }}"><i class="bi bi-circle"></i><span>Laporan Presensi</span></a></li>
<li><a href="#"><i class="bi bi-circle"></i><span>Laporan Penilaian</span></a></li> <li><a href="#"><i class="bi bi-circle"></i><span>Laporan Penilaian</span></a></li>
</ul> </ul>
</li> </li>

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: sans-serif; font-size: 11px; }
table { width: 100%; border-collapse: collapse; margin-top: 15px; }
th, td { border: 1px solid #000; padding: 6px; text-align: left; }
th { background-color: #f2f2f2; text-align: center; }
.text-center { text-align: center; }
.text-right { text-align: right; }
.header { text-align: center; margin-bottom: 20px; }
.badge { padding: 2px 5px; border-radius: 3px; font-size: 9px; }
</style>
</head>
<body>
<div class="header">
<h2>LAPORAN TAGIHAN SPP ANGGOTA</h2>
<p>PPS Merpati Putih Cabang Jember | Tanggal Cetak: {{ date('d/m/Y') }}</p>
</div>
<table>
<thead>
<tr>
<th>No</th>
<th>Nama Anggota</th>
<th>Kolat</th>
<th>Periode</th>
<th>Nominal</th>
<th>Jatuh Tempo</th>
<th>Status</th>
</tr>
</thead>
<tbody>
@foreach($data_spp as $key => $item)
<tr>
<td class="text-center">{{ $key + 1 }}</td>
<td>{{ $item->anggota->nama_lengkap ?? '-' }}</td>
<td>{{ $item->kolat->nama_kolat ?? '-' }}</td>
<td class="text-center">{{ $item->bulan }} {{ $item->tahun }}</td>
<td class="text-right">Rp {{ number_format($item->nominal, 0, ',', '.') }}</td>
<td class="text-center">{{ \Carbon\Carbon::parse($item->jatuh_tempo)->format('d/m/Y') }}</td>
<td class="text-center">{{ strtoupper(str_replace('_', ' ', $item->status)) }}</td>
</tr>
@endforeach
</tbody>
</table>
</body>
</html>

View File

@ -3,7 +3,7 @@
@section('content') @section('content')
<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"> {{-- <div class="d-flex justify-content-between align-items-center mb-4">
<div> <div>
<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>
@ -24,6 +24,33 @@
<i class="fas fa-download me-1"></i> Export <i class="fas fa-download me-1"></i> Export
</button> </button>
</div> </div>
</div> --}}
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-3">
<div class="text-start">
<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>
</div>
<div class="d-flex flex-wrap gap-2">
<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>
<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>
<!-- Statistik Cards --> <!-- Statistik Cards -->

View File

@ -6,6 +6,7 @@
use App\Http\Controllers\JadwalController; use App\Http\Controllers\JadwalController;
use App\Http\Controllers\KasController; use App\Http\Controllers\KasController;
use App\Http\Controllers\KolatController; use App\Http\Controllers\KolatController;
use App\Http\Controllers\LaporanController;
use App\Http\Controllers\PelatihController; use App\Http\Controllers\PelatihController;
use App\Http\Controllers\PenilaianController; use App\Http\Controllers\PenilaianController;
use App\Http\Controllers\PresensiController; use App\Http\Controllers\PresensiController;
@ -60,6 +61,8 @@
Route::post('/anggota/simpan', [AnggotaController::class, 'store'])->name('anggota.store'); Route::post('/anggota/simpan', [AnggotaController::class, 'store'])->name('anggota.store');
Route::get('/anggota/{id}/edit', [AnggotaController::class, 'edit'])->name('anggota.edit'); Route::get('/anggota/{id}/edit', [AnggotaController::class, 'edit'])->name('anggota.edit');
Route::put('/anggota/{id}', [AnggotaController::class, 'update'])->name('anggota.update'); Route::put('/anggota/{id}', [AnggotaController::class, 'update'])->name('anggota.update');
Route::get('/anggota/export/excel', [AnggotaController::class, 'exportExcel'])->name('anggota.export.excel');
Route::get('/anggota/export/pdf', [AnggotaController::class, 'exportPdf'])->name('anggota.export.pdf');
// kolat // kolat
Route::get('/kolat', [KolatController::class, 'kolat'])->name('kolat.index'); Route::get('/kolat', [KolatController::class, 'kolat'])->name('kolat.index');
@ -150,4 +153,46 @@
// Halaman utama rekap jadwal (untuk pilih jadwal mana yang mau dicek) // Halaman utama rekap jadwal (untuk pilih jadwal mana yang mau dicek)
//Penialaian
Route::prefix('penilaian')->name('penilaian.')->group(function () {
Route::get('/', [PenilaianController::class, 'index'])->name('index');
// Hilangkan kata 'penilaian' di dalam sini karena sudah ada di prefix
Route::get('/create/{id}', [PenilaianController::class, 'create'])->name('create');
Route::post('/store', [PenilaianController::class, 'store'])->name('store');
Route::get('/penilaian/rekap/{id}', [PenilaianController::class, 'show'])->name('show');
});
//Kas
Route::prefix('kas')->name('kas.')->group(function () {
Route::get('/', [KasController::class, 'index'])->name('index');
Route::post('/store', [KasController::class, 'store'])->name('store');
Route::put('/update/{id}', [KasController::class, 'update'])->name('update');
Route::delete('/{id}', [KasController::class, 'destroy'])->name('destroy');
Route::get('/export/excel', [KasController::class, 'exportExcel'])->name('export.excel');
Route::get('/export/pdf', [KasController::class, 'exportPdf'])->name('export.pdf');
});
// Group SPP
Route::prefix('spp')->name('spp.')->group(function () {
Route::get('/', [SppController::class, 'index'])->name('index');
Route::get('/create', [SppController::class, 'create'])->name('create');
Route::post('/store', [SppController::class, 'store'])->name('store');
Route::post('/bayar/{id}', [SppController::class, 'bayar'])->name('bayar');
Route::post('/generate', [SppController::class, 'generateTagihan'])->name('generate');
Route::get('/export/excel', [SppController::class, 'exportExcel'])->name('export.excel');
Route::get('/export/pdf', [SppController::class, 'exportPdf'])->name('export.pdf');
});
Route::prefix('laporan')->name('laporan.')->group(function () {
Route::get('/anggota', [LaporanController::class, 'anggota'])->name('anggota');
Route::get('/kas', [LaporanController::class, 'kas'])->name('kas');
Route::get('/spp', [LaporanController::class, 'spp'])->name('spp');
Route::get('/presensi', [LaporanController::class, 'presensi'])->name('presensi');
Route::get('/presensi/excel', [LaporanController::class, 'presensiExcel'])->name('presensi.excel');
Route::get('/presensi/pdf', [LaporanController::class, 'presensiPdf'])->name('presensi.pdf');
});
}); });