rekap dan dashboard
This commit is contained in:
parent
7027bdd847
commit
2ccaa0b4c5
|
|
@ -1,13 +1,78 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
use App\Models\Anggota;
|
||||||
use Illuminate\Http\Request;
|
use App\Models\Kolat;
|
||||||
|
use App\Models\Presensi;
|
||||||
|
use App\Models\Role;
|
||||||
|
use App\Models\Spp;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
// use Illuminate\Http\Request;
|
||||||
|
|
||||||
class DashboardController extends Controller
|
class DashboardController extends Controller
|
||||||
{
|
{
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
return view('dashboard.dashboard');
|
// --- 1. DATA STATISTIK UTAMA ---
|
||||||
|
$total_anggota_aktif = Anggota::where('status', 'Aktif')->count();
|
||||||
|
$total_kolat = Kolat::count();
|
||||||
|
|
||||||
|
// Ambil ID Role Pelatih secara dinamis
|
||||||
|
$rolePelatih = Role::where('nama_role', 'Pelatih')->first();
|
||||||
|
$total_pelatih = $rolePelatih ? Anggota::where('role_id', $rolePelatih->id)->count() : 0;
|
||||||
|
|
||||||
|
// Hitung SPP yang statusnya masih 'pending' atau 'belum_lunas'
|
||||||
|
$spp_pending = Spp::whereIn('status', ['pending', 'belum_lunas'])->count();
|
||||||
|
|
||||||
|
// --- 2. DATA GRAFIK LINE (TREN PRESENSI 7 HARI) ---
|
||||||
|
$grafikPresensi = Presensi::select(
|
||||||
|
DB::raw('DATE(created_at) as date'),
|
||||||
|
DB::raw('count(*) as total')
|
||||||
|
)
|
||||||
|
->where('status', 'hadir')
|
||||||
|
->where('created_at', '>=', now()->subDays(7))
|
||||||
|
->groupBy('date')
|
||||||
|
->orderBy('date', 'ASC')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
// --- 3. DATA GRAFIK DOUGHNUT (KOMPOSISI SABUK) ---
|
||||||
|
$persebaran_sabuk = Anggota::select('tingkatan', DB::raw('count(*) as total'))
|
||||||
|
->groupBy('tingkatan')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
// --- 4. DATA AKTIVITAS TERBARU (REAL DARI SPP) ---
|
||||||
|
$aktivitas = Spp::with('anggota')
|
||||||
|
->latest()
|
||||||
|
->take(5)
|
||||||
|
->get()
|
||||||
|
->map(function ($item) {
|
||||||
|
return [
|
||||||
|
'waktu' => $item->created_at->format('d/m/Y H:i'),
|
||||||
|
'kegiatan' => 'Pembayaran SPP: ' . ($item->keterangan ?? 'Iuran Bulanan'),
|
||||||
|
'user' => $item->anggota->nama_lengkap ?? 'System',
|
||||||
|
'status' => strtoupper($item->status),
|
||||||
|
'badge' => $item->status == 'lunas' ? 'success' : ($item->status == 'pending' ? 'warning' : 'danger')
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- 5. LOGIKA KELAYAKAN UNTUK RINGKASAN ---
|
||||||
|
$anggota = Anggota::with('presensi')->get();
|
||||||
|
$jumlah_layak_ujian = $anggota->filter(function($item) {
|
||||||
|
$total = $item->presensi->count();
|
||||||
|
$hadir = $item->presensi->where('status', 'hadir')->count();
|
||||||
|
$persen = $total > 0 ? ($hadir / $total) * 100 : 0;
|
||||||
|
return $persen >= 75;
|
||||||
|
})->count();
|
||||||
|
|
||||||
|
return view('dashboard.dashboard', compact(
|
||||||
|
'total_anggota_aktif',
|
||||||
|
'total_pelatih',
|
||||||
|
'total_kolat',
|
||||||
|
'spp_pending',
|
||||||
|
'grafikPresensi',
|
||||||
|
'persebaran_sabuk',
|
||||||
|
'aktivitas',
|
||||||
|
'jumlah_layak_ujian'
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
|
class ProfileController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Menampilkan form profil anggota yang sedang login.
|
||||||
|
*/
|
||||||
|
public function edit()
|
||||||
|
{
|
||||||
|
// Mengambil data anggota yang berelasi dengan User yang sedang login
|
||||||
|
$anggota = Auth::user()->anggota;
|
||||||
|
|
||||||
|
if (!$anggota) {
|
||||||
|
return redirect()->back()->with('error', 'Data profil tidak ditemukan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('profil.edit', compact('anggota'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menyimpan perubahan data yang diperbaiki anggota.
|
||||||
|
*/
|
||||||
|
public function update(Request $request)
|
||||||
|
{
|
||||||
|
$anggota = Auth::user()->anggota;
|
||||||
|
|
||||||
|
// Validasi data yang boleh diubah oleh anggota[cite: 1, 2]
|
||||||
|
$request->validate([
|
||||||
|
'nama_lengkap' => 'required|string|max:255',
|
||||||
|
'no_hp' => 'required|numeric',
|
||||||
|
'tempat_lahir' => 'required|string',
|
||||||
|
'tgl_lahir' => 'required|date',
|
||||||
|
'jenis_kelamin'=> 'required|in:L,P',
|
||||||
|
'alamat' => 'required|string',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Mengambil data input
|
||||||
|
$input = $request->only([
|
||||||
|
'nama_lengkap', 'no_hp', 'tempat_lahir', 'tgl_lahir', 'jenis_kelamin', 'alamat'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Proses update data ke database
|
||||||
|
$anggota->update($input);
|
||||||
|
|
||||||
|
// Update nama di tabel users agar sinkron
|
||||||
|
Auth::user()->update([
|
||||||
|
'name' => $request->nama_lengkap
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('profil.edit')->with('success', 'Profil Anda berhasil diperbarui!');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menyimpan perubahan password (FUNGSI BARU).
|
||||||
|
*/
|
||||||
|
public function updatePassword(Request $request)
|
||||||
|
{
|
||||||
|
// 1. Validasi input
|
||||||
|
// 'confirmed' akan otomatis mencocokkan input 'password' dengan 'password_confirmation'
|
||||||
|
$request->validate([
|
||||||
|
'current_password' => 'required',
|
||||||
|
'password' => 'required|min:8|confirmed',
|
||||||
|
], [
|
||||||
|
'password.confirmed' => 'Konfirmasi password baru tidak cocok!',
|
||||||
|
'password.min' => 'Password minimal harus 8 karakter!'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
// 2. Cek apakah password lama yang dimasukkan benar
|
||||||
|
if (!Hash::check($request->current_password, $user->password)) {
|
||||||
|
// Jika salah, kembalikan ke halaman profil dengan pesan error
|
||||||
|
return back()->withErrors(['current_password' => 'Password saat ini salah.']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Jika benar, update dengan password baru yang di-hash (enkripsi)
|
||||||
|
$user->update([
|
||||||
|
'password' => Hash::make($request->password)
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('profile.edit')->with('success', 'Password berhasil diperbarui!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Anggota;
|
||||||
|
use App\Models\Kolat;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class RekapController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request) // Tambahkan Request untuk filter
|
||||||
|
{
|
||||||
|
// 1. Ambil data Kolat untuk dropdown filter
|
||||||
|
$data_kolat = Kolat::all();
|
||||||
|
|
||||||
|
// 2. Query data anggota dengan filter
|
||||||
|
$query = Anggota::with(['presensi', 'spp', 'kolat']);
|
||||||
|
|
||||||
|
if ($request->kolat_id) {
|
||||||
|
$query->where('kolat_id', $request->kolat_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->status) {
|
||||||
|
$query->where('status', $request->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
$anggota = $query->get();
|
||||||
|
|
||||||
|
// 3. Transformasi data untuk Rekap
|
||||||
|
$dataRekap = $anggota->map(function ($item) {
|
||||||
|
// Logika Presensi
|
||||||
|
$totalPertemuan = $item->presensi->count();
|
||||||
|
$hadir = $item->presensi->where('status', 'hadir')->count();
|
||||||
|
$persentasePresensi = $totalPertemuan > 0 ? ($hadir / $totalPertemuan) * 100 : 0;
|
||||||
|
|
||||||
|
// Logika SPP
|
||||||
|
$punyaTunggakan = $item->spp->where('status', 'belum_lunas')->count() > 0;
|
||||||
|
|
||||||
|
// Logika Keaktifan
|
||||||
|
$statusAktif = ($totalPertemuan > 0 && $persentasePresensi > 0) ? 'Aktif' : 'Non-Aktif';
|
||||||
|
|
||||||
|
// Syarat Ujian (Presensi >= 75% dan SPP Lunas)
|
||||||
|
$layakUjian = ($persentasePresensi >= 75 && !$punyaTunggakan);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'nama' => $item->nama_lengkap, // Sesuaikan dengan kolom tabel Anda
|
||||||
|
'no_induk' => $item->no_induk,
|
||||||
|
'tingkatan' => $item->tingkatan,
|
||||||
|
'nama_kolat' => $item->kolat->nama_kolat ?? '-',
|
||||||
|
'status_aktif' => $statusAktif,
|
||||||
|
'persentase_presensi' => round($persentasePresensi, 1),
|
||||||
|
'status_spp' => $punyaTunggakan ? 'Ada Tunggakan' : 'Lunas',
|
||||||
|
'layak' => $layakUjian
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4. Kirim variabel yang dibutuhkan view
|
||||||
|
return view('rekap.index', compact('dataRekap', 'data_kolat'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -87,7 +87,6 @@ public function store(Request $request)
|
||||||
|
|
||||||
public function bayar(Request $request, $id)
|
public function bayar(Request $request, $id)
|
||||||
{
|
{
|
||||||
// Perbaikan: Pakai 'anggota' (singular) sesuai relasi model biasanya
|
|
||||||
$spp = Spp::with('anggota')->findOrFail($id);
|
$spp = Spp::with('anggota')->findOrFail($id);
|
||||||
|
|
||||||
if ($spp->status == 'lunas') {
|
if ($spp->status == 'lunas') {
|
||||||
|
|
@ -99,28 +98,32 @@ public function bayar(Request $request, $id)
|
||||||
$saldo_terakhir = Kas::saldoTerakhir() ?? 0;
|
$saldo_terakhir = Kas::saldoTerakhir() ?? 0;
|
||||||
$saldo_baru = $saldo_terakhir + $spp->nominal;
|
$saldo_baru = $saldo_terakhir + $spp->nominal;
|
||||||
|
|
||||||
|
// Buat Catatan Kas
|
||||||
$kas = Kas::create([
|
$kas = Kas::create([
|
||||||
'tanggal' => now(),
|
'tanggal' => now(),
|
||||||
'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_lengkap . ' - ' . $spp->bulan . ' ' . $spp->tahun,
|
||||||
'saldo_akhir' => $saldo_baru,
|
'saldo_akhir' => $saldo_baru,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Update Status SPP
|
||||||
$spp->update([
|
$spp->update([
|
||||||
'status' => 'lunas',
|
'status' => 'lunas',
|
||||||
'tanggal_bayar' => now(),
|
// Jangan timpa tanggal_bayar jika sudah diisi saat upload bukti TF
|
||||||
|
'tanggal_bayar' => $spp->tanggal_bayar ?? now(),
|
||||||
'kas_id' => $kas->id,
|
'kas_id' => $kas->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
|
|
||||||
return redirect()->back()->with('success', 'Pembayaran SPP berhasil dicatat!');
|
$pesan = $spp->status == 'pending' ? 'Pembayaran via transfer berhasil divalidasi!' : 'Pembayaran SPP tunai berhasil dicatat!';
|
||||||
|
return redirect()->back()->with('success', $pesan);
|
||||||
|
|
||||||
} 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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -213,4 +216,104 @@ public function exportPdf(Request $request)
|
||||||
|
|
||||||
return $pdf->download('Laporan_SPP_TapakMP_'.date('Ymd').'.pdf');
|
return $pdf->download('Laporan_SPP_TapakMP_'.date('Ymd').'.pdf');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public function indexAnggota()
|
||||||
|
// {
|
||||||
|
// // Sesuaikan cara pemanggilan ID anggota dengan struktur tabel User kamu
|
||||||
|
// // Contoh ini mengasumsikan di tabel users ada kolom 'anggota_id'
|
||||||
|
// $anggota_id = auth()->user()->anggota_id;
|
||||||
|
|
||||||
|
// $data_spp = Spp::where('anggota_id', $anggota_id)
|
||||||
|
// ->orderBy('tahun', 'desc')
|
||||||
|
// ->orderBy('bulan', 'desc')
|
||||||
|
// ->get();
|
||||||
|
|
||||||
|
// return view('spp.anggota.index', compact('data_spp'));
|
||||||
|
// }
|
||||||
|
|
||||||
|
public function indexAnggota()
|
||||||
|
{
|
||||||
|
// 1. Panggil relasi anggota dari user yang sedang login
|
||||||
|
$profil_anggota = auth()->user()->anggota;
|
||||||
|
|
||||||
|
// 2. Proteksi jika user belum punya profil anggota (mencegah error)
|
||||||
|
if (!$profil_anggota) {
|
||||||
|
$data_spp = collect(); // Kirim data kosong agar tidak error di view
|
||||||
|
return view('spp.anggota.index', compact('data_spp'))
|
||||||
|
->with('error', 'Profil anggota Anda belum terhubung. Silakan hubungi pengurus.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Jika aman, ambil ID anggotanya
|
||||||
|
$anggota_id = $profil_anggota->id;
|
||||||
|
|
||||||
|
// 4. Cari tagihan SPP
|
||||||
|
$data_spp = Spp::where('anggota_id', $anggota_id)
|
||||||
|
->orderBy('tahun', 'desc')
|
||||||
|
->orderBy('bulan', 'desc')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return view('spp.anggota.index', compact('data_spp'));
|
||||||
|
}
|
||||||
|
// 2. Menampilkan form upload bukti transfer
|
||||||
|
// public function formBayarAnggota($id)
|
||||||
|
// {
|
||||||
|
// $spp = Spp::findOrFail($id);
|
||||||
|
|
||||||
|
// // Keamanan: Pastikan yang diakses adalah tagihannya sendiri
|
||||||
|
// if ($spp->anggota_id != auth()->user()->anggota_id) {
|
||||||
|
// abort(403, 'Akses ditolak.');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return view('spp.anggota.bayar', compact('spp'));
|
||||||
|
// }
|
||||||
|
public function formBayarAnggota($id)
|
||||||
|
{
|
||||||
|
$spp = Spp::findOrFail($id);
|
||||||
|
$profil_anggota = auth()->user()->anggota;
|
||||||
|
|
||||||
|
// Proteksi 1: Pastikan user punya profil anggota
|
||||||
|
if (!$profil_anggota) {
|
||||||
|
abort(403, 'Profil anggota belum terhubung.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proteksi 2: Pastikan yang diakses adalah tagihannya sendiri
|
||||||
|
if ($spp->anggota_id != $profil_anggota->id) {
|
||||||
|
abort(403, 'Akses ditolak. Ini bukan tagihan Anda.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('spp.anggota.bayar', compact('spp'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Memproses upload gambar bukti TF
|
||||||
|
public function prosesBayarAnggota(Request $request, $id)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'bukti_pembayaran' => 'required|image|mimes:jpeg,png,jpg|max:2048', // Maksimal 2MB
|
||||||
|
], [
|
||||||
|
'bukti_pembayaran.required' => 'Bukti transfer wajib diunggah.',
|
||||||
|
'bukti_pembayaran.image' => 'File harus berupa gambar.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$spp = Spp::findOrFail($id);
|
||||||
|
|
||||||
|
if ($request->hasFile('bukti_pembayaran')) {
|
||||||
|
$file = $request->file('bukti_pembayaran');
|
||||||
|
// Membuat nama file unik
|
||||||
|
$nama_file = time() . "_" . $file->getClientOriginalName();
|
||||||
|
|
||||||
|
// Pindahkan gambar ke folder public/uploads/bukti_spp
|
||||||
|
$file->move(public_path('uploads/bukti_spp'), $nama_file);
|
||||||
|
|
||||||
|
// Update status menjadi pending dan simpan nama file
|
||||||
|
$spp->update([
|
||||||
|
'bukti_pembayaran' => $nama_file,
|
||||||
|
'status' => 'pending',
|
||||||
|
'tanggal_bayar' => now(), // Mencatat waktu upload
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('spp.anggota.index')->with('success', 'Bukti pembayaran berhasil diunggah! Menunggu konfirmasi pengurus.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->back()->with('error', 'Gagal mengunggah bukti pembayaran.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,5 +54,12 @@ public function user()
|
||||||
return $this->belongsTo(User::class, 'user_id');
|
return $this->belongsTo(User::class, 'user_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function presensi() {
|
||||||
|
return $this->hasMany(Presensi::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function spp() {
|
||||||
|
return $this->hasMany(Spp::class);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ class Spp extends Model
|
||||||
'nominal',
|
'nominal',
|
||||||
'status',
|
'status',
|
||||||
'jatuh_tempo',
|
'jatuh_tempo',
|
||||||
'keterangan'
|
'keterangan',
|
||||||
|
'bukti_pembayaran'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Relasi ke Anggota
|
// Relasi ke Anggota
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?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::table('spp', function (Blueprint $table) {
|
||||||
|
$table->string('bukti_pembayaran')->nullable()->after('status');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('spp', function (Blueprint $table) {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
|
|
@ -1,6 +1,11 @@
|
||||||
@extends('layout.app')
|
@extends('layout.app')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
@php
|
||||||
|
// Ambil nama role user yang login saat ini
|
||||||
|
$userRole = auth()->user()->role->nama_role ?? 'Anggota';
|
||||||
|
@endphp
|
||||||
|
|
||||||
<div class="container-fluid py-4">
|
<div class="container-fluid py-4">
|
||||||
<div class="page-header mb-4 text-start">
|
<div class="page-header mb-4 text-start">
|
||||||
<nav aria-label="breadcrumb">
|
<nav aria-label="breadcrumb">
|
||||||
|
|
@ -62,8 +67,7 @@
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">No. WhatsApp</label>
|
<label class="form-label fw-bold">No. WhatsApp</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
|
<input type="number" name="no_hp" class="form-control" value="{{ old('no_hp', $anggota->no_hp ?? '') }}" placeholder="081234567xxx" required>
|
||||||
<input type="number" name="no_hp" class="form-control" value="{{ old('no_hp', $anggota->no_hp ?? '') }}" placeholder="81234567xxx" required>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
|
@ -103,18 +107,31 @@
|
||||||
<label class="form-label fw-bold text-muted small">No Induk</label>
|
<label class="form-label fw-bold text-muted small">No Induk</label>
|
||||||
<input type="text" class="form-control bg-light fw-bold text-primary" value="{{ $anggota->no_induk ?? 'JB-XXX (Otomatis)' }}" readonly>
|
<input type="text" class="form-control bg-light fw-bold text-primary" value="{{ $anggota->no_induk ?? 'JB-XXX (Otomatis)' }}" readonly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label class="form-label fw-bold">Jabatan / Role</label>
|
<label class="form-label fw-bold">Jabatan / Role</label>
|
||||||
<select name="role_id" id="roleSelect" class="form-select border-primary" onchange="toggleSKFields()" required>
|
<select name="role_id" id="roleSelect" class="form-select border-primary" onchange="toggleSKFields()" required>
|
||||||
<option value="" disabled selected>-- Pilih Jabatan --</option>
|
<option value="" disabled selected>-- Pilih Jabatan --</option>
|
||||||
@foreach($data_role as $role)
|
@foreach($data_role as $role)
|
||||||
|
{{-- LOGIKA PENGAMANAN ROLE --}}
|
||||||
|
{{-- Jika yang login BUKAN pengurus, dan pilihan role saat ini BUKAN anggota, maka sembunyikan pilihannya --}}
|
||||||
|
@if($userRole != 'Pengurus' && strtolower($role->nama_role) != 'anggota')
|
||||||
|
@continue
|
||||||
|
@endif
|
||||||
|
|
||||||
<option value="{{ $role->id }}"
|
<option value="{{ $role->id }}"
|
||||||
{{ old('role_id', $anggota->role_id ?? '') == $role->id ? 'selected' : '' }}>
|
{{ old('role_id', $anggota->role_id ?? '') == $role->id ? 'selected' : '' }}>
|
||||||
{{ $role->nama_role }}
|
{{ $role->nama_role }}
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
{{-- Pesan informasi tambahan untuk Pelatih --}}
|
||||||
|
@if($userRole != 'Pengurus')
|
||||||
|
<small class="text-info mt-1 d-block"><i class="icon-info me-1"></i>Anda hanya dapat mendaftarkan Anggota biasa.</small>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label class="form-label fw-bold">Status Keanggotaan</label>
|
<label class="form-label fw-bold">Status Keanggotaan</label>
|
||||||
<select name="status" class="form-select" required>
|
<select name="status" class="form-select" required>
|
||||||
|
|
@ -123,6 +140,8 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- BOX SK HANYA DI-RENDER UTUH UNTUK PENGURUS AGAR LEBIH AMAN --}}
|
||||||
|
@if($userRole == 'Pengurus')
|
||||||
<div id="boxSK" class="col-12 mt-3 p-4 bg-light rounded-4 border border-dashed border-danger" style="display: none;">
|
<div id="boxSK" class="col-12 mt-3 p-4 bg-light rounded-4 border border-dashed border-danger" style="display: none;">
|
||||||
<h6 class="text-danger fw-bold mb-3"><i class="icon-file-text me-2"></i>Data Legalitas (Khusus Pelatih/Pengurus)</h6>
|
<h6 class="text-danger fw-bold mb-3"><i class="icon-file-text me-2"></i>Data Legalitas (Khusus Pelatih/Pengurus)</h6>
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
|
|
@ -140,6 +159,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="col-md-6 mt-4">
|
<div class="col-md-6 mt-4">
|
||||||
<label class="form-label fw-bold">Asal Kolat</label>
|
<label class="form-label fw-bold">Asal Kolat</label>
|
||||||
|
|
@ -189,7 +209,8 @@ function toggleSKFields() {
|
||||||
const roleSelect = document.getElementById('roleSelect');
|
const roleSelect = document.getElementById('roleSelect');
|
||||||
const boxSK = document.getElementById('boxSK');
|
const boxSK = document.getElementById('boxSK');
|
||||||
|
|
||||||
if (roleSelect.selectedIndex > 0) {
|
|
||||||
|
if (boxSK && roleSelect.selectedIndex > 0) {
|
||||||
const selectedText = roleSelect.options[roleSelect.selectedIndex].text.toLowerCase();
|
const selectedText = roleSelect.options[roleSelect.selectedIndex].text.toLowerCase();
|
||||||
|
|
||||||
// Tampilkan box SK jika role mengandung kata Pelatih atau Pengurus
|
// Tampilkan box SK jika role mengandung kata Pelatih atau Pengurus
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,22 @@
|
||||||
@extends('layout.app')
|
@extends('layout.app')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
@php
|
||||||
|
// Ambil nama role user yang login saat ini
|
||||||
|
$userRole = auth()->user()->role->nama_role ?? 'Anggota';
|
||||||
|
@endphp
|
||||||
|
|
||||||
<div class="container-fluid py-4">
|
<div class="container-fluid py-4">
|
||||||
@if ($errors->any())
|
@if ($errors->any())
|
||||||
<div class="alert alert-danger">
|
<div class="alert alert-danger border-0 shadow-sm mb-4" style="border-radius: 15px;">
|
||||||
<ul>
|
<div class="d-flex">
|
||||||
@foreach ($errors->all() as $error)
|
<i class="icon-alert-circle me-2 mt-1"></i>
|
||||||
<li>{{ $error }}</li>
|
<ul class="mb-0">
|
||||||
@endforeach
|
@foreach ($errors->all() as $error)
|
||||||
</ul>
|
<li class="small">{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
@ -43,6 +51,11 @@
|
||||||
<label class="form-label fw-bold">Role / Hak Akses</label>
|
<label class="form-label fw-bold">Role / Hak Akses</label>
|
||||||
<select name="role_id" class="form-select" required>
|
<select name="role_id" class="form-select" required>
|
||||||
@foreach($data_role as $role)
|
@foreach($data_role as $role)
|
||||||
|
{{-- LOGIKA PENGAMANAN ROLE --}}
|
||||||
|
@if($userRole != 'Pengurus' && strtolower($role->nama_role) != 'anggota')
|
||||||
|
@continue
|
||||||
|
@endif
|
||||||
|
|
||||||
<option value="{{ $role->id }}" {{ $anggota->role_id == $role->id ? 'selected' : '' }}>
|
<option value="{{ $role->id }}" {{ $anggota->role_id == $role->id ? 'selected' : '' }}>
|
||||||
{{ $role->nama_role }}
|
{{ $role->nama_role }}
|
||||||
</option>
|
</option>
|
||||||
|
|
@ -81,9 +94,17 @@
|
||||||
<label class="form-label fw-bold">Jabatan Khusus</label>
|
<label class="form-label fw-bold">Jabatan Khusus</label>
|
||||||
<select name="jabatan" id="jabatanSelect" class="form-select border-primary" onchange="toggleSKFields()" required>
|
<select name="jabatan" id="jabatanSelect" class="form-select border-primary" onchange="toggleSKFields()" required>
|
||||||
<option value="anggota" {{ $anggota->jabatan == 'anggota' ? 'selected' : '' }}>Anggota</option>
|
<option value="anggota" {{ $anggota->jabatan == 'anggota' ? 'selected' : '' }}>Anggota</option>
|
||||||
<option value="pelatih" {{ $anggota->jabatan == 'pelatih' ? 'selected' : '' }}>Pelatih</option>
|
|
||||||
<option value="pengurus" {{ $anggota->jabatan == 'pengurus' ? 'selected' : '' }}>Pengurus</option>
|
{{-- HANYA PENGURUS YANG BISA JADIKAN PELATIH/PENGURUS --}}
|
||||||
|
@if($userRole == 'Pengurus')
|
||||||
|
<option value="pelatih" {{ $anggota->jabatan == 'pelatih' ? 'selected' : '' }}>Pelatih</option>
|
||||||
|
<option value="pengurus" {{ $anggota->jabatan == 'pengurus' ? 'selected' : '' }}>Pengurus</option>
|
||||||
|
@endif
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
@if($userRole != 'Pengurus')
|
||||||
|
<small class="text-info mt-1 d-block"><i class="icon-info me-1"></i>Anda hanya dapat mengubah data Anggota biasa.</small>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label class="form-label fw-bold">Tingkatan</label>
|
<label class="form-label fw-bold">Tingkatan</label>
|
||||||
|
|
@ -97,6 +118,8 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- BOX SK HANYA DIBUKA UNTUK PENGURUS --}}
|
||||||
|
@if($userRole == 'Pengurus')
|
||||||
<div id="boxSK" class="col-12 mt-3 p-4 bg-light rounded-4 border border-dashed border-danger" style="display: none;">
|
<div id="boxSK" class="col-12 mt-3 p-4 bg-light rounded-4 border border-dashed border-danger" style="display: none;">
|
||||||
<h6 class="text-danger fw-bold mb-3">Data Legalitas SK</h6>
|
<h6 class="text-danger fw-bold mb-3">Data Legalitas SK</h6>
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
|
|
@ -113,11 +136,12 @@
|
||||||
<input type="date" name="masa_berlaku" class="form-control" value="{{ $anggota->masa_berlaku }}">
|
<input type="date" name="masa_berlaku" class="form-control" value="{{ $anggota->masa_berlaku }}">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label class="form-label small fw-bold">Upload Scan SK</label>
|
<label class="form-label small fw-bold">Upload Scan SK (Gambar)</label>
|
||||||
<input type="file" name="foto_sk" class="form-control">
|
<input type="file" name="foto_sk" class="form-control">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="col-md-12 mt-3">
|
<div class="col-md-12 mt-3">
|
||||||
<label class="form-label fw-bold">Asal Kolat</label>
|
<label class="form-label fw-bold">Asal Kolat</label>
|
||||||
|
|
@ -134,8 +158,8 @@
|
||||||
|
|
||||||
<div class="card-footer bg-light border-0 p-4" style="border-radius: 0 0 20px 20px;">
|
<div class="card-footer bg-light border-0 p-4" style="border-radius: 0 0 20px 20px;">
|
||||||
<div class="d-flex justify-content-end gap-3">
|
<div class="d-flex justify-content-end gap-3">
|
||||||
<a href="{{ route('anggota.anggota') }}" class="btn btn-outline-secondary px-4 fw-bold">Batal</a>
|
<a href="{{ route('anggota.anggota') }}" class="btn btn-outline-secondary px-4 fw-bold btn-cancel">Batal</a>
|
||||||
<button type="submit" class="btn btn-primary px-5 fw-bold shadow">Simpan Perubahan</button>
|
<button type="submit" class="btn btn-primary px-5 fw-bold btn-save shadow">Simpan Perubahan</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -146,10 +170,37 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function toggleSKFields() {
|
function toggleSKFields() {
|
||||||
const jabatan = document.getElementById('jabatanSelect').value;
|
const jabatanSelect = document.getElementById('jabatanSelect');
|
||||||
const boxSK = document.getElementById('boxSK');
|
const boxSK = document.getElementById('boxSK');
|
||||||
boxSK.style.display = (jabatan === 'pelatih' || jabatan === 'pengurus') ? 'block' : 'none';
|
|
||||||
|
|
||||||
|
if (boxSK && jabatanSelect) {
|
||||||
|
const jabatan = jabatanSelect.value;
|
||||||
|
boxSK.style.display = (jabatan === 'pelatih' || jabatan === 'pengurus') ? 'block' : 'none';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener("DOMContentLoaded", toggleSKFields);
|
document.addEventListener("DOMContentLoaded", toggleSKFields);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.form-control, .form-select {
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border: 1px solid #dce1e7;
|
||||||
|
}
|
||||||
|
.form-control:focus, .form-select:focus {
|
||||||
|
border-color: #0d6efd;
|
||||||
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.1);
|
||||||
|
}
|
||||||
|
.btn-save {
|
||||||
|
border-radius: 12px;
|
||||||
|
background: linear-gradient(45deg, #0d6efd, #004dc0);
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-cancel {
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
.bg-light { background-color: #f8f9fa !important; }
|
||||||
|
</style>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,212 @@
|
||||||
@extends('layout.app')
|
@extends('layout.app')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<p>Halo aku afi</p>
|
<div class="container-fluid py-4">
|
||||||
|
<!-- Header Section -->
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4 text-start">
|
||||||
|
<div>
|
||||||
|
<h3 class="fw-bold text-dark mb-1">Dashboard Pengurus</h3>
|
||||||
|
<p class="text-muted small">Ringkasan data Merpati Putih Cabang Jember • {{ date('d M Y') }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="badge bg-primary-soft text-primary px-3 py-2 rounded-pill">
|
||||||
|
<i class="fas fa-user-shield me-1"></i> Mode Administrator
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Statistik Cards -->
|
||||||
|
<div class="row g-3 mb-4">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card border-0 shadow-sm p-3" style="border-radius: 15px; border-left: 5px solid #0d6efd;">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="p-3 bg-primary bg-opacity-10 rounded-3 text-primary me-3">
|
||||||
|
<i class="fas fa-users fa-lg"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<small class="text-muted d-block">Anggota Aktif</small>
|
||||||
|
<h4 class="fw-bold mb-0">{{ $total_anggota_aktif }}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card border-0 shadow-sm p-3" style="border-radius: 15px; border-left: 5px solid #198754;">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="p-3 bg-success bg-opacity-10 rounded-3 text-success me-3">
|
||||||
|
<i class="fas fa-user-tie fa-lg"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<small class="text-muted d-block">Total Pelatih</small>
|
||||||
|
<h4 class="fw-bold mb-0">{{ $total_pelatih }}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card border-0 shadow-sm p-3" style="border-radius: 15px; border-left: 5px solid #0dcaf0;">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="p-3 bg-info bg-opacity-10 rounded-3 text-info me-3">
|
||||||
|
<i class="fas fa-university fa-lg"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<small class="text-muted d-block">Total Kolat</small>
|
||||||
|
<h4 class="fw-bold mb-0">{{ $total_kolat }}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card border-0 shadow-sm p-3" style="border-radius: 15px; border-left: 5px solid #ffc107;">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="p-3 bg-warning bg-opacity-10 rounded-3 text-warning me-3">
|
||||||
|
<i class="fas fa-file-invoice-dollar fa-lg"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<small class="text-muted d-block">SPP Tertunda</small>
|
||||||
|
<h4 class="fw-bold mb-0">{{ $spp_pending }}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Charts Row -->
|
||||||
|
<div class="row g-4 mb-4 text-start">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card border-0 shadow-sm p-4" style="border-radius: 20px;">
|
||||||
|
<h6 class="fw-bold text-dark mb-4"><i class="fas fa-chart-line me-2 text-primary"></i>Tren Kehadiran Latihan (7 Hari Terakhir)</h6>
|
||||||
|
<div style="height: 300px;">
|
||||||
|
<canvas id="chartPresensi"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card border-0 shadow-sm p-4" style="border-radius: 20px;">
|
||||||
|
<h6 class="fw-bold text-dark mb-4"><i class="fas fa-chart-pie me-2 text-primary"></i>Komposisi Tingkatan</h6>
|
||||||
|
<div style="height: 300px;">
|
||||||
|
<canvas id="chartSabuk"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Activities & Quick Actions Row -->
|
||||||
|
<div class="row g-4 text-start">
|
||||||
|
<!-- Aktivitas Terbaru -->
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card border-0 shadow-sm p-4" style="border-radius: 20px;">
|
||||||
|
<h6 class="fw-bold text-dark mb-4">Aktivitas Transaksi Terbaru</h6>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover align-middle">
|
||||||
|
<thead class="bg-light">
|
||||||
|
<tr class="small text-muted">
|
||||||
|
<th>WAKTU</th>
|
||||||
|
<th>KEGIATAN</th>
|
||||||
|
<th>USER</th>
|
||||||
|
<th>STATUS</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach($aktivitas as $act)
|
||||||
|
<tr>
|
||||||
|
<td class="small text-muted">{{ $act['waktu'] }}</td>
|
||||||
|
<td class="small fw-bold">{{ $act['kegiatan'] }}</td>
|
||||||
|
<td class="small">{{ $act['user'] }}</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-{{ $act['badge'] }}-soft text-{{ $act['badge'] }} px-2 py-1 rounded small">
|
||||||
|
{{ $act['status'] }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Quick Actions & Summary -->
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card border-0 shadow-sm p-4 h-100" style="border-radius: 20px; background: linear-gradient(135deg, #ffffff 0%, #f8faff 100%);">
|
||||||
|
<h6 class="fw-bold text-dark mb-4">Ringkasan Operasional</h6>
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<small class="text-muted d-block mb-2">Kelayakan Ujian Saat Ini</small>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<h3 class="fw-bold text-primary mb-0 me-2">{{ $jumlah_layak_ujian }}</h3>
|
||||||
|
<span class="text-muted small">Anggota Siap Ujian</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress mt-2" style="height: 5px;">
|
||||||
|
<div class="progress-bar bg-primary" style="width: {{ ($total_anggota_aktif > 0) ? ($jumlah_layak_ujian/$total_anggota_aktif)*100 : 0 }}%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-grid gap-2">
|
||||||
|
<a href="{{ route('rekap.index') }}" class="btn btn-primary py-3 rounded-3 shadow-sm">
|
||||||
|
<i class="fas fa-clipboard-check me-2"></i> Buka Rekap Kelayakan
|
||||||
|
</a>
|
||||||
|
<a href="{{ route('spp.index') }}" class="btn btn-outline-primary py-3 rounded-3">
|
||||||
|
<i class="fas fa-wallet me-2"></i> Verifikasi SPP
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Chart JS -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
<script>
|
||||||
|
// Grafik Presensi (Line Chart)
|
||||||
|
const ctxP = document.getElementById('chartPresensi').getContext('2d');
|
||||||
|
new Chart(ctxP, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: {!! json_encode($grafikPresensi->pluck('date')) !!},
|
||||||
|
datasets: [{
|
||||||
|
label: 'Jumlah Hadir',
|
||||||
|
data: {!! json_encode($grafikPresensi->pluck('total')) !!},
|
||||||
|
borderColor: '#0d6efd',
|
||||||
|
backgroundColor: 'rgba(13, 110, 253, 0.05)',
|
||||||
|
fill: true,
|
||||||
|
tension: 0.4,
|
||||||
|
borderWidth: 3
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
plugins: { legend: { display: false } },
|
||||||
|
scales: { y: { beginAtZero: true, grid: { display: false } }, x: { grid: { display: false } } }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Grafik Sabuk (Doughnut Chart)
|
||||||
|
const ctxS = document.getElementById('chartSabuk').getContext('2d');
|
||||||
|
new Chart(ctxS, {
|
||||||
|
type: 'doughnut',
|
||||||
|
data: {
|
||||||
|
labels: {!! json_encode($persebaran_sabuk->pluck('tingkatan')) !!},
|
||||||
|
datasets: [{
|
||||||
|
data: {!! json_encode($persebaran_sabuk->pluck('total')) !!},
|
||||||
|
backgroundColor: ['#0d6efd', '#0dcaf0', '#198754', '#ffc107', '#dc3545', '#6610f2']
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
cutout: '75%',
|
||||||
|
plugins: { legend: { position: 'bottom', labels: { usePointStyle: true, boxWidth: 10 } } }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.bg-primary-soft { background-color: #e7f0ff; }
|
||||||
|
.bg-success-soft { background-color: #e6fffa; }
|
||||||
|
.bg-warning-soft { background-color: #fffaf0; }
|
||||||
|
.bg-info-soft { background-color: #e0f2fe; }
|
||||||
|
.bg-danger-soft { background-color: #fff5f5; }
|
||||||
|
</style>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@
|
||||||
<aside id="sidebar" class="sidebar">
|
<aside id="sidebar" class="sidebar">
|
||||||
<ul class="sidebar-nav" id="sidebar-nav">
|
<ul class="sidebar-nav" id="sidebar-nav">
|
||||||
|
|
||||||
{{-- MENU DASHBOARD (Semua Role Bisa Akses) --}}
|
{{-- ======================================================== --}}
|
||||||
|
{{-- MENU DASHBOARD (Semua Role Bisa Akses) --}}
|
||||||
|
{{-- ======================================================== --}}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {{ request()->routeIs('dashboard') ? '' : 'collapsed' }}" href="{{ route('dashboard') }}">
|
<a class="nav-link {{ request()->routeIs('dashboard') ? '' : 'collapsed' }}" href="{{ route('dashboard') }}">
|
||||||
<i class="bi bi-grid"></i>
|
<i class="bi bi-grid"></i>
|
||||||
|
|
@ -14,11 +16,14 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{{-- MENU MANAJEMEN ANGGOTA (Hanya Pelatih & Pengurus) --}}
|
{{-- ======================================================== --}}
|
||||||
@if($userRole != 'Anggota')
|
{{-- MENU MANAJEMEN ANGGOTA (Hanya Pelatih & Pengurus) --}}
|
||||||
|
{{-- ======================================================== --}}
|
||||||
|
@if($userRole == 'Pengurus' || $userRole == 'Pelatih')
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {{ request()->routeIs(['pelatih.*', 'anggota.*', 'kolat.*']) ? '' : 'collapsed' }}"
|
<a class="nav-link {{ request()->routeIs(['pelatih.*', 'anggota.*', 'kolat.*']) ? '' : 'collapsed' }}"
|
||||||
data-bs-target="#anggota-nav" data-bs-toggle="collapse" href="#" aria-expanded="{{ request()->routeIs(['pelatih.*', 'anggota.*', 'kolat.*']) ? 'true' : 'false' }}">
|
data-bs-target="#anggota-nav" data-bs-toggle="collapse" href="#"
|
||||||
|
aria-expanded="{{ request()->routeIs(['pelatih.*', 'anggota.*', 'kolat.*']) ? 'true' : 'false' }}">
|
||||||
<i class="bi bi-people"></i><span>Manajemen Anggota</span><i class="bi bi-chevron-down ms-auto"></i>
|
<i class="bi bi-people"></i><span>Manajemen Anggota</span><i class="bi bi-chevron-down ms-auto"></i>
|
||||||
</a>
|
</a>
|
||||||
<ul id="anggota-nav" class="nav-content collapse {{ request()->routeIs(['pelatih.*', 'anggota.*', 'kolat.*']) ? 'show' : '' }}" data-bs-parent="#sidebar-nav">
|
<ul id="anggota-nav" class="nav-content collapse {{ request()->routeIs(['pelatih.*', 'anggota.*', 'kolat.*']) ? 'show' : '' }}" data-bs-parent="#sidebar-nav">
|
||||||
|
|
@ -41,88 +46,149 @@
|
||||||
</li>
|
</li>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{-- MENU MANAJEMEN LATIHAN (Semua Bisa Akses, Tapi Isinya Beda) --}}
|
{{-- ======================================================== --}}
|
||||||
|
{{-- MENU MANAJEMEN LATIHAN (Semua Bisa Akses) --}}
|
||||||
|
{{-- ======================================================== --}}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {{ request()->routeIs(['presensi.*', 'jadwal.*']) ? '' : 'collapsed' }}"
|
<a class="nav-link {{ request()->routeIs(['presensi.*', 'jadwal.*', 'penilaian.*']) ? '' : 'collapsed' }}"
|
||||||
data-bs-target="#latihan-nav" data-bs-toggle="collapse" href="#" aria-expanded="{{ request()->routeIs(['presensi.*', 'jadwal.*']) ? 'true' : 'false' }}">
|
data-bs-target="#latihan-nav" data-bs-toggle="collapse" href="#"
|
||||||
|
aria-expanded="{{ request()->routeIs(['presensi.*', 'jadwal.*', 'penilaian.*']) ? 'true' : 'false' }}">
|
||||||
<i class="bi bi-journal-check"></i><span>Manajemen Latihan</span><i class="bi bi-chevron-down ms-auto"></i>
|
<i class="bi bi-journal-check"></i><span>Manajemen Latihan</span><i class="bi bi-chevron-down ms-auto"></i>
|
||||||
</a>
|
</a>
|
||||||
<ul id="latihan-nav" class="nav-content collapse {{ request()->routeIs(['presensi.*', 'jadwal.*']) ? 'show' : '' }}" data-bs-parent="#sidebar-nav">
|
<ul id="latihan-nav" class="nav-content collapse {{ request()->routeIs(['presensi.*', 'jadwal.*', 'penilaian.*']) ? 'show' : '' }}" data-bs-parent="#sidebar-nav">
|
||||||
|
|
||||||
{{-- Jika Login Sebagai ANGGOTA --}}
|
{{-- SUB-MENU ANGGOTA --}}
|
||||||
@if($userRole == 'Anggota')
|
@if($userRole == 'Anggota')
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ route('presensi.anggota.index') }}" class="{{ request()->routeIs('presensi.anggota.*') ? 'active' : '' }}">
|
<a href="{{ route('presensi.anggota.index') }}" class="{{ request()->routeIs('presensi.anggota.*') ? 'active' : '' }}">
|
||||||
<i class="bi bi-circle"></i><span>Kehadiran Latihan</span>
|
<i class="bi bi-circle"></i><span>Kehadiran Latihan</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<!-- Link Penilaian masih manual (sesuaikan id pelatihnya nanti) -->
|
||||||
|
<li>
|
||||||
|
<a href="#" class="{{ request()->routeIs('penilaian.*') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-circle"></i><span>Isi Nilai Pelatih</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
{{-- Jika Login Sebagai PELATIH / PENGURUS --}}
|
{{-- SUB-MENU PELATIH & PENGURUS --}}
|
||||||
@else
|
@else
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ route('presensi.index') }}" class="{{ request()->routeIs('presensi.index', 'presensi.kehadiran') ? 'active' : '' }}">
|
<a href="{{ route('presensi.index') }}" class="{{ request()->routeIs('presensi.index', 'presensi.kehadiran') ? 'active' : '' }}">
|
||||||
<i class="bi bi-circle"></i><span>Presensi</span>
|
<i class="bi bi-circle"></i><span>Presensi Anggota</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ route('jadwal.index') }}" class="{{ request()->routeIs('jadwal.*') ? 'active' : '' }}">
|
<a href="{{ route('jadwal.index') }}" class="{{ request()->routeIs('jadwal.*') ? 'active' : '' }}">
|
||||||
<i class="bi bi-circle"></i><span>Jadwal & Pengumuman</span>
|
<i class="bi bi-circle"></i><span>Jadwal Latihan</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('penilaian.index') }}" class="{{ request()->routeIs('penilaian.*') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-circle"></i><span>Rekap Penilaian</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#"><i class="bi bi-circle"></i><span>Penilaian Pelatih</span></a></li>
|
|
||||||
@endif
|
@endif
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{{-- MENU TRANSAKSI (Semua Bisa Akses, Tapi Anggota Cuma Lihat SPP) --}}
|
{{-- ======================================================== --}}
|
||||||
|
{{-- MENU TRANSAKSI (Semua Akses, Isi Berbeda) --}}
|
||||||
|
{{-- ======================================================== --}}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link collapsed" data-bs-target="#transaksi-nav" data-bs-toggle="collapse" href="#">
|
<a class="nav-link {{ request()->routeIs(['kas.*', 'spp.*']) ? '' : 'collapsed' }}"
|
||||||
|
data-bs-target="#transaksi-nav" data-bs-toggle="collapse" href="#"
|
||||||
|
aria-expanded="{{ request()->routeIs(['kas.*', 'spp.*']) ? 'true' : 'false' }}">
|
||||||
<i class="bi bi-wallet2"></i><span>Transaksi</span><i class="bi bi-chevron-down ms-auto"></i>
|
<i class="bi bi-wallet2"></i><span>Transaksi</span><i class="bi bi-chevron-down ms-auto"></i>
|
||||||
</a>
|
</a>
|
||||||
<ul id="transaksi-nav" class="nav-content collapse" data-bs-parent="#sidebar-nav">
|
<ul id="transaksi-nav" class="nav-content collapse {{ request()->routeIs(['kas.*', 'spp.*']) ? 'show' : '' }}" data-bs-parent="#sidebar-nav">
|
||||||
@if($userRole != 'Anggota')
|
|
||||||
<li><a href="#"><i class="bi bi-circle"></i><span>Kas Cabang</span></a></li>
|
{{-- Kas Cabang HANYA Pengurus --}}
|
||||||
|
@if($userRole == 'Pengurus')
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('kas.index') }}" class="{{ request()->routeIs('kas.*') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-circle"></i><span>Kas Cabang</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
@endif
|
@endif
|
||||||
<li><a href="#"><i class="bi bi-circle"></i><span>SPP Anggota</span></a></li>
|
|
||||||
|
{{-- SPP --}}
|
||||||
|
<li>
|
||||||
|
@if($userRole == 'Anggota')
|
||||||
|
<a href="{{ route('spp.anggota.index') }}" class="{{ request()->routeIs('spp.anggota.*') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-circle"></i><span>Tagihan SPP Saya</span>
|
||||||
|
</a>
|
||||||
|
@else
|
||||||
|
<a href="{{ route('spp.index') }}" class="{{ request()->routeIs('spp.index', 'spp.create') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-circle"></i><span>Kelola SPP Anggota</span>
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{{-- MENU LAPORAN (Hanya Pelatih & Pengurus) --}}
|
{{-- ======================================================== --}}
|
||||||
@if($userRole != 'Anggota')
|
{{-- MENU LAPORAN (Hanya Pelatih & Pengurus) --}}
|
||||||
|
{{-- ======================================================== --}}
|
||||||
|
@if($userRole == 'Pengurus' || $userRole == 'Pelatih')
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link collapsed" data-bs-target="#laporan-nav" data-bs-toggle="collapse" href="#">
|
<a class="nav-link {{ request()->routeIs('laporan.*') ? '' : 'collapsed' }}"
|
||||||
|
data-bs-target="#laporan-nav" data-bs-toggle="collapse" href="#"
|
||||||
|
aria-expanded="{{ request()->routeIs('laporan.*') ? 'true' : 'false' }}">
|
||||||
<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 {{ request()->routeIs('laporan.*') ? 'show' : '' }}" data-bs-parent="#sidebar-nav">
|
||||||
<li><a href="{{ route('laporan.anggota') }}"><i class="bi bi-circle"></i><span>Laporan Anggota</span></a></li>
|
|
||||||
<li><a href="{{ route('laporan.kas') }}"><i class="bi bi-circle"></i><span>Laporan Keuangan</span></a></li>
|
{{-- Hanya Pengurus --}}
|
||||||
<li><a href="{{ route('laporan.presensi') }}"><i class="bi bi-circle"></i><span>Laporan Presensi</span></a></li>
|
@if($userRole == 'Pengurus')
|
||||||
<li><a href="#"><i class="bi bi-circle"></i><span>Laporan Penilaian</span></a></li>
|
<li>
|
||||||
|
<a href="{{ route('laporan.anggota') }}" class="{{ request()->routeIs('laporan.anggota') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-circle"></i><span>Laporan Anggota</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('laporan.kas') }}" class="{{ request()->routeIs('laporan.kas') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-circle"></i><span>Laporan Keuangan</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('laporan.spp') }}" class="{{ request()->routeIs('laporan.spp') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-circle"></i><span>Laporan SPP</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- Pengurus & Pelatih --}}
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('laporan.presensi') }}" class="{{ request()->routeIs('laporan.presensi') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-circle"></i><span>Laporan Presensi</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('rekap.index') }}" class="{{ request()->routeIs('rekap.index') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-circle"></i><span>Rekap Kelayakan Anggota</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{-- MENU AKUN (Semua Bisa Akses) --}}
|
{{-- ======================================================== --}}
|
||||||
<li class="nav-heading">Akun</li>
|
{{-- MENU AKUN (Semua Bisa Akses) --}}
|
||||||
|
{{-- ======================================================== --}}
|
||||||
|
<li class="nav-heading mt-3">Akun</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link collapsed" href="#"><i class="bi bi-person"></i><span>Profile</span></a>
|
<a class="nav-link collapsed" href="{{ route('profile.edit') }}">
|
||||||
|
<i class="bi bi-person"></i><span>Profile Saya</span>
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">@csrf</form>
|
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">@csrf</form>
|
||||||
<a class="nav-link collapsed" href="#" onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
<a class="nav-link collapsed text-danger" href="#" onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
||||||
<i class="bi bi-box-arrow-right"></i><span>Logout</span>
|
<i class="bi bi-box-arrow-right"></i><span>Logout</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
|
||||||
var bootstrapCollapseMenus = document.querySelectorAll('.nav-content.collapse.show');
|
|
||||||
bootstrapCollapseMenus.forEach(function (menuElement) {
|
|
||||||
new bootstrap.Collapse(menuElement, {
|
|
||||||
toggle: false
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@
|
||||||
});
|
});
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
// Popup jika gagal login atau akun non-aktif
|
// Popup jika gagal login manual (dilempar via with('error', '...'))
|
||||||
@if(session('error'))
|
@if(session('error'))
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
icon: 'warning',
|
icon: 'warning',
|
||||||
|
|
@ -142,6 +142,22 @@
|
||||||
confirmButtonColor: '#06163a'
|
confirmButtonColor: '#06163a'
|
||||||
});
|
});
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
// [TAMBAHAN BARU] Popup jika validasi gagal (Email/Password salah)
|
||||||
|
@if($errors->any())
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Login Gagal!',
|
||||||
|
html: `
|
||||||
|
<ul style="text-align: left; margin-bottom: 0;">
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
`,
|
||||||
|
confirmButtonColor: '#06163a'
|
||||||
|
});
|
||||||
|
@endif
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
@extends('layout.app')
|
@extends('layout.app')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
@php
|
||||||
|
// Ambil nama role user yang login saat ini
|
||||||
|
$userRole = auth()->user()->role->nama_role ?? 'Anggota';
|
||||||
|
@endphp
|
||||||
|
|
||||||
<div class="container-fluid py-4">
|
<div class="container-fluid py-4">
|
||||||
<div class="page-header mb-4 text-start">
|
<div class="page-header mb-4 text-start">
|
||||||
<nav aria-label="breadcrumb">
|
<nav aria-label="breadcrumb">
|
||||||
|
|
@ -22,11 +27,14 @@
|
||||||
<h5 class="card-title mb-0 fw-bold text-dark">Daftar Pelatih Aktif</h5>
|
<h5 class="card-title mb-0 fw-bold text-dark">Daftar Pelatih Aktif</h5>
|
||||||
<p class="text-muted small mb-0">Kelola sertifikasi dan masa berlaku SK Pelatih Cabang.</p>
|
<p class="text-muted small mb-0">Kelola sertifikasi dan masa berlaku SK Pelatih Cabang.</p>
|
||||||
</div>
|
</div>
|
||||||
<!-- Link ke halaman Upgrade -->
|
|
||||||
|
<!-- HANYA PENGURUS YANG BISA MELIHAT TOMBOL INI -->
|
||||||
|
@if($userRole == 'Pengurus')
|
||||||
<a href="{{ route('pelatih.upgrade') }}" class="btn btn-primary px-4 py-2 shadow-sm"
|
<a href="{{ route('pelatih.upgrade') }}" class="btn btn-primary px-4 py-2 shadow-sm"
|
||||||
style="border-radius: 12px;">
|
style="border-radius: 12px;">
|
||||||
<i class="icon-plus me-1"></i> Upgrade Anggota ke Pelatih
|
<i class="icon-plus me-1"></i> Upgrade Anggota ke Pelatih
|
||||||
</a>
|
</a>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
|
@ -38,7 +46,11 @@
|
||||||
<th>No. SK & Masa Berlaku</th>
|
<th>No. SK & Masa Berlaku</th>
|
||||||
<th>Kolat</th>
|
<th>Kolat</th>
|
||||||
<th>Status SK</th>
|
<th>Status SK</th>
|
||||||
|
|
||||||
|
<!-- KOLOM AKSI HANYA MUNCUL JIKA PENGURUS -->
|
||||||
|
@if($userRole == 'Pengurus')
|
||||||
<th>Aksi</th>
|
<th>Aksi</th>
|
||||||
|
@endif
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
@ -64,6 +76,9 @@
|
||||||
{{ !$isExpired ? 'Berlaku' : 'Expired' }}
|
{{ !$isExpired ? 'Berlaku' : 'Expired' }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
<!-- TOMBOL EDIT HANYA MUNCUL JIKA PENGURUS -->
|
||||||
|
@if($userRole == 'Pengurus')
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<div class="d-flex justify-content-center gap-2">
|
<div class="d-flex justify-content-center gap-2">
|
||||||
<a href="{{ route('pelatih.edit', $item->id) }}"
|
<a href="{{ route('pelatih.edit', $item->id) }}"
|
||||||
|
|
@ -72,6 +87,7 @@ class="btn btn-sm btn-action-edit fw-bold px-3 shadow-xs">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
@endif
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,238 @@
|
||||||
|
@extends('layout.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid py-4">
|
||||||
|
<!-- Header Profil (Dipercantik dengan Avatar) -->
|
||||||
|
<div class="row mb-4">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card shadow-sm border-0" style="border-radius: 20px; background: linear-gradient(135deg, #0d6efd 0%, #0a58ca 100%);">
|
||||||
|
<div class="card-body p-4 d-flex align-items-center position-relative overflow-hidden">
|
||||||
|
<!-- Elemen dekorasi background -->
|
||||||
|
<div class="position-absolute top-0 end-0 opacity-10 mt-n4 me-n4">
|
||||||
|
<i class="icon-shield" style="font-size: 150px; color: white;"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Foto Default Avatar -->
|
||||||
|
<div class="bg-white rounded-circle d-flex justify-content-center align-items-center shadow p-1 me-4" style="width: 80px; height: 80px; z-index: 1;">
|
||||||
|
<img src="https://ui-avatars.com/api/?name={{ urlencode($anggota->nama_lengkap) }}&background=e9ecef&color=0d6efd&size=80" alt="Avatar" class="rounded-circle" style="width: 100%; height: 100%;">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="z-index: 1;">
|
||||||
|
<h3 class="fw-bold text-white mb-1">{{ $anggota->nama_lengkap }}</h3>
|
||||||
|
<p class="text-white-50 mb-0"><i class="icon-map-pin me-1"></i> Kolat {{ $anggota->kolat->nama_kolat }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if(session('success'))
|
||||||
|
<div class="alert alert-success border-0 shadow-sm mb-4" style="border-radius: 15px;">
|
||||||
|
<i class="icon-check-circle me-2"></i> {{ session('success') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<!-- KOLOM KIRI: Data Pribadi & Ganti Password -->
|
||||||
|
<div class="col-md-8">
|
||||||
|
|
||||||
|
<!-- FORM 1: DATA PRIBADI -->
|
||||||
|
<form action="{{ route('profile.update') }}" method="POST" id="formProfil">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
|
||||||
|
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
|
||||||
|
<div class="card-header bg-white border-0 pt-4 px-4 d-flex justify-content-between align-items-center">
|
||||||
|
<h5 class="fw-bold text-primary mb-0"><i class="icon-user me-2"></i>Data Pribadi</h5>
|
||||||
|
<!-- Tombol untuk mengaktifkan Edit Mode -->
|
||||||
|
<button type="button" id="btnEditMode" class="btn btn-sm btn-outline-primary rounded-pill px-3 fw-bold">
|
||||||
|
<i class="icon-edit-2 me-1"></i> Edit Data
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label class="form-label fw-bold">Nama Lengkap</label>
|
||||||
|
<input type="text" name="nama_lengkap" class="form-control profil-input"
|
||||||
|
value="{{ old('nama_lengkap', $anggota->nama_lengkap) }}" disabled required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Alamat Email (User ID)</label>
|
||||||
|
<input type="email" class="form-control bg-light"
|
||||||
|
value="{{ $anggota->user->email }}" readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">No. WhatsApp</label>
|
||||||
|
<input type="number" name="no_hp" class="form-control profil-input"
|
||||||
|
value="{{ old('no_hp', $anggota->no_hp) }}" disabled required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Tempat Lahir</label>
|
||||||
|
<input type="text" name="tempat_lahir" class="form-control profil-input"
|
||||||
|
value="{{ old('tempat_lahir', $anggota->tempat_lahir) }}" disabled required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Tanggal Lahir</label>
|
||||||
|
<input type="date" name="tgl_lahir" class="form-control profil-input"
|
||||||
|
value="{{ old('tgl_lahir', $anggota->tgl_lahir) }}" disabled required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label class="form-label fw-bold">Alamat Lengkap</label>
|
||||||
|
<textarea name="alamat" class="form-control profil-input" rows="3" disabled required>{{ old('alamat', $anggota->alamat) }}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Area Tombol Simpan (Disembunyikan secara default) -->
|
||||||
|
<div class="card-footer bg-light border-0 p-4 d-none" id="footerSimpanProfil" style="border-radius: 0 0 20px 20px;">
|
||||||
|
<div class="d-flex justify-content-end gap-2">
|
||||||
|
<button type="button" id="btnBatalEdit" class="btn btn-light px-4 fw-bold shadow-sm" style="border-radius: 10px;">Batal</button>
|
||||||
|
<button type="submit" class="btn btn-primary px-4 fw-bold shadow" style="border-radius: 10px;">Simpan Perubahan</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- FORM 2: UBAH PASSWORD -->
|
||||||
|
<form action="{{ route('profile.password') }}" method="POST">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
|
||||||
|
<div class="card-header bg-white border-0 pt-4 px-4">
|
||||||
|
<h5 class="fw-bold text-dark mb-0"><i class="icon-lock me-2 text-warning"></i>Keamanan & Password</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label class="form-label fw-bold">Password Saat Ini</label>
|
||||||
|
<input type="password" name="current_password" class="form-control" placeholder="Masukkan password lama" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Password Baru</label>
|
||||||
|
<input type="password" name="password" class="form-control" placeholder="Minimal 8 karakter" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Konfirmasi Password Baru</label>
|
||||||
|
<input type="password" name="password_confirmation" class="form-control" placeholder="Ulangi password baru" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer bg-white border-0 px-4 pb-4 pt-0">
|
||||||
|
<button type="submit" class="btn btn-warning text-dark fw-bold shadow-sm w-100" style="border-radius: 10px;">
|
||||||
|
Perbarui Password
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- KOLOM KANAN: Status Organisasi -->
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
|
||||||
|
<div class="card-header bg-white border-0 pt-4 px-4">
|
||||||
|
<h5 class="fw-bold text-success mb-0"><i class="icon-badge me-2"></i>Status Organisasi</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="text-muted small d-block">Nomor Induk Anggota</label>
|
||||||
|
<span class="fw-bold text-primary fs-5">{{ $anggota->no_induk }}</span>
|
||||||
|
</div>
|
||||||
|
<hr class="opacity-10">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label fw-bold">Jabatan</label>
|
||||||
|
<div class="p-2 bg-light rounded text-dark fw-semibold border border-light">
|
||||||
|
{{ $anggota->role->nama_role }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label fw-bold">Asal Kolat</label>
|
||||||
|
<div class="p-2 bg-light rounded text-dark fw-semibold border border-light">
|
||||||
|
Kolat {{ $anggota->kolat->nama_kolat }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label fw-bold">Tingkatan Sabuk</label>
|
||||||
|
<div class="p-2 bg-light rounded text-dark fw-semibold border border-light">
|
||||||
|
{{ $anggota->tingkatan ?? 'Belum ada data' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bantuan Card -->
|
||||||
|
<div class="card border-0 shadow-sm" style="border-radius: 20px; background-color: #fff4f4;">
|
||||||
|
<div class="card-body p-4 text-center">
|
||||||
|
<div class="rounded-circle bg-white d-inline-flex p-3 mb-3 shadow-sm">
|
||||||
|
<i class="icon-help-circle text-danger fs-4"></i>
|
||||||
|
</div>
|
||||||
|
<h6 class="fw-bold text-danger">Butuh Bantuan?</h6>
|
||||||
|
<p class="small text-muted mb-0">Jika data organisasi (Kolat/Jabatan/Tingkat) tidak sesuai, silakan hubungi Pengurus Cabang melalui pelatih Anda.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- JAVASCRIPT UNTUK TOGGLE EDIT MODE -->
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
const btnEditMode = document.getElementById('btnEditMode');
|
||||||
|
const btnBatalEdit = document.getElementById('btnBatalEdit');
|
||||||
|
const inputs = document.querySelectorAll('.profil-input');
|
||||||
|
const footerSimpan = document.getElementById('footerSimpanProfil');
|
||||||
|
|
||||||
|
// Fungsi untuk mengaktifkan mode edit
|
||||||
|
btnEditMode.addEventListener('click', function() {
|
||||||
|
inputs.forEach(input => {
|
||||||
|
input.removeAttribute('disabled');
|
||||||
|
input.classList.add('border-primary'); // Highlight input yang bisa diedit
|
||||||
|
});
|
||||||
|
btnEditMode.classList.add('d-none'); // Sembunyikan tombol Edit
|
||||||
|
footerSimpan.classList.remove('d-none'); // Munculkan tombol Simpan
|
||||||
|
inputs[0].focus(); // Fokus ke input pertama
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fungsi untuk membatalkan mode edit
|
||||||
|
btnBatalEdit.addEventListener('click', function() {
|
||||||
|
inputs.forEach(input => {
|
||||||
|
input.setAttribute('disabled', 'disabled');
|
||||||
|
input.classList.remove('border-primary');
|
||||||
|
});
|
||||||
|
btnEditMode.classList.remove('d-none');
|
||||||
|
footerSimpan.classList.add('d-none');
|
||||||
|
|
||||||
|
// Opsi: reset form ke nilai awal jika dibatalkan
|
||||||
|
document.getElementById('formProfil').reset();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.form-control {
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border: 1px solid #dce1e7;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
.form-control:disabled {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
.form-control:focus {
|
||||||
|
border-color: #0d6efd;
|
||||||
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.1);
|
||||||
|
}
|
||||||
|
.border-primary {
|
||||||
|
border-color: #0d6efd !important;
|
||||||
|
background-color: #fff !important;
|
||||||
|
}
|
||||||
|
.bg-light { background-color: #f8f9fa !important; }
|
||||||
|
</style>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
@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 active text-primary fw-bold small" aria-current="page">Rekap Kelayakan</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
<h3 class="fw-bold text-dark">Rekap Kelayakan Anggota</h3>
|
||||||
|
<p class="text-muted small">Penentuan kelayakan ujian berdasarkan presensi dan administrasi SPP.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<!-- Action Form disesuaikan ke rekap.index -->
|
||||||
|
<form action="{{ route('rekap.index') }}" 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="fas fa-search 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 Analisis</h6>
|
||||||
|
<p class="text-muted small mb-0">Menampilkan {{ $dataRekap->count() }} data hasil kalkulasi.</p>
|
||||||
|
</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</th>
|
||||||
|
<th class="text-center">Presensi</th>
|
||||||
|
<th class="text-center">Status SPP</th>
|
||||||
|
<th class="text-center">Kelayakan Ujian</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@forelse($dataRekap 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'] }}</div>
|
||||||
|
<small class="text-muted text-start ps-3 d-block">Tingkat: {{ $item['tingkatan'] }}</small>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="fw-bold {{ $item['persentase_presensi'] >= 75 ? 'text-primary' : 'text-warning' }}">
|
||||||
|
{{ $item['persentase_presensi'] }}%
|
||||||
|
</span>
|
||||||
|
<div style="font-size: 10px;" class="text-muted">{{ $item['status_aktif'] }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="badge rounded-pill {{ $item['status_spp'] == 'Lunas' ? 'bg-success-soft text-success' : 'bg-secondary-soft text-secondary' }} px-3 py-2">
|
||||||
|
{{ $item['status_spp'] }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
@if($item['layak'])
|
||||||
|
<span class="badge bg-info-soft text-info px-3 py-2 rounded-pill">
|
||||||
|
<i class="fas fa-check-circle me-1"></i> Layak
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-secondary-soft text-muted px-3 py-2 rounded-pill">
|
||||||
|
Belum Layak
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="5" class="text-center py-5">
|
||||||
|
<span class="text-muted small">Data tidak ditemukan.</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Style tetap sama seperti yang Anda miliki */
|
||||||
|
.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; }
|
||||||
|
</style>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
@extends('layout.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid py-4">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center mb-4">
|
||||||
|
<a href="{{ route('spp.anggota.index') }}" class="btn btn-light shadow-sm me-3" style="border-radius: 10px;">
|
||||||
|
<i class="fas fa-arrow-left"></i>
|
||||||
|
</a>
|
||||||
|
<h3 class="fw-bold text-dark mb-0">Upload Bukti Pembayaran</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if($errors->any())
|
||||||
|
<div class="alert alert-danger" style="border-radius: 10px;">
|
||||||
|
<ul class="mb-0">
|
||||||
|
@foreach($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="alert alert-info border-0" style="border-radius: 12px; background-color: rgba(13, 110, 253, 0.1);">
|
||||||
|
<h6 class="fw-bold mb-1"><i class="fas fa-info-circle me-1"></i> Informasi Tagihan</h6>
|
||||||
|
<p class="mb-0 small text-dark">Anda akan melakukan pembayaran SPP periode <b>{{ $spp->bulan }} {{ $spp->tahun }}</b> sebesar <b>Rp {{ number_format($spp->nominal, 0, ',', '.') }}</b>.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- PENTING: enctype harus ada untuk upload file -->
|
||||||
|
<form action="{{ route('spp.anggota.prosesBayar', $spp->id) }}" method="POST" enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="mb-4 mt-4">
|
||||||
|
<label class="form-label fw-bold">Pilih Bukti Transfer (Gambar/Foto)</label>
|
||||||
|
<!-- Input File -->
|
||||||
|
<input type="file" name="bukti_pembayaran" class="form-control border-0 bg-light py-2" accept="image/png, image/jpeg, image/jpg" required style="border-radius: 12px;">
|
||||||
|
<div class="form-text small mt-2">* Format yang didukung: JPG, JPEG, PNG. Maksimal ukuran file 2MB.</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary w-100 py-3 fw-bold shadow-sm" style="border-radius: 12px; font-size: 1.1rem;">
|
||||||
|
<i class="fas fa-paper-plane me-2"></i> Kirim Bukti Pembayaran
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
@extends('layout.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid py-4">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<div>
|
||||||
|
<h3 class="fw-bold text-dark mb-1">Tagihan SPP Saya</h3>
|
||||||
|
<p class="text-muted small mb-0">Lihat riwayat dan lakukan pembayaran SPP bulanan.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if(session('success'))
|
||||||
|
<div class="alert alert-success border-0 shadow-sm" style="border-radius: 10px;">
|
||||||
|
<i class="fas fa-check-circle me-1"></i> {{ session('success') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="card border-0 shadow-sm" style="border-radius: 20px; overflow: hidden;">
|
||||||
|
<div class="card-header border-0 py-3 text-white" style="background-color: #0d6efd;">
|
||||||
|
<h6 class="mb-0 fw-bold"><i class="fas fa-file-invoice me-2"></i>Daftar Tagihan</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-0">
|
||||||
|
@if($data_spp->isEmpty())
|
||||||
|
<div class="py-5 text-center">
|
||||||
|
<i class="fas fa-smile text-muted mb-3" style="font-size: 60px; opacity: 0.3;"></i>
|
||||||
|
<h5 class="fw-bold text-muted">Belum ada tagihan SPP untuk Anda.</h5>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover align-middle mb-0">
|
||||||
|
<thead class="bg-light text-muted" style="font-size: 13px; text-transform: uppercase;">
|
||||||
|
<tr>
|
||||||
|
<th class="ps-4">Periode</th>
|
||||||
|
<th>Nominal</th>
|
||||||
|
<th>Batas Bayar</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th class="text-center">Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach($data_spp as $spp)
|
||||||
|
<tr>
|
||||||
|
<td class="ps-4 fw-bold text-dark">
|
||||||
|
{{ $spp->bulan }} {{ $spp->tahun }}
|
||||||
|
</td>
|
||||||
|
<td class="text-dark">Rp {{ number_format($spp->nominal, 0, ',', '.') }}</td>
|
||||||
|
<td class="text-muted small">
|
||||||
|
{{ \Carbon\Carbon::parse($spp->jatuh_tempo)->translatedFormat('d F Y') }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if($spp->status == 'lunas')
|
||||||
|
<span class="badge bg-success-soft text-success rounded-pill px-3">Lunas</span>
|
||||||
|
@elseif($spp->status == 'pending')
|
||||||
|
<span class="badge bg-warning-soft text-warning rounded-pill px-3">Menunggu Verifikasi</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-danger-soft text-danger rounded-pill px-3">Belum Bayar</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
@if($spp->status == 'belum_bayar')
|
||||||
|
<a href="{{ route('spp.anggota.formBayar', $spp->id) }}" class="btn btn-sm btn-primary px-3 shadow-sm" style="border-radius: 8px;">
|
||||||
|
<i class="fas fa-upload me-1"></i> Upload Bukti
|
||||||
|
</a>
|
||||||
|
@elseif($spp->status == 'pending')
|
||||||
|
<button class="btn btn-sm btn-secondary px-3" style="border-radius: 8px;" disabled>Diproses</button>
|
||||||
|
@else
|
||||||
|
<i class="fas fa-check-circle text-success fs-5"></i>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.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); }
|
||||||
|
</style>
|
||||||
|
@endsection
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
<option value="" selected disabled>Cari nama anggota...</option>
|
<option value="" selected disabled>Cari nama anggota...</option>
|
||||||
@foreach($data_anggota as $agt)
|
@foreach($data_anggota as $agt)
|
||||||
<option value="{{ $agt->id }}" {{ old('anggota_id') == $agt->id ? 'selected' : '' }}>
|
<option value="{{ $agt->id }}" {{ old('anggota_id') == $agt->id ? 'selected' : '' }}>
|
||||||
{{ $agt->nama }} (ID: {{ $agt->id }})
|
{{ $agt->nama_lengkap }} (ID: {{ $agt->id }})
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,27 @@
|
||||||
@extends('layout.app')
|
@extends('layout.app')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
@php
|
||||||
|
$userRole = auth()->user()->role->nama_role ?? 'Anggota';
|
||||||
|
@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">
|
|
||||||
<div>
|
|
||||||
<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 gap-2">
|
|
||||||
<form action="{{ route('spp.generate') }}" method="POST">
|
|
||||||
@csrf
|
|
||||||
<button type="submit" class="btn btn-warning text-white px-3 py-2 shadow-sm" style="border-radius: 10px;" onclick="return confirm('Generate tagihan otomatis untuk bulan ini?')">
|
|
||||||
<i class="fas fa-cog me-1"></i> Generate Tagihan
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<a href="{{ route('spp.create') }}" class="btn btn-danger px-3 py-2 shadow-sm" style="border-radius: 10px; display: flex; align-items: center; text-decoration: none;">
|
|
||||||
<i class="fas fa-plus me-1"></i> Tambah Manual
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<button class="btn btn-info text-white px-3 py-2 shadow-sm" style="border-radius: 10px; background-color: #0099bc;">
|
|
||||||
<i class="fas fa-download me-1"></i> Export
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div> --}}
|
|
||||||
|
|
||||||
<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>
|
||||||
<div class="d-flex flex-wrap gap-2">
|
<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">
|
<form action="{{ route('spp.generate') }}" method="POST" class="m-0">
|
||||||
@csrf
|
@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?')">
|
<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
|
<i class="fas fa-cog me-2"></i> Generate
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</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;">
|
<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
|
<i class="fas fa-file-excel me-2"></i> Excel
|
||||||
|
|
@ -53,6 +37,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Alert Notifikasi -->
|
||||||
|
@if(session('success'))
|
||||||
|
<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
|
||||||
|
|
||||||
<!-- Statistik Cards -->
|
<!-- Statistik Cards -->
|
||||||
<div class="row g-3 mb-4">
|
<div class="row g-3 mb-4">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
|
|
@ -129,6 +120,7 @@
|
||||||
<select name="status" class="form-select border-0 bg-light">
|
<select name="status" class="form-select border-0 bg-light">
|
||||||
<option value="">Semua Status</option>
|
<option value="">Semua Status</option>
|
||||||
<option value="lunas" {{ request('status') == 'lunas' ? 'selected' : '' }}>Lunas</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>
|
<option value="belum_bayar" {{ request('status') == 'belum_bayar' ? 'selected' : '' }}>Belum Bayar</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -178,7 +170,6 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td class="ps-4">
|
<td class="ps-4">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<!-- Avatar Inisial -->
|
|
||||||
<div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-center me-3 shadow-sm"
|
<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);">
|
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)) }}
|
{{ strtoupper(substr($spp->anggota->nama_lengkap, 0, 1)) }}
|
||||||
|
|
@ -203,6 +194,10 @@
|
||||||
<span class="badge bg-success-soft text-success rounded-pill px-3">
|
<span class="badge bg-success-soft text-success rounded-pill px-3">
|
||||||
<i class="fas fa-check-circle me-1"></i> Lunas
|
<i class="fas fa-check-circle me-1"></i> Lunas
|
||||||
</span>
|
</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())
|
@elseif($spp->status == 'belum_bayar' && \Carbon\Carbon::parse($spp->jatuh_tempo)->isPast())
|
||||||
<span class="badge bg-danger-soft text-danger rounded-pill px-3">
|
<span class="badge bg-danger-soft text-danger rounded-pill px-3">
|
||||||
<i class="fas fa-exclamation-circle me-1"></i> Terlambat
|
<i class="fas fa-exclamation-circle me-1"></i> Terlambat
|
||||||
|
|
@ -214,18 +209,70 @@
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
@if($spp->status != 'lunas')
|
@if($spp->status == 'belum_bayar')
|
||||||
<form action="{{ route('spp.bayar', $spp->id) }}" method="POST" class="d-inline">
|
<form action="{{ route('spp.bayar', $spp->id) }}" method="POST" class="d-inline">
|
||||||
@csrf
|
@csrf
|
||||||
<button type="submit" class="btn btn-sm btn-primary px-3 shadow-sm"
|
<button type="submit" class="btn btn-sm btn-primary px-3 shadow-sm"
|
||||||
style="border-radius: 8px;"
|
style="border-radius: 8px;"
|
||||||
onclick="return confirm('Konfirmasi pembayaran untuk {{ $spp->anggota->nama }}?')">
|
onclick="return confirm('Konfirmasi pembayaran tunai untuk {{ $spp->anggota->nama_lengkap }}?')">
|
||||||
Bayar
|
@if($userRole == 'Pelatih')
|
||||||
|
<i class="fas fa-hand-holding-usd me-1"></i> Terima Cash
|
||||||
|
@else
|
||||||
|
Bayar Tunai
|
||||||
|
@endif
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</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>
|
||||||
|
|
||||||
@else
|
@else
|
||||||
<span class="text-success small fw-bold">
|
<span class="text-success small fw-bold">
|
||||||
<i class="fas fa-check-double me-1"></i> Terbayar
|
<i class="fas fa-check-double me-1"></i> Terverifikasi
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -243,24 +290,10 @@
|
||||||
.bg-light { background-color: #f8f9fa !important; }
|
.bg-light { background-color: #f8f9fa !important; }
|
||||||
.uppercase { text-transform: uppercase; letter-spacing: 0.8px; font-size: 10px; font-weight: 700; }
|
.uppercase { text-transform: uppercase; letter-spacing: 0.8px; font-size: 10px; font-weight: 700; }
|
||||||
.fs-1 { font-size: 2.2rem !important; opacity: 0.2; }
|
.fs-1 { font-size: 2.2rem !important; opacity: 0.2; }
|
||||||
|
|
||||||
/* Soft Badge Styles */
|
|
||||||
.bg-success-soft { background-color: rgba(25, 135, 84, 0.12); }
|
.bg-success-soft { background-color: rgba(25, 135, 84, 0.12); }
|
||||||
.bg-danger-soft { background-color: rgba(220, 53, 69, 0.12); }
|
.bg-danger-soft { background-color: rgba(220, 53, 69, 0.12); }
|
||||||
.bg-warning-soft { background-color: rgba(255, 193, 7, 0.15); }
|
.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; }
|
||||||
.table-hover tbody tr:hover {
|
.form-select, .form-control { border-radius: 10px; padding: 0.6rem 1rem; }
|
||||||
background-color: rgba(13, 110, 253, 0.03);
|
|
||||||
transition: 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-select, .form-control {
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 0.6rem 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
transition: transform 0.2s;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
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;
|
||||||
|
use App\Http\Controllers\ProfileController;
|
||||||
|
use App\Http\Controllers\RekapController;
|
||||||
use App\Http\Controllers\SppController;
|
use App\Http\Controllers\SppController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
|
@ -24,175 +26,156 @@
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Route::get('/', function () {
|
// =======================================================
|
||||||
return view('index');
|
// RUTE PUBLIK (TIDAK PERLU LOGIN)
|
||||||
});
|
// =======================================================
|
||||||
|
Route::get('/', function () { return view('index'); });
|
||||||
Route::get('/index', function () {
|
Route::get('/index', function () { return view('layout.app'); });
|
||||||
return view('layout.app');
|
|
||||||
});
|
|
||||||
|
|
||||||
Route::get('/p', function () {
|
|
||||||
return view('user.user');
|
|
||||||
});
|
|
||||||
|
|
||||||
Route::get('/anggota', function () {
|
|
||||||
return view('anggota.anggota');
|
|
||||||
});
|
|
||||||
|
|
||||||
Route::middleware('guest')->group(function () {
|
Route::middleware('guest')->group(function () {
|
||||||
Route::get('/login', [AuthController::class, 'showLogin'])->name('login');
|
Route::get('/login', [AuthController::class, 'showLogin'])->name('login');
|
||||||
Route::post('/login', [AuthController::class, 'login']); // Sesuaikan nama method
|
Route::post('/login', [AuthController::class, 'login']);
|
||||||
|
|
||||||
Route::get('/register', [AuthController::class, 'showRegister'])->name('register');
|
Route::get('/register', [AuthController::class, 'showRegister'])->name('register');
|
||||||
Route::post('/register', [AuthController::class, 'register']); // Sesuaikan nama method
|
Route::post('/register', [AuthController::class, 'register']);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route untuk user yang SUDAH login
|
// =======================================================
|
||||||
|
// RUTE GLOBAL (SEMUA ROLE BISA AKSES SETELAH LOGIN)
|
||||||
|
// =======================================================
|
||||||
Route::middleware('auth')->group(function () {
|
Route::middleware('auth')->group(function () {
|
||||||
Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
|
Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
|
||||||
|
|
||||||
// Route dashboard atau menu lainnya masukkan di sini
|
|
||||||
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
|
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
|
||||||
|
|
||||||
// anggota
|
// =======================================================
|
||||||
Route::get('/anggota', [AnggotaController::class, 'anggota'])->name('anggota.anggota');
|
// 1. BLOK KHUSUS ANGGOTA
|
||||||
Route::get('/anggota/tambah', [AnggotaController::class, 'create'])->name('anggota.create');
|
// =======================================================
|
||||||
Route::post('/anggota/simpan', [AnggotaController::class, 'store'])->name('anggota.store');
|
Route::middleware('checkrole:Anggota')->group(function () {
|
||||||
Route::get('/anggota/{id}/edit', [AnggotaController::class, 'edit'])->name('anggota.edit');
|
// SPP Anggota (Upload Bukti)
|
||||||
Route::put('/anggota/{id}', [AnggotaController::class, 'update'])->name('anggota.update');
|
Route::prefix('anggota/spp')->name('spp.anggota.')->group(function () {
|
||||||
Route::get('/anggota/export/excel', [AnggotaController::class, 'exportExcel'])->name('anggota.export.excel');
|
Route::get('/', [SppController::class, 'indexAnggota'])->name('index');
|
||||||
Route::get('/anggota/export/pdf', [AnggotaController::class, 'exportPdf'])->name('anggota.export.pdf');
|
Route::get('/bayar/{id}', [SppController::class, 'formBayarAnggota'])->name('formBayar');
|
||||||
|
Route::post('/bayar/{id}', [SppController::class, 'prosesBayarAnggota'])->name('prosesBayar');
|
||||||
|
});
|
||||||
|
|
||||||
// kolat
|
// Presensi Mandiri
|
||||||
Route::get('/kolat', [KolatController::class, 'kolat'])->name('kolat.index');
|
Route::prefix('presensi/anggota')->name('presensi.anggota.')->group(function () {
|
||||||
Route::get('/kolat/tambah', [KolatController::class, 'create'])->name('kolat.create');
|
Route::get('/', [PresensiController::class, 'indexAnggota'])->name('index');
|
||||||
Route::post('/kolat/simpan', [KolatController::class, 'store'])->name('kolat.store');
|
Route::get('/riwayat', [PresensiController::class, 'riwayatAnggota'])->name('riwayat');
|
||||||
Route::get('/kolat/{id}/edit', [KolatController::class, 'edit'])->name('kolat.edit');
|
Route::get('/scan/{jadwal_id}', [PresensiController::class, 'scan'])->name('scan');
|
||||||
Route::put('/kolat/{id}', [KolatController::class, 'update'])->name('kolat.update');
|
Route::post('/store-mandiri', [PresensiController::class, 'storeMandiri'])->name('storeMandiri');
|
||||||
Route::delete('/kolat/{id}', [KolatController::class, 'destroy'])->name('kolat.destroy');
|
});
|
||||||
|
|
||||||
// pelatih
|
// Penilaian (Anggota mengisi nilai)
|
||||||
// prefix diguakan untuk mengelompokkan route yang berhubungan dengan pelatih, sehingga URL nya menjadi /manajemen-pelatih/...
|
Route::get('/penilaian/create/{id}', [PenilaianController::class, 'create'])->name('penilaian.create');
|
||||||
Route::prefix('manajemen-pelatih')->group(function () {
|
Route::post('/penilaian/store', [PenilaianController::class, 'store'])->name('penilaian.store');
|
||||||
Route::get('/', [PelatihController::class, 'index'])->name('pelatih.index');
|
|
||||||
Route::get('/upgrade', [PelatihController::class, 'create'])->name('pelatih.upgrade');
|
|
||||||
Route::post('/upgrade', [PelatihController::class, 'store'])->name('pelatih.store');
|
|
||||||
Route::get('/{id}/edit', [PelatihController::class, 'edit'])->name('pelatih.edit');
|
|
||||||
Route::put('/{id}', [PelatihController::class, 'update'])->name('pelatih.update');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// jadwal
|
// =======================================================
|
||||||
// prefix diguakan untuk mengelompokkan route yang berhubungan dengan jadwal
|
// 2. BLOK KHUSUS PENGURUS & PELATIH (Bisa Akses Bersama)
|
||||||
Route::prefix('jadwal')->group(function () {
|
// =======================================================
|
||||||
Route::get('/', [JadwalController::class, 'index'])->name('jadwal.index');
|
Route::middleware('checkrole:Pengurus,Pelatih')->group(function () {
|
||||||
Route::post('/jadwal/{id}/konfirmasi', [JadwalController::class, 'konfirmasiSelesai'])->name('jadwal.konfirmasi');
|
// Lihat Master Data Dasar
|
||||||
Route::get('/create', [JadwalController::class, 'create'])->name('jadwal.create');
|
Route::get('/anggota', [AnggotaController::class, 'anggota'])->name('anggota.anggota');
|
||||||
Route::get('/{id}/detail', [JadwalController::class, 'show'])->name('jadwal.show');
|
Route::get('/anggota/tambah', [AnggotaController::class, 'create'])->name('anggota.create');
|
||||||
Route::post('/store', [JadwalController::class, 'store'])->name('jadwal.store');
|
Route::post('/anggota/simpan', [AnggotaController::class, 'store'])->name('anggota.store');
|
||||||
Route::get('/{id}/edit', [JadwalController::class, 'edit'])->name('jadwal.edit');
|
Route::get('/anggota/{id}/edit', [AnggotaController::class, 'edit'])->name('anggota.edit');
|
||||||
Route::put('/{id}/update', [JadwalController::class, 'update'])->name('jadwal.update');
|
Route::put('/anggota/{id}', [AnggotaController::class, 'update'])->name('anggota.update');
|
||||||
Route::delete('/{id}/delete', [JadwalController::class, 'destroy'])->name('jadwal.destroy');
|
Route::get('/kolat', [KolatController::class, 'kolat'])->name('kolat.index');
|
||||||
});
|
Route::get('/manajemen-pelatih', [PelatihController::class, 'index'])->name('pelatih.index');
|
||||||
|
Route::get('/jadwal', [JadwalController::class, 'index'])->name('jadwal.index');
|
||||||
|
Route::get('/jadwal/{id}/detail', [JadwalController::class, 'show'])->name('jadwal.show');
|
||||||
|
|
||||||
// Rute untuk Presensi
|
// Presensi (Verifikasi & Manual)
|
||||||
Route::prefix('presensi')->name('presensi.')->group(function () {
|
Route::prefix('presensi')->name('presensi.')->group(function () {
|
||||||
Route::get('/', [PresensiController::class, 'index'])->name('index');
|
Route::get('/', [PresensiController::class, 'index'])->name('index');
|
||||||
|
Route::get('/kehadiran/{jadwal_id}', [PresensiController::class, 'kehadiran'])->name('kehadiran');
|
||||||
|
Route::post('/konfirmasi/{presensi_id}', [PresensiController::class, 'konfirmasi'])->name('konfirmasi');
|
||||||
|
Route::post('/tambah-manual', [PresensiController::class, 'storeManual'])->name('storeManual');
|
||||||
|
});
|
||||||
|
|
||||||
// Halaman daftar kehadiran anggota pada jadwal tertentu (tampil QR Code & List)
|
Route::post('/jadwal/{id}/konfirmasi', [JadwalController::class, 'konfirmasiSelesai'])->name('jadwal.konfirmasi');
|
||||||
Route::get('/kehadiran/{jadwal_id}', [PresensiController::class, 'kehadiran'])->name('kehadiran');
|
Route::get('/jadwal/create', [JadwalController::class, 'create'])->name('jadwal.create');
|
||||||
|
Route::post('/jadwal/store', [JadwalController::class, 'store'])->name('jadwal.store');
|
||||||
|
Route::get('/jadwal/{id}/edit', [JadwalController::class, 'edit'])->name('jadwal.edit');
|
||||||
|
Route::put('/jadwal/{id}/update', [JadwalController::class, 'update'])->name('jadwal.update');
|
||||||
|
Route::delete('/jadwal/{id}/delete', [JadwalController::class, 'destroy'])->name('jadwal.destroy');
|
||||||
|
|
||||||
// Proses konfirmasi/verifikasi pelatih klik tombol "Sah"
|
// Lihat SPP & Penilaian
|
||||||
Route::post('/konfirmasi/{presensi_id}', [PresensiController::class, 'konfirmasi'])->name('konfirmasi');
|
Route::get('/spp', [SppController::class, 'index'])->name('spp.index');
|
||||||
|
Route::get('/penilaian', [PenilaianController::class, 'index'])->name('penilaian.index');
|
||||||
|
Route::get('/penilaian/rekap/{id}', [PenilaianController::class, 'show'])->name('penilaian.show');
|
||||||
|
|
||||||
// Proses tambah presensi manual (Kasus Lupa HP)
|
// Laporan (Hanya Presensi)
|
||||||
Route::post('/tambah-manual', [PresensiController::class, 'storeManual'])->name('storeManual');
|
Route::get('/laporan/presensi', [LaporanController::class, 'presensi'])->name('laporan.presensi');
|
||||||
|
Route::get('/laporan/presensi/excel', [LaporanController::class, 'presensiExcel'])->name('laporan.presensi.excel');
|
||||||
|
Route::get('/laporan/presensi/pdf', [LaporanController::class, 'presensiPdf'])->name('laporan.presensi.pdf');
|
||||||
|
|
||||||
// --- AKTOR: ANGGOTA ---
|
// Menu Rekap Kelayakan (Ditambahkan di sini)
|
||||||
// Halaman daftar jadwal hari ini di sisi anggota (Tampil tombol "Scan Absen")
|
Route::get('/rekap/kelayakan', [RekapController::class, 'index'])->name('rekap.index');
|
||||||
Route::get('/anggota', [PresensiController::class, 'indexAnggota'])->name('anggota.index');
|
|
||||||
|
|
||||||
Route::get('/riwayat', [PresensiController::class, 'riwayatAnggota'])->name('anggota.riwayat');
|
|
||||||
|
|
||||||
// Halaman Kamera Scanner (Tempat anggota men-scan QR Code pelatih)
|
|
||||||
Route::get('/scan/{jadwal_id}', [PresensiController::class, 'scan'])->name('anggota.scan');
|
|
||||||
|
|
||||||
// Proses penyimpanan absen mandiri setelah sukses scan
|
|
||||||
Route::post('/store-mandiri', [PresensiController::class, 'storeMandiri'])->name('storeMandiri');
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//Penialaian
|
// =======================================================
|
||||||
|
// 3. BLOK KHUSUS PENGURUS SAJA (Akses Tertinggi)
|
||||||
|
// =======================================================
|
||||||
|
Route::middleware('checkrole:Pengurus')->group(function () {
|
||||||
|
// Aksi CRUD Anggota
|
||||||
|
|
||||||
Route::prefix('penilaian')->name('penilaian.')->group(function () {
|
Route::get('/anggota/export/excel ', [AnggotaController::class, 'exportExcel'])->name('anggota.export.excel');
|
||||||
Route::get('/', [PenilaianController::class, 'index'])->name('index');
|
Route::get('/anggota/export/pdf', [AnggotaController::class, 'exportPdf'])->name('anggota.export.pdf');
|
||||||
// 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
|
// Aksi CRUD Kolat
|
||||||
Route::prefix('kas')->name('kas.')->group(function () {
|
Route::get('/kolat/tambah', [KolatController::class, 'create'])->name('kolat.create');
|
||||||
Route::get('/', [KasController::class, 'index'])->name('index');
|
Route::post('/kolat/simpan', [KolatController::class, 'store'])->name('kolat.store');
|
||||||
Route::post('/store', [KasController::class, 'store'])->name('store');
|
Route::get('/kolat/{id}/edit', [KolatController::class, 'edit'])->name('kolat.edit');
|
||||||
Route::put('/update/{id}', [KasController::class, 'update'])->name('update');
|
Route::put('/kolat/{id}', [KolatController::class, 'update'])->name('kolat.update');
|
||||||
Route::delete('/{id}', [KasController::class, 'destroy'])->name('destroy');
|
Route::delete('/kolat/{id}', [KolatController::class, 'destroy'])->name('kolat.destroy');
|
||||||
});
|
|
||||||
|
|
||||||
// Group SPP
|
// Aksi CRUD Pelatih
|
||||||
Route::prefix('spp')->name('spp.')->group(function () {
|
Route::get('/manajemen-pelatih/upgrade', [PelatihController::class, 'create'])->name('pelatih.upgrade');
|
||||||
Route::get('/', [SppController::class, 'index'])->name('index');
|
Route::post('/manajemen-pelatih/upgrade', [PelatihController::class, 'store'])->name('pelatih.store');
|
||||||
Route::get('/create', [SppController::class, 'create'])->name('create');
|
Route::get('/manajemen-pelatih/{id}/edit', [PelatihController::class, 'edit'])->name('pelatih.edit');
|
||||||
Route::post('/store', [SppController::class, 'store'])->name('store');
|
Route::put('/manajemen-pelatih/{id}', [PelatihController::class, 'update'])->name('pelatih.update');
|
||||||
Route::post('/bayar/{id}', [SppController::class, 'bayar'])->name('bayar');
|
|
||||||
Route::post('/generate', [SppController::class, 'generateTagihan'])->name('generate');
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- AKTOR: PENGURUS / PELATIH ---
|
// Aksi CRUD Jadwal
|
||||||
// Halaman utama rekap jadwal (untuk pilih jadwal mana yang mau dicek)
|
|
||||||
|
|
||||||
|
|
||||||
//Penialaian
|
// Aksi Transaksi SPP
|
||||||
|
Route::prefix('spp')->name('spp.')->group(function () {
|
||||||
|
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('penilaian')->name('penilaian.')->group(function () {
|
// Kas Cabang (Terkunci Mutlak)
|
||||||
Route::get('/', [PenilaianController::class, 'index'])->name('index');
|
Route::prefix('kas')->name('kas.')->group(function () {
|
||||||
// Hilangkan kata 'penilaian' di dalam sini karena sudah ada di prefix
|
Route::get('/', [KasController::class, 'index'])->name('index');
|
||||||
Route::get('/create/{id}', [PenilaianController::class, 'create'])->name('create');
|
Route::post('/store', [KasController::class, 'store'])->name('store');
|
||||||
Route::post('/store', [PenilaianController::class, 'store'])->name('store');
|
Route::put('/update/{id}', [KasController::class, 'update'])->name('update');
|
||||||
Route::get('/penilaian/rekap/{id}', [PenilaianController::class, 'show'])->name('show');
|
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');
|
||||||
|
});
|
||||||
|
|
||||||
//Kas
|
// Sisa Laporan
|
||||||
Route::prefix('kas')->name('kas.')->group(function () {
|
Route::prefix('laporan')->name('laporan.')->group(function () {
|
||||||
Route::get('/', [KasController::class, 'index'])->name('index');
|
Route::get('/anggota', [LaporanController::class, 'anggota'])->name('anggota');
|
||||||
Route::post('/store', [KasController::class, 'store'])->name('store');
|
Route::get('/kas', [LaporanController::class, 'kas'])->name('kas');
|
||||||
Route::put('/update/{id}', [KasController::class, 'update'])->name('update');
|
Route::get('/spp', [LaporanController::class, 'spp'])->name('spp');
|
||||||
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');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::get('/profile/edit', [ProfileController::class, 'edit'])->name('profile.edit');
|
||||||
|
Route::put('/profile/update', [ProfileController::class, 'update'])->name('profile.update');
|
||||||
|
Route::put('/profile/password', [ProfileController::class, 'updatePassword'])->name('profile.password');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue