From 65bc2458acadfb21475255ded9292c642363682d Mon Sep 17 00:00:00 2001 From: SitiAfiah Date: Sun, 26 Apr 2026 20:05:32 +0700 Subject: [PATCH] manajemen latihan belum --- .../app/Http/Controllers/JadwalController.php | 35 +- .../Http/Controllers/PelatihController.php | 2 +- .../Http/Controllers/PresensiController.php | 147 +++++++- manajemen_mp/app/Models/Presensi.php | 14 +- manajemen_mp/config/app.php | 2 +- ...26_04_13_165708_create_presensis_table.php | 24 +- ..._20_163145_add_status_to_jadwals_table.php | 30 ++ ...026_04_22_125908_add_report_to_jadwals.php | 31 ++ .../database/seeders/DatabaseSeeder.php | 3 + manajemen_mp/database/seeders/RoleSeeder.php | 28 ++ .../views/anggota/editanggota.blade.php | 348 ++++++++++-------- .../views/jadwal/editjadwal.blade.php | 132 +++++++ .../resources/views/jadwal/jadwal.blade.php | 179 +++++---- .../resources/views/layout/app.blade.php | 2 + .../views/pelatih/editpelatih.blade.php | 147 ++++++++ .../resources/views/pelatih/pelatih.blade.php | 8 +- .../views/presensi/anggota/index.blade.php | 83 +++++ .../views/presensi/anggota/riwayat.blade.php | 0 .../views/presensi/anggota/scan.blade.php | 0 .../views/presensi/pengurus/index.blade.php | 149 ++++++++ .../presensi/pengurus/kehadiran.blade.php | 193 ++++++++++ .../views/presensi/pengurus/laporan.blade.php | 0 manajemen_mp/routes/web.php | 13 + 23 files changed, 1314 insertions(+), 256 deletions(-) create mode 100644 manajemen_mp/database/migrations/2026_04_20_163145_add_status_to_jadwals_table.php create mode 100644 manajemen_mp/database/migrations/2026_04_22_125908_add_report_to_jadwals.php create mode 100644 manajemen_mp/database/seeders/RoleSeeder.php create mode 100644 manajemen_mp/resources/views/jadwal/editjadwal.blade.php create mode 100644 manajemen_mp/resources/views/pelatih/editpelatih.blade.php create mode 100644 manajemen_mp/resources/views/presensi/anggota/index.blade.php create mode 100644 manajemen_mp/resources/views/presensi/anggota/riwayat.blade.php create mode 100644 manajemen_mp/resources/views/presensi/anggota/scan.blade.php create mode 100644 manajemen_mp/resources/views/presensi/pengurus/index.blade.php create mode 100644 manajemen_mp/resources/views/presensi/pengurus/kehadiran.blade.php create mode 100644 manajemen_mp/resources/views/presensi/pengurus/laporan.blade.php diff --git a/manajemen_mp/app/Http/Controllers/JadwalController.php b/manajemen_mp/app/Http/Controllers/JadwalController.php index 8bf1735..0a0c924 100644 --- a/manajemen_mp/app/Http/Controllers/JadwalController.php +++ b/manajemen_mp/app/Http/Controllers/JadwalController.php @@ -13,12 +13,26 @@ class JadwalController extends Controller public function index() { - // Mengambil data jadwal beserta relasi kolat dan pelatih - $data_jadwal = Jadwal::with(['kolat', 'pelatih'])->orderBy('tanggal', 'desc')->get(); + $data_jadwal = Jadwal::with(['kolat', 'pelatih']) + ->orderBy('tanggal', 'desc') + ->orderBy('jam_mulai', 'desc') + ->get(); return view('jadwal.jadwal', compact('data_jadwal')); } + public function konfirmasiSelesai($id) +{ + $jadwal = Jadwal::findOrFail($id); + + // Kita paksa ubah status ke 'selesai' + $jadwal->status = 'selesai'; + $jadwal->save(); + + return redirect()->route('jadwal.index') + ->with('success', 'Latihan ' . $jadwal->judul_kegiatan . ' telah dikonfirmasi selesai!'); +} + public function create() { @@ -70,19 +84,21 @@ public function edit($id) $query->where('nama_role', 'Pelatih'); })->get(); - return view('jadwal.edit', compact('jadwal', 'data_kolat', 'data_pelatih')); + return view('jadwal.editjadwal', compact('jadwal', 'data_kolat', 'data_pelatih')); } - public function update(Request $request, $id) { $jadwal = Jadwal::findOrFail($id); - $request->validate([ - 'judul_kegiatan' => 'required|string', - 'kolat_id' => 'required', - 'pelatih_id' => 'required', - 'tanggal' => 'required|date', + $request->validate([ + 'judul_kegiatan' => 'required|string|max:255', + 'kolat_id' => 'required|exists:kolat,id', + 'pelatih_id' => 'required|exists:anggotas,id', + 'jenis' => 'required|in:Rutin,Tambahan,Pengumuman', + 'tanggal' => 'required|date', + 'jam_mulai' => 'required', + 'lokasi' => 'required|string', ]); $jadwal->update($request->all()); @@ -100,4 +116,5 @@ public function destroy($id) return redirect()->route('jadwal.index') ->with('success', 'Jadwal telah dihapus dari sistem.'); } + } diff --git a/manajemen_mp/app/Http/Controllers/PelatihController.php b/manajemen_mp/app/Http/Controllers/PelatihController.php index 6befb87..4b265b6 100644 --- a/manajemen_mp/app/Http/Controllers/PelatihController.php +++ b/manajemen_mp/app/Http/Controllers/PelatihController.php @@ -75,7 +75,7 @@ public function store(Request $request) public function edit($id) { $pelatih = Anggota::findOrFail($id); - return view('pelatih.edit', compact('pelatih')); + return view('pelatih.editpelatih', compact('pelatih')); } public function update(Request $request, $id) diff --git a/manajemen_mp/app/Http/Controllers/PresensiController.php b/manajemen_mp/app/Http/Controllers/PresensiController.php index 48dca04..1351a48 100644 --- a/manajemen_mp/app/Http/Controllers/PresensiController.php +++ b/manajemen_mp/app/Http/Controllers/PresensiController.php @@ -4,7 +4,152 @@ use Illuminate\Http\Request; +// TAMBAHAN WAJIB: Memanggil Facades dan Model yang digunakan +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Auth; +use App\Models\Jadwal; +use App\Models\Presensi; +use App\Models\Anggota; + class PresensiController extends Controller { - // + public function index() + { + // Mengambil semua jadwal secara manual menggunakan Query Builder (JOIN) + $data_jadwal = DB::table('jadwals') + ->leftJoin('anggotas', 'jadwals.pelatih_id', '=', 'anggotas.id') + ->leftJoin('kolat', 'jadwals.kolat_id', '=', 'kolat.id') // Sesuaikan jika nama tabel di database kamu adalah 'kolat' + ->select( + 'jadwals.*', + 'anggotas.nama_lengkap as nama_pelatih', + 'kolat.nama_kolat as nama_kolat' + ) + ->orderBy('jadwals.tanggal', 'desc') + ->get(); + + // Pastikan nama foldernya konsisten (admin atau pengurus) + return view('presensi.pengurus.index', compact('data_jadwal')); + } + + public function kehadiran($jadwal_id) +{ + // Variabel dibuat dengan nama $jadwal (tunggal) + $jadwal = Jadwal::with(['kolat', 'pelatih'])->findOrFail($jadwal_id); + + $data_presensi = Presensi::with('anggota', 'pelatihVerifikator') + ->where('jadwal_id', $jadwal_id) + ->get(); + + $daftar_anggota = Anggota::where('kolat_id', $jadwal->kolat_id) + ->where('status', 'Aktif') + ->get(); + + // Pastikan di sini tulisannya 'jadwal' (sesuai nama variabel di atas) + return view('presensi.pengurus.kehadiran', compact('jadwal', 'data_presensi', 'daftar_anggota')); +} + + /** + * 2. Proses Pelatih klik "Konfirmasi Hadir" + */ + public function konfirmasi($presensi_id) + { + $presensi = Presensi::findOrFail($presensi_id); + + // Ubah status menjadi terverifikasi dan catat ID Pelatih yang klik + $presensi->update([ + 'is_verified' => true, + 'verified_by' => Auth::user()->id + ]); + + return redirect()->back()->with('success', 'Kehadiran ' . $presensi->anggota->nama_lengkap . ' berhasil dikonfirmasi!'); + } + + /** + * 3. Proses Pelatih input manual dari Modal (Kasus Lupa HP) + */ + public function storeManual(Request $request) + { + // Validasi input dari form modal + $request->validate([ + 'jadwal_id' => 'required|exists:jadwals,id', + 'anggota_id' => 'required|exists:anggotas,id', + ]); + + // Cek apakah anggota tersebut sudah absen sebelumnya agar tidak ada data ganda (double input) + $sudah_absen = Presensi::where('jadwal_id', $request->jadwal_id) + ->where('anggota_id', $request->anggota_id) + ->first(); + + if ($sudah_absen) { + return redirect()->back()->with('error', 'Anggota tersebut sudah tercatat di daftar kehadiran!'); + } + + // Simpan data presensi baru + // Karena diinput langsung oleh pelatih, is_verified otomatis bernilai true + Presensi::create([ + 'jadwal_id' => $request->jadwal_id, + 'anggota_id' => $request->anggota_id, + 'status' => 'Hadir', + 'waktu_presensi' => now(), // Waktu dicatat saat form disubmit + 'is_verified' => true, // Langsung Sah + 'verified_by' => Auth::user()->id + ]); + + return redirect()->back()->with('success', 'Presensi manual berhasil ditambahkan!'); + } + + + public function indexAnggota() + { + $now = \Carbon\Carbon::now('Asia/Jakarta'); + $hari_ini = $now->format('Y-m-d'); + $user = Auth::user(); + + // 1. Ambil jadwal latihan yang terjadi HARI INI sesuai dengan Kolat si Anggota + // Asumsinya di tabel anggotas (users) ada kolom kolat_id + $jadwal_hari_ini = Jadwal::with('pelatih') + ->where('tanggal', $hari_ini) + ->where('kolat_id', $user->kolat_id) + ->orderBy('jam_mulai', 'asc') + ->get(); + + // 2. Cek apakah anggota ini sudah absen di jadwal tersebut + // Menggunakan pluck() untuk mengambil ID jadwal hari ini saja + $presensi_saya = Presensi::where('anggota_id', $user->id) + ->whereIn('jadwal_id', $jadwal_hari_ini->pluck('id')) + ->get() + ->keyBy('jadwal_id'); // Jadikan ID jadwal sebagai key array agar mudah dicek di View + + return view('presensi.anggota.index', compact('jadwal_hari_ini', 'presensi_saya', 'now')); + } + + public function storeMandiri(Request $request) + { + $request->validate([ + 'jadwal_id' => 'required|exists:jadwals,id', + ]); + + $user = Auth::user(); + + // Cek agar tidak bisa klik absen 2 kali (Double submit) + $sudah_absen = Presensi::where('jadwal_id', $request->jadwal_id) + ->where('anggota_id', $user->id) + ->exists(); + + if ($sudah_absen) { + return redirect()->back()->with('error', 'Kamu sudah melakukan absensi untuk jadwal ini!'); + } + + // Simpan data presensi dengan status is_verified = false (Menunggu ACC) + Presensi::create([ + 'jadwal_id' => $request->jadwal_id, + 'anggota_id' => $user->id, + 'status' => 'Hadir', + 'waktu_presensi' => now(), + 'is_verified' => false, // Belum Sah, butuh ACC Pelatih + 'verified_by' => null + ]); + + return redirect()->back()->with('success', 'Berhasil! Kehadiranmu sedang menunggu konfirmasi Pelatih.'); + } } diff --git a/manajemen_mp/app/Models/Presensi.php b/manajemen_mp/app/Models/Presensi.php index 168c475..658cd9f 100644 --- a/manajemen_mp/app/Models/Presensi.php +++ b/manajemen_mp/app/Models/Presensi.php @@ -9,12 +9,14 @@ class Presensi extends Model { use HasFactory; protected $fillable = [ - 'jadwal_id', - 'anggota_id', - 'status', - 'keterangan', - 'waktu_presensi' - ]; + 'jadwal_id', + 'anggota_id', + 'status', + 'keterangan', + 'waktu_presensi', + 'is_verified', + 'verified_by' +]; // Relasi: Presensi ini untuk jadwal yang mana? public function jadwal() diff --git a/manajemen_mp/config/app.php b/manajemen_mp/config/app.php index 9207160..3556121 100644 --- a/manajemen_mp/config/app.php +++ b/manajemen_mp/config/app.php @@ -70,7 +70,7 @@ | */ - 'timezone' => 'UTC', + 'timezone' => 'Asia/Jakarta', /* |-------------------------------------------------------------------------- diff --git a/manajemen_mp/database/migrations/2026_04_13_165708_create_presensis_table.php b/manajemen_mp/database/migrations/2026_04_13_165708_create_presensis_table.php index cacba96..6a7a632 100644 --- a/manajemen_mp/database/migrations/2026_04_13_165708_create_presensis_table.php +++ b/manajemen_mp/database/migrations/2026_04_13_165708_create_presensis_table.php @@ -12,14 +12,22 @@ public function up(): void { Schema::create('presensis', function (Blueprint $table) { - $table->id(); - $table->foreignId('jadwal_id')->constrained('jadwals')->onDelete('cascade'); - $table->foreignId('anggota_id')->constrained('anggotas')->onDelete('cascade'); - $table->enum('status', ['Hadir', 'Izin', 'Sakit', 'Alfa'])->default('Alfa'); - $table->text('keterangan')->nullable(); // Alasan izin/sakit - $table->timestamp('waktu_presensi')->nullable(); // Catat jam tepatnya dia absen - $table->timestamps(); - }); + $table->id(); + $table->foreignId('jadwal_id')->constrained('jadwals')->onDelete('cascade'); + $table->foreignId('anggota_id')->constrained('anggotas')->onDelete('cascade'); + $table->enum('status', ['Hadir', 'Izin', 'Sakit', 'Alfa'])->default('Alfa'); + $table->text('keterangan')->nullable(); + $table->timestamp('waktu_presensi')->nullable(); + + // TAMBAHKAN 2 BARIS INI: + $table->boolean('is_verified')->default(false); // Untuk tahu sudah di-ACC pelatih atau belum + $table->unsignedBigInteger('verified_by')->nullable(); // Untuk catat ID pelatih yang meng-ACC + + $table->timestamps(); + + // Tambahkan foreign key untuk verified_by + $table->foreign('verified_by')->references('id')->on('anggotas'); + }); } /** diff --git a/manajemen_mp/database/migrations/2026_04_20_163145_add_status_to_jadwals_table.php b/manajemen_mp/database/migrations/2026_04_20_163145_add_status_to_jadwals_table.php new file mode 100644 index 0000000..5d714ca --- /dev/null +++ b/manajemen_mp/database/migrations/2026_04_20_163145_add_status_to_jadwals_table.php @@ -0,0 +1,30 @@ +string('status')->default('pending')->after('jenis'); + }); + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('jadwals', function (Blueprint $table) { + $table->dropColumn('status'); + }); + } +}; diff --git a/manajemen_mp/database/migrations/2026_04_22_125908_add_report_to_jadwals.php b/manajemen_mp/database/migrations/2026_04_22_125908_add_report_to_jadwals.php new file mode 100644 index 0000000..6cb0e08 --- /dev/null +++ b/manajemen_mp/database/migrations/2026_04_22_125908_add_report_to_jadwals.php @@ -0,0 +1,31 @@ +string('foto_bukti')->nullable()->after('lokasi'); + // Menambah kolom untuk materi/catatan latihan + $table->text('catatan_latihan')->nullable()->after('foto_bukti'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('jadwals', function (Blueprint $table) { + $table->dropColumn(['foto_bukti', 'catatan_latihan']); + }); + } +}; diff --git a/manajemen_mp/database/seeders/DatabaseSeeder.php b/manajemen_mp/database/seeders/DatabaseSeeder.php index a9f4519..3ae00ff 100644 --- a/manajemen_mp/database/seeders/DatabaseSeeder.php +++ b/manajemen_mp/database/seeders/DatabaseSeeder.php @@ -12,6 +12,9 @@ class DatabaseSeeder extends Seeder */ public function run(): void { + $this->call([ + RoleSeeder::class, + ]); // \App\Models\User::factory(10)->create(); // \App\Models\User::factory()->create([ diff --git a/manajemen_mp/database/seeders/RoleSeeder.php b/manajemen_mp/database/seeders/RoleSeeder.php new file mode 100644 index 0000000..4f9efd7 --- /dev/null +++ b/manajemen_mp/database/seeders/RoleSeeder.php @@ -0,0 +1,28 @@ +insert([ + 'nama_role' => $role, + 'slug' => Str::slug($role), + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + } +} diff --git a/manajemen_mp/resources/views/anggota/editanggota.blade.php b/manajemen_mp/resources/views/anggota/editanggota.blade.php index 1bf9f50..fc3d108 100644 --- a/manajemen_mp/resources/views/anggota/editanggota.blade.php +++ b/manajemen_mp/resources/views/anggota/editanggota.blade.php @@ -1,181 +1,221 @@ @extends('layout.app') @section('content') -
- - +
+ + -
-
- -
- @csrf - @method('PUT') +
+
+ + + @csrf + @method('PUT') - -
-
-
Informasi Pribadi
-
-
-
-
- - - * No. induk permanen dan tidak dapat diubah -
-
- - -
-
- -
- +62 - + +
+
+
Informasi Pribadi
+
+
+
+
+ + + * No. induk permanen dan tidak dapat + diubah +
+
+ + +
+
+ +
+ +62 + +
+
+
+ +
-
-
- -
-
- -
-
-
Informasi Organisasi
-
-
-
-
- - -
-
- - -
-
- - -
+ +
+
+
Informasi Organisasi
+
+
+
+
+ + +
+
+ + +
+
+ + +
- - - - - -
- + +
-
- - + // Jalankan saat pertama kali halaman dimuat + document.addEventListener("DOMContentLoaded", function() { + toggleSKFields(); + }); + - + @endsection diff --git a/manajemen_mp/resources/views/jadwal/editjadwal.blade.php b/manajemen_mp/resources/views/jadwal/editjadwal.blade.php new file mode 100644 index 0000000..95ff4b1 --- /dev/null +++ b/manajemen_mp/resources/views/jadwal/editjadwal.blade.php @@ -0,0 +1,132 @@ +@extends('layout.app') + +@section('content') +
+ + +
+
+
+ @csrf + @method('PUT') + +
+
+
Informasi Agenda
+
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + +
+
+ +
+
+ @csrf + @method('DELETE') + +
+
+
+
+
+ + +@endsection diff --git a/manajemen_mp/resources/views/jadwal/jadwal.blade.php b/manajemen_mp/resources/views/jadwal/jadwal.blade.php index 15f9d46..18150c5 100644 --- a/manajemen_mp/resources/views/jadwal/jadwal.blade.php +++ b/manajemen_mp/resources/views/jadwal/jadwal.blade.php @@ -12,6 +12,13 @@

Manajemen Latihan TapakMP

+ @if(session('success')) + + @endif +
@@ -32,32 +39,59 @@ - - - - + + + - - + + @forelse ($data_jadwal as $no => $item) + @php + // Set timezone ke Jakarta agar sinkron dengan waktu Indonesia + $now = \Carbon\Carbon::now('Asia/Jakarta'); + $start = \Carbon\Carbon::parse($item->tanggal . ' ' . $item->jam_mulai, 'Asia/Jakarta'); + $end = $item->jam_selesai + ? \Carbon\Carbon::parse($item->tanggal . ' ' . $item->jam_selesai, 'Asia/Jakarta') + : $start->copy()->addHours(2); + + $dbStatus = trim(strtolower($item->status)); + + // Logika Penentuan Label Status + if ($dbStatus == 'selesai') { + $status_label = 'Selesai'; + $status_color = 'success'; + } elseif ($now->greaterThanOrEqualTo($start) && $now->lessThanOrEqualTo($end)) { + $status_label = 'Berlangsung'; + $status_color = 'primary'; + } elseif ($now->lt($start)) { + $status_label = 'Mendatang'; + $status_color = 'secondary'; + } else { + $status_label = 'Menunggu Konfirmasi'; + $status_color = 'warning'; + } + @endphp - - {{-- MODAL DETAIL JADWAL (Identik dengan Modal Anggota) --}} + {{-- MODAL DETAIL JADWAL --}} - + @endforelse @@ -187,22 +206,38 @@ class="btn btn-sm btn-action-edit fw-bold px-3 shadow-xs"> + + @endsection diff --git a/manajemen_mp/resources/views/layout/app.blade.php b/manajemen_mp/resources/views/layout/app.blade.php index 3bbfd66..d1344ac 100644 --- a/manajemen_mp/resources/views/layout/app.blade.php +++ b/manajemen_mp/resources/views/layout/app.blade.php @@ -100,5 +100,7 @@ @endif + + diff --git a/manajemen_mp/resources/views/pelatih/editpelatih.blade.php b/manajemen_mp/resources/views/pelatih/editpelatih.blade.php new file mode 100644 index 0000000..19e75bc --- /dev/null +++ b/manajemen_mp/resources/views/pelatih/editpelatih.blade.php @@ -0,0 +1,147 @@ +@extends('layout.app') + +@section('content') +
+ + +
+
+
+ @csrf + @method('PUT') + +
+
+
Identitas Pelatih
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ * Data identitas di atas bersifat tetap. Ubah di menu Anggota jika terdapat kesalahan input nama/induk. +
+
+ +
+
+
Legalitas & Masa Aktif SK
+
+
+
+
+ + + @error('no_sk') {{ $message }} @enderror +
+
+ + +
+
+ + +
+ +
+
+ + + + @if ($pelatih->foto_sk) +
+ + File saat ini: + + Lihat Dokumen SK + + +
+ @else + Belum ada file SK yang diunggah. + @endif +
+
+
+
+ + +
+ +
+
+
+ + +@endsection diff --git a/manajemen_mp/resources/views/pelatih/pelatih.blade.php b/manajemen_mp/resources/views/pelatih/pelatih.blade.php index 7653819..38a34f1 100644 --- a/manajemen_mp/resources/views/pelatih/pelatih.blade.php +++ b/manajemen_mp/resources/views/pelatih/pelatih.blade.php @@ -30,7 +30,7 @@
-
NoKegiatan & DeskripsiKolatPelatih BertugasNoKegiatan & PelatihStatus Waktu & LokasiTipeAksiTipeAksi
{{ $no + 1 }} -
{{ $item->judul_kegiatan }}
- {{ Str::limit($item->deskripsi, 40) }} +
+ {{ $item->judul_kegiatan }} + @if($dbStatus == 'selesai') + + @endif +
+ + {{ $item->pelatih->nama_lengkap ?? 'Belum Ditentukan' }} +
- - {{ $item->kolat->nama_kolat ?? '-' }} + + {{ $status_label }} -
{{ $item->pelatih->nama_lengkap ?? 'Belum Ditentukan' }}
- ID: {{ $item->pelatih->no_induk ?? '-' }} -
{{ \Carbon\Carbon::parse($item->tanggal)->format('d M Y') }} @@ -66,45 +100,52 @@ {{ substr($item->jam_mulai, 0, 5) }} - {{ $item->jam_selesai ? substr($item->jam_selesai, 0, 5) : 'Selesai' }}
- {{ $item->lokasi }} + {{ $item->lokasi }}
@php - $bg_color = 'bg-secondary-soft text-secondary'; - if($item->jenis == 'Rutin') $bg_color = 'bg-success-soft text-success border-success'; - elseif($item->jenis == 'Tambahan') $bg_color = 'bg-info-soft text-info border-info'; - elseif($item->jenis == 'Pengumuman') $bg_color = 'bg-danger-soft text-danger border-danger'; + $bg_type = 'bg-secondary-soft text-secondary'; + if($item->jenis == 'Rutin') $bg_type = 'bg-success-soft text-success border-success'; + elseif($item->jenis == 'Tambahan') $bg_type = 'bg-info-soft text-info border-info'; + elseif($item->jenis == 'Pengumuman') $bg_type = 'bg-danger-soft text-danger border-danger'; @endphp - + {{ $item->jenis }}
- - @if($item->jenis != 'Pengumuman') - - Absen - + {{-- TOMBOL KONFIRMASI: Muncul jika sudah masuk jamnya, bukan pengumuman, dan belum selesai --}} + @if($dbStatus != 'selesai' && $item->jenis != 'Pengumuman' && $now->greaterThanOrEqualTo($start)) +
+ @csrf + +
@endif + + + class="btn btn-sm btn-action-edit fw-bold px-2 shadow-xs">
Belum ada jadwal latihan atau pengumuman.Belum ada jadwal latihan atau pengumuman.
+
@@ -46,10 +46,10 @@ - diff --git a/manajemen_mp/resources/views/presensi/anggota/index.blade.php b/manajemen_mp/resources/views/presensi/anggota/index.blade.php new file mode 100644 index 0000000..88e5af6 --- /dev/null +++ b/manajemen_mp/resources/views/presensi/anggota/index.blade.php @@ -0,0 +1,83 @@ +@extends('layout.app') + +@section('content') +
+ + + @if(session('success')) +
+ {{ session('success') }} + +
+ @endif + + @if(session('error')) +
+ {{ session('error') }} + +
+ @endif + +
+ @forelse($jadwal_hari_ini as $jadwal) +
+
+
+
+ + {{ $jadwal->jenis }} + + {{ \Carbon\Carbon::parse($jadwal->tanggal)->format('d M Y') }} +
+ +
{{ $jadwal->judul_kegiatan }}
+

Pelatih: {{ $jadwal->pelatih->nama_lengkap ?? '-' }}

+ +
+
{{ substr($jadwal->jam_mulai, 0, 5) }} - Selesai
+
{{ $jadwal->lokasi }}
+
+ + {{-- LOGIKA TOMBOL ABSEN --}} + @if(isset($presensi_saya[$jadwal->id])) + {{-- Jika sudah absen --}} + @if($presensi_saya[$jadwal->id]->is_verified) + + @else + + @endif + @else + {{-- Jika belum absen, tampilkan tombol submit --}} +
+ @csrf + + + + @endif + +
+
+
+ @empty +
+ No Schedule +
Tidak ada jadwal latihan hari ini.
+

Selamat istirahat atau berlatih mandiri di rumah!

+
+ @endforelse +
+
+ + +@endsection diff --git a/manajemen_mp/resources/views/presensi/anggota/riwayat.blade.php b/manajemen_mp/resources/views/presensi/anggota/riwayat.blade.php new file mode 100644 index 0000000..e69de29 diff --git a/manajemen_mp/resources/views/presensi/anggota/scan.blade.php b/manajemen_mp/resources/views/presensi/anggota/scan.blade.php new file mode 100644 index 0000000..e69de29 diff --git a/manajemen_mp/resources/views/presensi/pengurus/index.blade.php b/manajemen_mp/resources/views/presensi/pengurus/index.blade.php new file mode 100644 index 0000000..2d4f9d5 --- /dev/null +++ b/manajemen_mp/resources/views/presensi/pengurus/index.blade.php @@ -0,0 +1,149 @@ +@extends('layout.app') + +@section('content') +
+ + + @if(session('success')) + + @endif + +
+
+
+
+ +
+
+
Pilih Jadwal Latihan
+

Klik tombol cek kehadiran untuk memverifikasi absen anggota dan upload bukti latihan.

+
+
+ +
+
No
{{ $no + 1 }} -
{{ $item->nama_lengkap }}
- ID: {{ $item->no_induk }} +
{{ $item->nama_lengkap }}
+ ID: {{ $item->no_induk }}
+
{{ $item->no_sk }}
Hingga: {{ \Carbon\Carbon::parse($item->masa_berlaku)->format('d M Y') }}
+ + + + + + + + + + + + @forelse ($data_jadwal as $no => $item) + @php + // Set timezone ke Jakarta agar sinkron dengan waktu Indonesia + $now = \Carbon\Carbon::now('Asia/Jakarta'); + $start = \Carbon\Carbon::parse($item->tanggal . ' ' . $item->jam_mulai, 'Asia/Jakarta'); + $end = $item->jam_selesai + ? \Carbon\Carbon::parse($item->tanggal . ' ' . $item->jam_selesai, 'Asia/Jakarta') + : $start->copy()->addHours(2); + + $dbStatus = trim(strtolower($item->status)); + + // Logika Penentuan Label Status + if ($dbStatus == 'selesai') { + $status_label = 'Selesai'; + $status_color = 'success'; + } elseif ($now->greaterThanOrEqualTo($start) && $now->lessThanOrEqualTo($end)) { + $status_label = 'Berlangsung'; + $status_color = 'primary'; + } elseif ($now->lt($start)) { + $status_label = 'Mendatang'; + $status_color = 'secondary'; + } else { + $status_label = 'Menunggu Konfirmasi'; + $status_color = 'warning'; + } + @endphp + + + + + + + + + @empty + + + + @endforelse + +
NoKegiatan & PelatihStatus JadwalWaktu & LokasiTipeAksi
{{ $no + 1 }} +
+ {{ $item->judul_kegiatan }} + @if($dbStatus == 'selesai') + + @endif +
+ + {{-- Pemanggilan dari Query Builder Manual --}} + {{ $item->nama_pelatih ?? 'Belum Ditentukan' }} + +
+ + {{ $status_label }} + + +
+ {{ \Carbon\Carbon::parse($item->tanggal)->format('d M Y') }} +
+
+ {{ substr($item->jam_mulai, 0, 5) }} - {{ $item->jam_selesai ? substr($item->jam_selesai, 0, 5) : 'Selesai' }} +
+
+ {{ $item->lokasi }} +
+
+ @php + $bg_type = 'bg-secondary-soft text-secondary'; + if($item->jenis == 'Rutin') $bg_type = 'bg-success-soft text-success border-success'; + elseif($item->jenis == 'Tambahan') $bg_type = 'bg-info-soft text-info border-info'; + elseif($item->jenis == 'Pengumuman') $bg_type = 'bg-danger-soft text-danger border-danger'; + @endphp + + {{ $item->jenis }} + + + {{-- Tombol Cek Kehadiran --}} + + Cek Kehadiran + +
Belum ada jadwal latihan tersedia.
+
+ +
+
+
+
+
+ + +@endsection diff --git a/manajemen_mp/resources/views/presensi/pengurus/kehadiran.blade.php b/manajemen_mp/resources/views/presensi/pengurus/kehadiran.blade.php new file mode 100644 index 0000000..990fa81 --- /dev/null +++ b/manajemen_mp/resources/views/presensi/pengurus/kehadiran.blade.php @@ -0,0 +1,193 @@ +@extends('layout.app') + +@section('content') +
+ + + {{-- Menampilkan Pesan Sukses --}} + @if(session('success')) + + @endif + + {{-- Menampilkan Pesan Error (Misal: Input manual ganda) --}} + @if(session('error')) + + @endif + + {{-- KARTU INFORMASI JADWAL --}} +
+
+
+
+
+
+
{{ $jadwal->judul_kegiatan }}
+

+ {{ $jadwal->lokasi }} | + {{ \Carbon\Carbon::parse($jadwal->tanggal)->format('d M Y') }} | + {{ substr($jadwal->jam_mulai, 0, 5) }} - {{ $jadwal->jam_selesai ? substr($jadwal->jam_selesai, 0, 5) : 'Selesai' }} +

+
+
+ + Kolat: {{ $jadwal->kolat->nama_kolat ?? '-' }} + +
+
+
+
+
+
+ + {{-- TABEL PRESENSI --}} +
+
+
+
+ +
+
+
Daftar Absensi Masuk
+

Klik konfirmasi untuk mensahkan kehadiran anggota.

+
+ + {{-- Tombol Buka Modal Tambah Manual --}} + +
+ +
+ + + + + + + + + + + + @forelse ($data_presensi as $no => $item) + + + + + + + + @empty + + + + @endforelse + +
NoIdentitas AnggotaWaktu AbsenStatus VerifikasiAksi
{{ $no + 1 }} +
{{ $item->anggota->nama_lengkap }}
+ ID: {{ $item->anggota->no_induk }} +
+ + {{ \Carbon\Carbon::parse($item->waktu_presensi)->format('H:i') }} WIB + + + @if($item->is_verified) + + Sah + +
+ Oleh: {{ $item->pelatihVerifikator->nama_lengkap ?? 'Pelatih' }} +
+ @else + + Menunggu + + @endif +
+ @if(!$item->is_verified) + {{-- Tombol Konfirmasi Hadir --}} +
+ @csrf + +
+ @else + + @endif +
Belum ada anggota yang melakukan absensi masuk.
+
+ +
+
+
+
+
+ + {{-- MODAL TAMBAH MANUAL (KASUS LUPA HP) --}} + + + +@endsection diff --git a/manajemen_mp/resources/views/presensi/pengurus/laporan.blade.php b/manajemen_mp/resources/views/presensi/pengurus/laporan.blade.php new file mode 100644 index 0000000..e69de29 diff --git a/manajemen_mp/routes/web.php b/manajemen_mp/routes/web.php index a8ef62b..ce75038 100644 --- a/manajemen_mp/routes/web.php +++ b/manajemen_mp/routes/web.php @@ -4,6 +4,7 @@ use App\Http\Controllers\JadwalController; use App\Http\Controllers\KolatController; use App\Http\Controllers\PelatihController; +use App\Http\Controllers\PresensiController; use Illuminate\Support\Facades\Route; @@ -64,6 +65,7 @@ //prefix diguakan untuk mengelompokkan route yang berhubungan dengan jadwal Route::prefix('jadwal')->group(function () { Route::get('/', [JadwalController::class, 'index'])->name('jadwal.index'); + Route::post('/jadwal/{id}/konfirmasi', [JadwalController::class, 'konfirmasiSelesai'])->name('jadwal.konfirmasi'); Route::get('/create', [JadwalController::class, 'create'])->name('jadwal.create'); Route::get('/{id}/detail', [JadwalController::class, 'show'])->name('jadwal.show'); Route::post('/store', [JadwalController::class, 'store'])->name('jadwal.store'); @@ -72,3 +74,14 @@ Route::delete('/{id}/delete', [JadwalController::class, 'destroy'])->name('jadwal.destroy'); }); + // --- ROUTE PRESENSI (ABSENSI) --- +Route::prefix('presensi')->name('presensi.')->group(function () { + Route::get('/', [PresensiController::class, 'index'])->name('index'); + // Halaman daftar kehadiran (View Admin/Pelatih) + Route::get('/kehadiran/{jadwal_id}', [PresensiController::class, 'kehadiran'])->name('kehadiran'); + // konfirmasi pelatih + Route::post('/konfirmasi/{presensi_id}', [PresensiController::class, 'konfirmasi'])->name('konfirmasi'); + // Proses tambah presensi manual (Kasus Lupa HP) + Route::post('/tambah-manual', [PresensiController::class, 'storeManual'])->name('storeManual'); +}); +