manajemen latihan belum

This commit is contained in:
SitiAfiah 2026-04-26 20:05:32 +07:00
parent 2092a810ce
commit 65bc2458ac
23 changed files with 1314 additions and 256 deletions

View File

@ -13,12 +13,26 @@ class JadwalController extends Controller
public function index() public function index()
{ {
// Mengambil data jadwal beserta relasi kolat dan pelatih $data_jadwal = Jadwal::with(['kolat', 'pelatih'])
$data_jadwal = Jadwal::with(['kolat', 'pelatih'])->orderBy('tanggal', 'desc')->get(); ->orderBy('tanggal', 'desc')
->orderBy('jam_mulai', 'desc')
->get();
return view('jadwal.jadwal', compact('data_jadwal')); 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() public function create()
{ {
@ -70,19 +84,21 @@ public function edit($id)
$query->where('nama_role', 'Pelatih'); $query->where('nama_role', 'Pelatih');
})->get(); })->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) public function update(Request $request, $id)
{ {
$jadwal = Jadwal::findOrFail($id); $jadwal = Jadwal::findOrFail($id);
$request->validate([ $request->validate([
'judul_kegiatan' => 'required|string', 'judul_kegiatan' => 'required|string|max:255',
'kolat_id' => 'required', 'kolat_id' => 'required|exists:kolat,id',
'pelatih_id' => 'required', 'pelatih_id' => 'required|exists:anggotas,id',
'jenis' => 'required|in:Rutin,Tambahan,Pengumuman',
'tanggal' => 'required|date', 'tanggal' => 'required|date',
'jam_mulai' => 'required',
'lokasi' => 'required|string',
]); ]);
$jadwal->update($request->all()); $jadwal->update($request->all());
@ -100,4 +116,5 @@ public function destroy($id)
return redirect()->route('jadwal.index') return redirect()->route('jadwal.index')
->with('success', 'Jadwal telah dihapus dari sistem.'); ->with('success', 'Jadwal telah dihapus dari sistem.');
} }
} }

View File

@ -75,7 +75,7 @@ public function store(Request $request)
public function edit($id) public function edit($id)
{ {
$pelatih = Anggota::findOrFail($id); $pelatih = Anggota::findOrFail($id);
return view('pelatih.edit', compact('pelatih')); return view('pelatih.editpelatih', compact('pelatih'));
} }
public function update(Request $request, $id) public function update(Request $request, $id)

View File

@ -4,7 +4,152 @@
use Illuminate\Http\Request; 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 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.');
}
} }

View File

@ -13,8 +13,10 @@ class Presensi extends Model
'anggota_id', 'anggota_id',
'status', 'status',
'keterangan', 'keterangan',
'waktu_presensi' 'waktu_presensi',
]; 'is_verified',
'verified_by'
];
// Relasi: Presensi ini untuk jadwal yang mana? // Relasi: Presensi ini untuk jadwal yang mana?
public function jadwal() public function jadwal()

View File

@ -70,7 +70,7 @@
| |
*/ */
'timezone' => 'UTC', 'timezone' => 'Asia/Jakarta',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@ -16,9 +16,17 @@ public function up(): void
$table->foreignId('jadwal_id')->constrained('jadwals')->onDelete('cascade'); $table->foreignId('jadwal_id')->constrained('jadwals')->onDelete('cascade');
$table->foreignId('anggota_id')->constrained('anggotas')->onDelete('cascade'); $table->foreignId('anggota_id')->constrained('anggotas')->onDelete('cascade');
$table->enum('status', ['Hadir', 'Izin', 'Sakit', 'Alfa'])->default('Alfa'); $table->enum('status', ['Hadir', 'Izin', 'Sakit', 'Alfa'])->default('Alfa');
$table->text('keterangan')->nullable(); // Alasan izin/sakit $table->text('keterangan')->nullable();
$table->timestamp('waktu_presensi')->nullable(); // Catat jam tepatnya dia absen $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(); $table->timestamps();
// Tambahkan foreign key untuk verified_by
$table->foreign('verified_by')->references('id')->on('anggotas');
}); });
} }

View File

@ -0,0 +1,30 @@
<?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('jadwals', function (Blueprint $table) {
// Tambahkan kolom status dengan default 'pending'
$table->string('status')->default('pending')->after('jenis');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('jadwals', function (Blueprint $table) {
$table->dropColumn('status');
});
}
};

View File

@ -0,0 +1,31 @@
<?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('jadwals', function (Blueprint $table) {
// Menambah kolom untuk simpan foto kegiatan (pengganti WA)
$table->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']);
});
}
};

View File

@ -12,6 +12,9 @@ class DatabaseSeeder extends Seeder
*/ */
public function run(): void public function run(): void
{ {
$this->call([
RoleSeeder::class,
]);
// \App\Models\User::factory(10)->create(); // \App\Models\User::factory(10)->create();
// \App\Models\User::factory()->create([ // \App\Models\User::factory()->create([

View File

@ -0,0 +1,28 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class RoleSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$roles = ['Anggota', 'Pelatih', 'Pengurus'];
foreach ($roles as $role) {
DB::table('role')->insert([
'nama_role' => $role,
'slug' => Str::slug($role),
'created_at' => now(),
'updated_at' => now(),
]);
}
}
}

View File

@ -1,12 +1,13 @@
@extends('layout.app') @extends('layout.app')
@section('content') @section('content')
<div class="container-fluid py-4"> <div class="container-fluid py-4">
<!-- Header & Breadcrumb --> <!-- Header & Breadcrumb -->
<div class="page-header mb-4 text-start"> <div class="page-header mb-4 text-start">
<nav aria-label="breadcrumb"> <nav aria-label="breadcrumb">
<ol class="breadcrumb bg-transparent p-0 mb-2"> <ol class="breadcrumb bg-transparent p-0 mb-2">
<li class="breadcrumb-item"><a href="{{ route('anggota.anggota') }}" class="text-muted text-decoration-none small">Daftar Anggota</a></li> <li class="breadcrumb-item"><a href="{{ route('anggota.anggota') }}"
class="text-muted text-decoration-none small">Daftar Anggota</a></li>
<li class="breadcrumb-item active text-primary fw-bold small" aria-current="page">Edit Anggota</li> <li class="breadcrumb-item active text-primary fw-bold small" aria-current="page">Edit Anggota</li>
</ol> </ol>
</nav> </nav>
@ -30,23 +31,28 @@
<div class="row g-3"> <div class="row g-3">
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label fw-bold">No Induk</label> <label class="form-label fw-bold">No Induk</label>
<input type="text" name="no_induk" class="form-control bg-light fw-bold text-primary" value="{{ $anggota->no_induk }}" readonly> <input type="text" name="no_induk" class="form-control bg-light fw-bold text-primary"
<small class="text-muted" style="font-size: 11px;">* No. induk permanen dan tidak dapat diubah</small> value="{{ $anggota->no_induk }}" readonly>
<small class="text-muted" style="font-size: 11px;">* No. induk permanen dan tidak dapat
diubah</small>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label fw-bold">Nama Lengkap</label> <label class="form-label fw-bold">Nama Lengkap</label>
<input type="text" name="nama_lengkap" class="form-control bg-light" value="{{ $anggota->nama_lengkap }}" required> <input type="text" name="nama_lengkap" class="form-control bg-light"
value="{{ $anggota->nama_lengkap }}" required>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label fw-bold">No. WhatsApp (HP)</label> <label class="form-label fw-bold">No. WhatsApp (HP)</label>
<div class="input-group"> <div class="input-group">
<span class="input-group-text bg-light border-end-0">+62</span> <span class="input-group-text bg-light border-end-0">+62</span>
<input type="number" name="no_hp" class="form-control" value="{{ $anggota->no_hp }}" placeholder="81234567xxx" required> <input type="number" name="no_hp" class="form-control"
value="{{ $anggota->no_hp }}" placeholder="81234567xxx" required>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label fw-bold">Alamat Lengkap</label> <label class="form-label fw-bold">Alamat Lengkap</label>
<input type="text" name="alamat" class="form-control" value="{{ $anggota->alamat }}" required> <input type="text" name="alamat" class="form-control" value="{{ $anggota->alamat }}"
required>
</div> </div>
</div> </div>
</div> </div>
@ -61,53 +67,79 @@
<div class="row g-3"> <div class="row g-3">
<div class="col-md-4"> <div class="col-md-4">
<label class="form-label fw-bold">Jabatan Organisasi</label> <label class="form-label fw-bold">Jabatan Organisasi</label>
<select name="jabatan" id="jabatanSelect" class="form-select border-primary" onchange="toggleSKFields()" required> <select name="jabatan" id="jabatanSelect" class="form-select border-primary"
<option value="anggota" {{ $anggota->jabatan == 'anggota' ? 'selected' : '' }}>Anggota</option> onchange="toggleSKFields()" required>
<option value="pelatih" {{ $anggota->jabatan == 'pelatih' ? 'selected' : '' }}>Pelatih</option> <option value="anggota" {{ $anggota->jabatan == 'anggota' ? 'selected' : '' }}>
<option value="pengurus" {{ $anggota->jabatan == 'pengurus' ? 'selected' : '' }}>Pengurus</option> Anggota</option>
<option value="pelatih" {{ $anggota->jabatan == 'pelatih' ? 'selected' : '' }}>
Pelatih</option>
<option value="pengurus" {{ $anggota->jabatan == 'pengurus' ? 'selected' : '' }}>
Pengurus</option>
</select> </select>
</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>
<input type="text" name="tingkatan" class="form-control" value="{{ $anggota->tingkatan }}" required> <input type="text" name="tingkatan" class="form-control"
value="{{ $anggota->tingkatan }}" required>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<label class="form-label fw-bold">Status Anggota</label> <label class="form-label fw-bold">Status Anggota</label>
<select name="status" class="form-select" required> <select name="status" class="form-select" required>
<option value="Aktif" {{ $anggota->status == 'Aktif' ? 'selected' : '' }}>Aktif</option> <option value="Aktif" {{ $anggota->status == 'Aktif' ? 'selected' : '' }}>Aktif
<option value="Non-Aktif" {{ $anggota->status == 'Non-Aktif' ? 'selected' : '' }}>Non-Aktif</option> </option>
<option value="Non-Aktif" {{ $anggota->status == 'Non-Aktif' ? 'selected' : '' }}>
Non-Aktif</option>
</select> </select>
</div> </div>
<!-- BOX DATA SK (Otomatis muncul jika pilih Pelatih/Pengurus) --> <!-- BOX DATA SK (Otomatis muncul jika pilih Pelatih/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"
<h6 class="text-danger fw-bold mb-3"><i class="icon-certificate me-2"></i>Data Legalitas SK (Wajib diisi untuk Pelatih/Pengurus)</h6> 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-certificate me-2"></i>Data Legalitas
SK (Wajib diisi untuk Pelatih/Pengurus)</h6>
<div class="row g-3"> <div class="row g-3">
<div class="col-md-3"> <div class="col-md-3">
<label class="form-label small fw-bold">Nomor SK</label> <label class="form-label small fw-bold">Nomor SK</label>
<input type="text" name="no_sk" class="form-control" value="{{ $anggota->no_sk ?? '' }}" placeholder="Contoh: SK/001/2026"> <input type="text" name="no_sk" class="form-control"
value="{{ $anggota->no_sk ?? '' }}" placeholder="Contoh: SK/001/2026">
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<label class="form-label small fw-bold">Tanggal SK</label> <label class="form-label small fw-bold">Tanggal SK</label>
<input type="date" name="tgl_sk" class="form-control" value="{{ $anggota->tgl_sk ?? '' }}"> <input type="date" name="tgl_sk" class="form-control"
value="{{ $anggota->tgl_sk ?? '' }}">
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<label class="form-label small fw-bold">Masa Berlaku</label> <label class="form-label small fw-bold">Masa Berlaku</label>
<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</label>
<input type="file" name="foto_sk" class="form-control"> <input type="file" name="foto_sk" class="form-control">
@if($anggota->foto_sk) @if ($anggota->foto_sk)
<small class="text-muted mt-1 d-block">File: {{ $anggota->foto_sk }}</small> <small class="text-muted mt-1 d-block">File:
{{ $anggota->foto_sk }}</small>
@endif @endif
</div> </div>
</div> </div>
</div> </div>
<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>
<input type="text" name="asal_kolat" class="form-control" value="{{ $anggota->asal_kolat }}" required> <input type="text" name="asal_kolat" class="form-control" value="{{ $anggota->asal_kolat }}" required>
</div> --}}
<div class="col-md-12 mt-3">
<label class="form-label fw-bold">Asal Kolat</label>
<select name="kolat_id" class="form-select" required>
<option value="" disabled>-- Pilih Kolat --</option>
@foreach ($data_kolat as $kolat)
<option value="{{ $kolat->id }}"
{{ $anggota->kolat_id == $kolat->id ? 'selected' : '' }}>
{{ $kolat->nama_kolat }}
</option>
@endforeach
</select>
</div> </div>
</div> </div>
</div> </div>
@ -115,7 +147,8 @@
<!-- FOOTER CARD UNTUK BUTTON --> <!-- FOOTER CARD UNTUK BUTTON -->
<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 align-items-center gap-3"> <div class="d-flex justify-content-end align-items-center gap-3">
<a href="{{ route('anggota.anggota') }}" class="btn btn-outline-secondary px-4 fw-bold btn-cancel"> <a href="{{ route('anggota.anggota') }}"
class="btn btn-outline-secondary px-4 fw-bold btn-cancel">
<i class="icon-x me-1"></i> Batal <i class="icon-x me-1"></i> Batal
</a> </a>
<button type="submit" class="btn btn-primary px-5 fw-bold btn-save shadow"> <button type="submit" class="btn btn-primary px-5 fw-bold btn-save shadow">
@ -127,10 +160,10 @@
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!-- JAVASCRIPT TOGGLE --> <!-- JAVASCRIPT TOGGLE -->
<script> <script>
function toggleSKFields() { function toggleSKFields() {
const jabatan = document.getElementById('jabatanSelect').value; const jabatan = document.getElementById('jabatanSelect').value;
const boxSK = document.getElementById('boxSK'); const boxSK = document.getElementById('boxSK');
@ -146,36 +179,43 @@ function toggleSKFields() {
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
toggleSKFields(); toggleSKFields();
}); });
</script> </script>
<style> <style>
.form-control, .form-select { .form-control,
.form-select {
border-radius: 10px; border-radius: 10px;
padding: 10px 15px; padding: 10px 15px;
} }
.form-control:focus, .form-select:focus {
.form-control:focus,
.form-select:focus {
border-color: #0d6efd; border-color: #0d6efd;
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.1); box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.1);
} }
.btn-cancel { .btn-cancel {
border-radius: 12px; border-radius: 12px;
transition: all 0.3s ease; transition: all 0.3s ease;
border: 2px solid #6c757d; border: 2px solid #6c757d;
} }
.btn-cancel:hover { .btn-cancel:hover {
background-color: #6c757d; background-color: #6c757d;
color: white; color: white;
transform: translateY(-2px); transform: translateY(-2px);
} }
.btn-save { .btn-save {
border-radius: 12px; border-radius: 12px;
background: (45deg, #0d6efd); background: (45deg, #0d6efd);
border: none; border: none;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.btn-save:hover { .btn-save:hover {
transform: translateY(-2px); transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(13, 110, 253, 0.4) !important; box-shadow: 0 5px 15px rgba(13, 110, 253, 0.4) !important;
} }
</style> </style>
@endsection @endsection

View File

@ -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="{{ route('jadwal.index') }}"
class="text-muted text-decoration-none small">Daftar Jadwal</a></li>
<li class="breadcrumb-item active text-primary fw-bold small" aria-current="page">Edit Jadwal</li>
</ol>
</nav>
<h3 class="fw-bold text-dark">Edit Agenda Latihan</h3>
<p class="text-muted small">Perbarui detail waktu, lokasi, atau pelatih yang bertugas untuk agenda ini.</p>
</div>
<div class="row">
<div class="col-md-12">
<form action="{{ route('jadwal.update', $jadwal->id) }}" 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-primary mb-0"><i class="icon-calendar me-2"></i>Informasi Agenda</h5>
</div>
<div class="card-body p-4">
<div class="row g-3">
<div class="col-md-12">
<label class="form-label fw-bold">Judul Kegiatan / Materi Latihan</label>
<input type="text" name="judul_kegiatan" class="form-control"
value="{{ old('judul_kegiatan', $jadwal->judul_kegiatan) }}" required>
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Kelompok Latihan (Kolat)</label>
<select name="kolat_id" class="form-select" required>
@foreach($data_kolat as $kolat)
<option value="{{ $kolat->id }}" {{ $jadwal->kolat_id == $kolat->id ? 'selected' : '' }}>
{{ $kolat->nama_kolat }}
</option>
@endforeach
</select>
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Pelatih Bertugas</label>
<select name="pelatih_id" class="form-select" required>
@foreach($data_pelatih as $pelatih)
<option value="{{ $pelatih->id }}" {{ $jadwal->pelatih_id == $pelatih->id ? 'selected' : '' }}>
{{ $pelatih->nama_lengkap }}
</option>
@endforeach
</select>
</div>
<div class="col-md-4">
<label class="form-label fw-bold">Tanggal</label>
<input type="date" name="tanggal" class="form-control"
value="{{ old('tanggal', $jadwal->tanggal) }}" required>
</div>
<div class="col-md-4">
<label class="form-label fw-bold">Jam Mulai</label>
<input type="time" name="jam_mulai" class="form-control"
value="{{ old('jam_mulai', substr($jadwal->jam_mulai, 0, 5)) }}" required>
</div>
<div class="col-md-4">
<label class="form-label fw-bold">Jam Selesai (Opsional)</label>
<input type="time" name="jam_selesai" class="form-control"
value="{{ old('jam_selesai', $jadwal->jam_selesai ? substr($jadwal->jam_selesai, 0, 5) : '') }}">
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Lokasi / Tempat Latihan</label>
<input type="text" name="lokasi" class="form-control"
value="{{ old('lokasi', $jadwal->lokasi) }}" placeholder="Contoh: GOR Perjuangan" required>
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Tipe Agenda</label>
<select name="jenis" class="form-select" required>
<option value="Rutin" {{ $jadwal->jenis == 'Rutin' ? 'selected' : '' }}>Rutin</option>
<option value="Tambahan" {{ $jadwal->jenis == 'Tambahan' ? 'selected' : '' }}>Tambahan</option>
<option value="Pengumuman" {{ $jadwal->jenis == 'Pengumuman' ? 'selected' : '' }}>Pengumuman</option>
</select>
</div>
<div class="col-md-12">
<label class="form-label fw-bold">Deskripsi / Catatan Tambahan</label>
<textarea name="deskripsi" class="form-control" rows="3">{{ old('deskripsi', $jadwal->deskripsi) }}</textarea>
</div>
</div>
</div>
<div class="card-footer bg-light border-0 p-4" style="border-radius: 0 0 20px 20px;">
<div class="d-flex justify-content-between align-items-center">
<div class="small text-muted">
Status saat ini: <span class="badge bg-{{ $jadwal->status == 'selesai' ? 'success' : 'secondary' }}">{{ strtoupper($jadwal->status) }}</span>
</div>
<div class="d-flex gap-3">
<a href="{{ route('jadwal.index') }}" class="btn btn-outline-secondary px-4 fw-bold btn-cancel">
Batal
</a>
<button type="submit" class="btn btn-primary px-5 fw-bold btn-save shadow">
Simpan Perubahan
</button>
</div>
</div>
</div>
</div>
</form>
<div class="text-center mt-2">
<form action="{{ route('jadwal.destroy', $jadwal->id) }}" method="POST" onsubmit="return confirm('Hapus jadwal ini secara permanen?')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-link text-danger text-decoration-none small">
<i class="icon-trash"></i> Hapus Agenda Ini
</button>
</form>
</div>
</div>
</div>
</div>
<style>
.form-control, .form-select { border-radius: 10px; padding: 10px 15px; }
.btn-cancel { border-radius: 12px; transition: 0.3s; border: 2px solid #6c757d; }
.btn-save { border-radius: 12px; background: linear-gradient(45deg, #0d6efd, #004fb1); border: none; transition: 0.3s; }
.btn-save:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(13, 110, 253, 0.4) !important; }
</style>
@endsection

View File

@ -12,6 +12,13 @@
<h3 class="fw-bold text-dark">Manajemen Latihan TapakMP</h3> <h3 class="fw-bold text-dark">Manajemen Latihan TapakMP</h3>
</div> </div>
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show border-0 shadow-sm mb-4" role="alert" style="border-radius: 15px;">
<strong>Berhasil!</strong> {{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<div class="card border-0 shadow-sm" style="border-radius: 20px;"> <div class="card border-0 shadow-sm" style="border-radius: 20px;">
@ -32,32 +39,59 @@
<table class="table table-hover align-middle main-table"> <table class="table table-hover align-middle main-table">
<thead> <thead>
<tr> <tr>
<th width="60">No</th> <th width="50" class="text-center">No</th>
<th>Kegiatan & Deskripsi</th> <th>Kegiatan & Pelatih</th>
<th>Kolat</th> <th class="text-center">Status</th>
<th>Pelatih Bertugas</th>
<th>Waktu & Lokasi</th> <th>Waktu & Lokasi</th>
<th>Tipe</th> <th class="text-center">Tipe</th>
<th>Aksi</th> <th class="text-center" width="220">Aksi</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@forelse ($data_jadwal as $no => $item) @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
<tr> <tr>
<td class="text-muted small text-center">{{ $no + 1 }}</td> <td class="text-muted small text-center">{{ $no + 1 }}</td>
<td> <td>
<div class="fw-bold text-dark text-start ps-3">{{ $item->judul_kegiatan }}</div> <div class="fw-bold text-dark text-start ps-2">
<small class="text-muted text-start ps-3 d-block">{{ Str::limit($item->deskripsi, 40) }}</small> {{ $item->judul_kegiatan }}
@if($dbStatus == 'selesai')
<i class="bi bi-check-circle-fill text-success ms-1"></i>
@endif
</div>
<small class="text-muted text-start ps-2 d-block">
<i class="icon-user small"></i> {{ $item->pelatih->nama_lengkap ?? 'Belum Ditentukan' }}
</small>
</td> </td>
<td class="text-center"> <td class="text-center">
<span class="badge bg-light text-dark border px-3" style="border-radius: 8px;"> <span class="badge bg-{{ $status_color }} px-3 py-2" style="border-radius: 8px; font-size: 11px;">
{{ $item->kolat->nama_kolat ?? '-' }} {{ $status_label }}
</span> </span>
</td> </td>
<td class="text-center">
<div class="fw-bold text-dark small">{{ $item->pelatih->nama_lengkap ?? 'Belum Ditentukan' }}</div>
<small class="text-muted" style="font-size: 10px;">ID: {{ $item->pelatih->no_induk ?? '-' }}</small>
</td>
<td class="text-start ps-4"> <td class="text-start ps-4">
<div class="small fw-bold text-dark"> <div class="small fw-bold text-dark">
<i class="icon-calendar me-1"></i> {{ \Carbon\Carbon::parse($item->tanggal)->format('d M Y') }} <i class="icon-calendar me-1"></i> {{ \Carbon\Carbon::parse($item->tanggal)->format('d M Y') }}
@ -66,45 +100,52 @@
<i class="icon-clock me-1"></i> {{ substr($item->jam_mulai, 0, 5) }} - {{ $item->jam_selesai ? substr($item->jam_selesai, 0, 5) : 'Selesai' }} <i class="icon-clock me-1"></i> {{ substr($item->jam_mulai, 0, 5) }} - {{ $item->jam_selesai ? substr($item->jam_selesai, 0, 5) : 'Selesai' }}
</div> </div>
<div class="small text-muted text-truncate" style="max-width: 150px;"> <div class="small text-muted text-truncate" style="max-width: 150px;">
<i class="icon-map-pin me-1"></i> {{ $item->lokasi }} <i class="icon-map-pin me-1 text-danger"></i> {{ $item->lokasi }}
</div> </div>
</td> </td>
<td class="text-center"> <td class="text-center">
@php @php
$bg_color = 'bg-secondary-soft text-secondary'; $bg_type = 'bg-secondary-soft text-secondary';
if($item->jenis == 'Rutin') $bg_color = 'bg-success-soft text-success border-success'; if($item->jenis == 'Rutin') $bg_type = 'bg-success-soft text-success border-success';
elseif($item->jenis == 'Tambahan') $bg_color = 'bg-info-soft text-info border-info'; elseif($item->jenis == 'Tambahan') $bg_type = 'bg-info-soft text-info border-info';
elseif($item->jenis == 'Pengumuman') $bg_color = 'bg-danger-soft text-danger border-danger'; elseif($item->jenis == 'Pengumuman') $bg_type = 'bg-danger-soft text-danger border-danger';
@endphp @endphp
<span class="badge rounded-pill {{ $bg_color }} px-3 border"> <span class="badge rounded-pill {{ $bg_type }} px-3 border" style="font-size: 10px;">
{{ $item->jenis }} {{ $item->jenis }}
</span> </span>
</td> </td>
<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">
<button class="btn btn-sm btn-action-detail fw-bold px-3 shadow-xs"
data-bs-toggle="modal"
data-bs-target="#modalDetailJadwal{{ $item->id }}">
<i class="icon-eye"></i> Detail
</button>
@if($item->jenis != 'Pengumuman') {{-- TOMBOL KONFIRMASI: Muncul jika sudah masuk jamnya, bukan pengumuman, dan belum selesai --}}
<a href="#" class="btn btn-sm btn-outline-primary fw-bold px-3" style="border-radius: 10px;"> @if($dbStatus != 'selesai' && $item->jenis != 'Pengumuman' && $now->greaterThanOrEqualTo($start))
<i class="icon-check-square"></i> Absen <form action="{{ route('jadwal.konfirmasi', $item->id) }}" method="POST" id="form-selesai-{{ $item->id }}" class="d-inline">
</a> @csrf
<button type="button" class="btn btn-sm btn-success fw-bold px-2 shadow-xs"
style="border-radius: 10px;"
onclick="konfirmasiLatihan('{{ $item->id }}', '{{ $item->judul_kegiatan }}')">
<i class="bi bi-check2-square"></i>
</button>
</form>
@endif @endif
<button class="btn btn-sm btn-action-detail fw-bold px-2 shadow-xs"
data-bs-toggle="modal"
data-bs-target="#modalDetailJadwal{{ $item->id }}">
<i class="icon-eye"></i>
</button>
<a href="{{ route('jadwal.edit', $item->id) }}" <a href="{{ route('jadwal.edit', $item->id) }}"
class="btn btn-sm btn-action-edit fw-bold px-3 shadow-xs"> class="btn btn-sm btn-action-edit fw-bold px-2 shadow-xs">
<i class="icon-pencil"></i> <i class="icon-pencil"></i>
</a> </a>
</div> </div>
</td> </td>
</tr> </tr>
{{-- MODAL DETAIL JADWAL (Identik dengan Modal Anggota) --}} {{-- MODAL DETAIL JADWAL --}}
<div class="modal fade" id="modalDetailJadwal{{ $item->id }}" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="modalDetailJadwal{{ $item->id }}" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg"> <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-lg">
<div class="modal-content" style="border-radius: 20px; border: none; overflow: hidden;"> <div class="modal-content" style="border-radius: 20px; border: none; overflow: hidden;">
<div class="modal-header bg-primary text-white border-0 py-3 px-4"> <div class="modal-header bg-primary text-white border-0 py-3 px-4">
<h5 class="modal-title fw-bold"> <h5 class="modal-title fw-bold">
@ -117,48 +158,27 @@ class="btn btn-sm btn-action-edit fw-bold px-3 shadow-xs">
<div class="col-md-4 text-center border-end"> <div class="col-md-4 text-center border-end">
<div class="mb-3"> <div class="mb-3">
<div class="bg-light rounded-circle d-inline-flex align-items-center justify-content-center shadow-sm" <div class="bg-light rounded-circle d-inline-flex align-items-center justify-content-center shadow-sm"
style="width: 120px; height: 120px; border: 4px solid #f8f9fa;"> style="width: 100px; height: 100px; border: 4px solid #f8f9fa;">
<i class="icon-clipboard text-primary" style="font-size: 60px;"></i> <i class="icon-clipboard text-primary" style="font-size: 50px;"></i>
</div> </div>
</div> </div>
<h5 class="fw-bold mb-1">{{ $item->judul_kegiatan }}</h5> <h5 class="fw-bold mb-1 text-dark">{{ $item->judul_kegiatan }}</h5>
<p class="text-muted small mb-3">ID Jadwal: #JDL-{{ $item->id }}</p> <p class="text-muted small mb-3">Status: <span class="text-{{ $status_color }} fw-bold">{{ strtoupper($status_label) }}</span></p>
<span class="badge rounded-pill {{ $bg_color }} px-4 py-2 border shadow-xs">
{{ $item->jenis }}
</span>
</div> </div>
<div class="col-md-8 ps-md-4 text-start"> <div class="col-md-8 ps-md-4 text-start">
<div class="row g-3"> <div class="row g-3">
<div class="col-12">
<h6 class="fw-bold text-primary mb-3 border-bottom pb-2">Informasi Pelaksanaan</h6>
</div>
<div class="col-6"> <div class="col-6">
<small class="text-muted d-block">Pelatih Bertugas</small> <small class="text-muted d-block small">Pelatih</small>
<span class="fw-bold text-dark">{{ $item->pelatih->nama_lengkap ?? '-' }}</span> <span class="fw-bold text-dark">{{ $item->pelatih->nama_lengkap ?? '-' }}</span>
</div> </div>
<div class="col-6"> <div class="col-6">
<small class="text-muted d-block">Kelompok Latihan (Kolat)</small> <small class="text-muted d-block small">Kolat</small>
<span class="fw-bold text-dark">{{ $item->kolat->nama_kolat ?? '-' }}</span> <span class="fw-bold text-dark">{{ $item->kolat->nama_kolat ?? '-' }}</span>
</div> </div>
<div class="col-6"> <div class="col-12 mt-3">
<small class="text-muted d-block">Hari & Tanggal</small> <h6 class="fw-bold text-primary border-bottom pb-1 small">Deskripsi Kegiatan</h6>
<span class="fw-bold text-dark">{{ \Carbon\Carbon::parse($item->tanggal)->translatedFormat('l, d F Y') }}</span> <p class="small text-muted mb-0" style="white-space: pre-line;">{{ $item->deskripsi ?? 'Tidak ada deskripsi.' }}</p>
</div>
<div class="col-6">
<small class="text-muted d-block">Waktu</small>
<span class="fw-bold text-dark">{{ substr($item->jam_mulai, 0, 5) }} - {{ $item->jam_selesai ? substr($item->jam_selesai, 0, 5) : 'Selesai' }} WIB</span>
</div>
<div class="col-12">
<small class="text-muted d-block">Lokasi Tempat</small>
<span class="fw-bold text-dark"><i class="icon-map-pin me-1 text-danger"></i>{{ $item->lokasi }}</span>
</div>
<div class="col-12 mt-4">
<h6 class="fw-bold text-primary mb-3 border-bottom pb-2">Deskripsi & Catatan</h6>
<div class="p-3 rounded-3" style="background-color: #f8faff; border: 1px solid #edf2f9;">
<p class="mb-0 text-dark small" style="white-space: pre-line;">{{ $item->deskripsi ?? 'Tidak ada deskripsi tambahan untuk agenda ini.' }}</p>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -166,14 +186,13 @@ class="btn btn-sm btn-action-edit fw-bold px-3 shadow-xs">
</div> </div>
<div class="modal-footer border-0 px-4 pb-4"> <div class="modal-footer border-0 px-4 pb-4">
<button type="button" class="btn btn-light px-4" data-bs-dismiss="modal" style="border-radius: 10px;">Tutup</button> <button type="button" class="btn btn-light px-4" data-bs-dismiss="modal" style="border-radius: 10px;">Tutup</button>
<a href="{{ route('jadwal.edit', $item->id) }}" class="btn btn-warning text-white px-4" style="border-radius: 10px;">Edit Jadwal</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@empty @empty
<tr> <tr>
<td colspan="7" class="text-center py-5 text-muted small">Belum ada jadwal latihan atau pengumuman.</td> <td colspan="6" class="text-center py-5 text-muted small">Belum ada jadwal latihan atau pengumuman.</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>
@ -187,22 +206,38 @@ class="btn btn-sm btn-action-edit fw-bold px-3 shadow-xs">
</div> </div>
<style> <style>
.main-table thead th { background-color: #f8faff; padding: 18px 10px; font-size: 0.75rem; color: #8c98a5; letter-spacing: 1px; text-transform: uppercase; border-bottom: 2px solid #edf2f9; } .main-table thead th { background-color: #f8faff; padding: 15px 10px; font-size: 0.7rem; 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; } .main-table tbody td { padding: 15px 10px; border-bottom: 1px solid #f1f4f8; color: #495057; font-size: 0.85rem; }
/* Soft Badges */
.bg-success-soft { background-color: #e6fffa; color: #38b2ac; } .bg-success-soft { background-color: #e6fffa; color: #38b2ac; }
.bg-info-soft { background-color: #e0f2fe; color: #0ea5e9; } .bg-info-soft { background-color: #e0f2fe; color: #0ea5e9; }
.bg-danger-soft { background-color: #fff5f5; color: #e53e3e; } .bg-danger-soft { background-color: #fff5f5; color: #e53e3e; }
.bg-secondary-soft { background-color: #f3f4f6; color: #6b7280; } .bg-secondary-soft { background-color: #f3f4f6; color: #6b7280; }
/* Buttons Action */
.btn-action-detail { background-color: #f0f7ff; color: #0d6efd; border: 1px solid #d0e4ff; border-radius: 10px; transition: 0.3s; } .btn-action-detail { background-color: #f0f7ff; color: #0d6efd; border: 1px solid #d0e4ff; border-radius: 10px; transition: 0.3s; }
.btn-action-edit { background-color: #fff8e6; color: #f59e0b; border: 1px solid #ffecb3; border-radius: 10px; transition: 0.3s; } .btn-action-edit { background-color: #fff8e6; color: #f59e0b; border: 1px solid #ffecb3; border-radius: 10px; transition: 0.3s; }
.btn-action-edit:hover { background-color: #f59e0b !important; color: white !important; transform: translateY(-2px); } .btn-action-edit:hover { background-color: #f59e0b !important; color: white !important; transform: translateY(-2px); }
.btn-action-detail:hover { background-color: #0d6efd !important; color: white !important; transform: translateY(-2px); } .btn-action-detail:hover { background-color: #0d6efd !important; color: white !important; transform: translateY(-2px); }
.shadow-xs { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } .shadow-xs { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); }
</style> </style>
<script>
function konfirmasiLatihan(id, judul) {
Swal.fire({
title: 'Konfirmasi Selesai',
text: "Apakah benar latihan '" + judul + "' telah dilaksanakan?",
icon: 'question',
showCancelButton: true,
confirmButtonColor: '#198754', // Warna hijau sukses
cancelButtonColor: '#6c757d',
confirmButtonText: 'Ya, Sudah Selesai!',
cancelButtonText: 'Batal',
border: 'none',
borderRadius: '20px'
}).then((result) => {
if (result.isConfirmed) {
// Submit form jika user klik OK
document.getElementById('form-selesai-' + id).submit();
}
})
}
</script>
@endsection @endsection

View File

@ -100,5 +100,7 @@
</script> </script>
@endif @endif
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
</body> </body>
</html> </html>

View File

@ -0,0 +1,147 @@
@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="{{ route('pelatih.index') }}"
class="text-muted text-decoration-none small">Daftar Pelatih</a></li>
<li class="breadcrumb-item active text-primary fw-bold small" aria-current="page">Edit Data Pelatih</li>
</ol>
</nav>
<h3 class="fw-bold text-dark">Form Edit Data Pelatih</h3>
<p class="text-muted small">Perbarui informasi legalitas SK atau status kepelatihan untuk <strong>{{ $pelatih->nama_lengkap }}</strong>.</p>
</div>
<div class="row">
<div class="col-md-12">
<form action="{{ route('pelatih.update', $pelatih->id) }}" method="POST" enctype="multipart/form-data">
@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-primary mb-0"><i class="icon-user me-2"></i>Identitas Pelatih</h5>
</div>
<div class="card-body p-4">
<div class="row g-3">
<div class="col-md-4">
<label class="form-label fw-bold">No Induk</label>
<input type="text" class="form-control bg-light fw-bold"
value="{{ $pelatih->no_induk }}" readonly>
</div>
<div class="col-md-4">
<label class="form-label fw-bold">Nama Lengkap</label>
<input type="text" class="form-control bg-light"
value="{{ $pelatih->nama_lengkap }}" readonly>
</div>
<div class="col-md-4">
<label class="form-label fw-bold">Asal Kolat</label>
<input type="text" class="form-control bg-light"
value="{{ $pelatih->kolat->nama_kolat ?? '-' }}" readonly>
</div>
</div>
<small class="text-muted mt-2 d-block">* Data identitas di atas bersifat tetap. Ubah di menu Anggota jika terdapat kesalahan input nama/induk.</small>
</div>
</div>
<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-danger mb-0"><i class="icon-certificate me-2"></i>Legalitas & Masa Aktif SK</h5>
</div>
<div class="card-body p-4">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label fw-bold">Nomor SK Kepelatihan</label>
<input type="text" name="no_sk" class="form-control border-danger"
value="{{ old('no_sk', $pelatih->no_sk) }}" placeholder="Contoh: SK/001/2026" required>
@error('no_sk') <small class="text-danger">{{ $message }}</small> @enderror
</div>
<div class="col-md-3">
<label class="form-label fw-bold">Tanggal Terbit SK</label>
<input type="date" name="tgl_sk" class="form-control"
value="{{ old('tgl_sk', $pelatih->tgl_sk) }}" required>
</div>
<div class="col-md-3">
<label class="form-label fw-bold">Masa Berlaku</label>
<input type="date" name="masa_berlaku" class="form-control"
value="{{ old('masa_berlaku', $pelatih->masa_berlaku) }}" required>
</div>
<div class="col-md-12 mt-4">
<div class="p-3 bg-light rounded-4 border">
<label class="form-label fw-bold d-block">Update Scan SK (Format: JPG, PNG, PDF | Max: 2MB)</label>
<input type="file" name="foto_sk" class="form-control mb-2">
@if ($pelatih->foto_sk)
<div class="d-flex align-items-center mt-2">
<i class="icon-file-text text-primary me-2"></i>
<small class="text-muted">File saat ini:
<a href="{{ asset('storage/' . $pelatih->foto_sk) }}" target="_blank" class="text-decoration-none">
Lihat Dokumen SK <i class="icon-external-link"></i>
</a>
</small>
</div>
@else
<small class="text-warning">Belum ada file SK yang diunggah.</small>
@endif
</div>
</div>
</div>
</div>
<div class="card-footer bg-light border-0 p-4" style="border-radius: 0 0 20px 20px;">
<div class="d-flex justify-content-end align-items-center gap-3">
<a href="{{ route('pelatih.index') }}"
class="btn btn-outline-secondary px-4 fw-bold btn-cancel">
<i class="icon-x me-1"></i> Batal
</a>
<button type="submit" class="btn btn-primary px-5 fw-bold btn-save shadow">
<i class="icon-check me-1"></i> Simpan Perubahan SK
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<style>
.form-control,
.form-select {
border-radius: 10px;
padding: 10px 15px;
}
.form-control:focus {
border-color: #0d6efd;
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.1);
}
.btn-cancel {
border-radius: 12px;
transition: all 0.3s ease;
border: 2px solid #6c757d;
}
.btn-cancel:hover {
background-color: #6c757d;
color: white;
transform: translateY(-2px);
}
.btn-save {
border-radius: 12px;
background: linear-gradient(45deg, #0d6efd, #004fb1);
border: none;
transition: all 0.3s ease;
}
.btn-save:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(13, 110, 253, 0.4) !important;
}
</style>
@endsection

View File

@ -30,7 +30,7 @@
</div> </div>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover align-middle main-table"> <table class="table table-hover align-middle main-table text-center">
<thead> <thead>
<tr> <tr>
<th width="60">No</th> <th width="60">No</th>
@ -46,10 +46,10 @@
<tr> <tr>
<td class="text-muted small text-center">{{ $no + 1 }}</td> <td class="text-muted small text-center">{{ $no + 1 }}</td>
<td> <td>
<div class="fw-bold text-dark text-start">{{ $item->nama_lengkap }}</div> <div class="fw-bold text-dark text-start text-center">{{ $item->nama_lengkap }}</div>
<small class="text-muted text-start d-block">ID: {{ $item->no_induk }}</small> <small class="text-muted text-start d-block text-center">ID: {{ $item->no_induk }}</small>
</td> </td>
<td class="text-start"> <td class="text-start text-center">
<div class="small fw-bold">{{ $item->no_sk }}</div> <div class="small fw-bold">{{ $item->no_sk }}</div>
<div class="text-muted" style="font-size: 11px;">Hingga: {{ \Carbon\Carbon::parse($item->masa_berlaku)->format('d M Y') }}</div> <div class="text-muted" style="font-size: 11px;">Hingga: {{ \Carbon\Carbon::parse($item->masa_berlaku)->format('d M Y') }}</div>
</td> </td>

View File

@ -0,0 +1,83 @@
@extends('layout.app')
@section('content')
<div class="container-fluid py-4">
<div class="page-header mb-4 text-start">
<h3 class="fw-bold text-dark">Kehadiran Latihan</h3>
<p class="text-muted small">Silakan lakukan absensi mandiri untuk jadwal hari ini.</p>
</div>
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show border-0 shadow-sm rounded-3 mb-4">
<i class="bi bi-check-circle-fill me-2"></i> {{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
@if(session('error'))
<div class="alert alert-danger alert-dismissible fade show border-0 shadow-sm rounded-3 mb-4">
<i class="bi bi-exclamation-circle-fill me-2"></i> {{ session('error') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
<div class="row">
@forelse($jadwal_hari_ini as $jadwal)
<div class="col-md-6 col-lg-4 mb-4">
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
<div class="card-body p-4">
<div class="d-flex justify-content-between align-items-start mb-3">
<span class="badge bg-primary-soft text-primary px-3 py-2 rounded-pill shadow-xs">
{{ $jadwal->jenis }}
</span>
<span class="small fw-bold text-muted">{{ \Carbon\Carbon::parse($jadwal->tanggal)->format('d M Y') }}</span>
</div>
<h5 class="fw-bold text-dark mb-1">{{ $jadwal->judul_kegiatan }}</h5>
<p class="small text-muted mb-3"><i class="bi bi-person-fill me-1"></i> Pelatih: {{ $jadwal->pelatih->nama_lengkap ?? '-' }}</p>
<div class="bg-light p-3 rounded-3 mb-4">
<div class="small fw-bold text-dark mb-1"><i class="bi bi-clock me-2 text-primary"></i>{{ substr($jadwal->jam_mulai, 0, 5) }} - Selesai</div>
<div class="small text-muted"><i class="bi bi-geo-alt-fill me-2 text-danger"></i>{{ $jadwal->lokasi }}</div>
</div>
{{-- LOGIKA TOMBOL ABSEN --}}
@if(isset($presensi_saya[$jadwal->id]))
{{-- Jika sudah absen --}}
@if($presensi_saya[$jadwal->id]->is_verified)
<button class="btn btn-success w-100 fw-bold disabled py-2" style="border-radius: 12px;">
<i class="bi bi-check2-all me-1"></i> Kehadiran Disahkan
</button>
@else
<button class="btn btn-warning w-100 fw-bold disabled py-2" style="border-radius: 12px; color: #854d0e; background-color: #fef08a; border:none;">
<i class="bi bi-hourglass-split me-1"></i> Menunggu Konfirmasi
</button>
@endif
@else
{{-- Jika belum absen, tampilkan tombol submit --}}
<form action="{{ route('anggota.presensi.store') }}" method="POST">
@csrf
<input type="hidden" name="jadwal_id" value="{{ $jadwal->id }}">
<button type="submit" class="btn btn-primary w-100 fw-bold py-2 shadow-sm" style="border-radius: 12px;" onclick="return confirm('Apakah kamu yakin ingin absen untuk jadwal ini?')">
<i class="bi bi-hand-index-thumb me-1"></i> Absen Sekarang
</button>
</form>
@endif
</div>
</div>
</div>
@empty
<div class="col-12 text-center py-5">
<img src="https://cdn-icons-png.flaticon.com/512/7486/7486747.png" width="120" class="mb-3 opacity-50" alt="No Schedule">
<h5 class="text-muted fw-bold">Tidak ada jadwal latihan hari ini.</h5>
<p class="text-muted small">Selamat istirahat atau berlatih mandiri di rumah!</p>
</div>
@endforelse
</div>
</div>
<style>
.bg-primary-soft { background-color: #e0f2fe; color: #0ea5e9; }
</style>
@endsection

View File

@ -0,0 +1,149 @@
@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">Presensi Latihan</li>
</ol>
</nav>
<h3 class="fw-bold text-dark">Rekap Presensi Latihan</h3>
</div>
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show border-0 shadow-sm mb-4" role="alert" style="border-radius: 15px;">
<strong>Berhasil!</strong> {{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
<div class="row">
<div class="col-12">
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
<div class="card-body p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="text-start">
<h5 class="card-title mb-0 fw-bold text-dark">Pilih Jadwal Latihan</h5>
<p class="text-muted small mb-0">Klik tombol cek kehadiran untuk memverifikasi absen anggota dan upload bukti latihan.</p>
</div>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle main-table">
<thead>
<tr>
<th width="50" class="text-center">No</th>
<th>Kegiatan & Pelatih</th>
<th class="text-center">Status Jadwal</th>
<th>Waktu & Lokasi</th>
<th class="text-center">Tipe</th>
<th class="text-center" width="150">Aksi</th>
</tr>
</thead>
<tbody>
@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
<tr>
<td class="text-muted small text-center">{{ $no + 1 }}</td>
<td>
<div class="fw-bold text-dark text-start ps-2">
{{ $item->judul_kegiatan }}
@if($dbStatus == 'selesai')
<i class="bi bi-check-circle-fill text-success ms-1"></i>
@endif
</div>
<small class="text-muted text-start ps-2 d-block">
{{-- Pemanggilan dari Query Builder Manual --}}
<i class="icon-user small"></i> {{ $item->nama_pelatih ?? 'Belum Ditentukan' }}
</small>
</td>
<td class="text-center">
<span class="badge bg-{{ $status_color }} px-3 py-2" style="border-radius: 8px; font-size: 11px;">
{{ $status_label }}
</span>
</td>
<td class="text-start ps-4">
<div class="small fw-bold text-dark">
<i class="icon-calendar me-1"></i> {{ \Carbon\Carbon::parse($item->tanggal)->format('d M Y') }}
</div>
<div class="small text-muted">
<i class="icon-clock me-1"></i> {{ substr($item->jam_mulai, 0, 5) }} - {{ $item->jam_selesai ? substr($item->jam_selesai, 0, 5) : 'Selesai' }}
</div>
<div class="small text-muted text-truncate" style="max-width: 150px;">
<i class="icon-map-pin me-1 text-danger"></i> {{ $item->lokasi }}
</div>
</td>
<td class="text-center">
@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
<span class="badge rounded-pill {{ $bg_type }} px-3 border" style="font-size: 10px;">
{{ $item->jenis }}
</span>
</td>
<td class="text-center">
{{-- Tombol Cek Kehadiran --}}
<a href="{{ route('presensi.kehadiran', $item->id) }}"
class="btn btn-sm btn-info fw-bold px-3 shadow-xs text-white"
style="border-radius: 10px;">
<i class="bi bi-person-check-fill me-1"></i> Cek Kehadiran
</a>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="text-center py-5 text-muted small">Belum ada jadwal latihan tersedia.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.main-table thead th { background-color: #f8faff; padding: 15px 10px; font-size: 0.7rem; color: #8c98a5; letter-spacing: 1px; text-transform: uppercase; border-bottom: 2px solid #edf2f9; }
.main-table tbody td { padding: 15px 10px; border-bottom: 1px solid #f1f4f8; color: #495057; font-size: 0.85rem; }
.bg-success-soft { background-color: #e6fffa; color: #38b2ac; }
.bg-info-soft { background-color: #e0f2fe; color: #0ea5e9; }
.bg-danger-soft { background-color: #fff5f5; color: #e53e3e; }
.bg-secondary-soft { background-color: #f3f4f6; color: #6b7280; }
.shadow-xs { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); }
.btn-info { background-color: #0ea5e9; border: none; transition: 0.3s; }
.btn-info:hover { background-color: #0284c7; transform: translateY(-2px); }
</style>
@endsection

View File

@ -0,0 +1,193 @@
@extends('layout.app')
@section('content')
<div class="container-fluid py-4">
<div class="page-header mb-4 text-start">
<nav aria-label="breadcrumb">
<ol class="breadcrumb bg-transparent p-0 mb-2">
<li class="breadcrumb-item"><a href="#" class="text-muted text-decoration-none small">Home</a></li>
<li class="breadcrumb-item"><a href="{{ route('presensi.index') }}" class="text-muted text-decoration-none small">Presensi Latihan</a></li>
<li class="breadcrumb-item active text-primary fw-bold small" aria-current="page">Verifikasi Kehadiran</li>
</ol>
</nav>
<h3 class="fw-bold text-dark">Verifikasi Kehadiran Anggota</h3>
</div>
{{-- Menampilkan Pesan Sukses --}}
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show border-0 shadow-sm mb-4" role="alert" style="border-radius: 15px;">
<strong>Berhasil!</strong> {{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
{{-- Menampilkan Pesan Error (Misal: Input manual ganda) --}}
@if(session('error'))
<div class="alert alert-danger alert-dismissible fade show border-0 shadow-sm mb-4" role="alert" style="border-radius: 15px;">
<strong>Gagal!</strong> {{ session('error') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
{{-- KARTU INFORMASI JADWAL --}}
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-sm" style="border-radius: 20px; background: linear-gradient(135deg, #0ea5e9 0%, #0284c7 100%);">
<div class="card-body p-4 text-white">
<div class="row align-items-center">
<div class="col-md-8">
<h5 class="fw-bold mb-1">{{ $jadwal->judul_kegiatan }}</h5>
<p class="mb-0 small" style="opacity: 0.9;">
<i class="icon-map-pin me-1"></i> {{ $jadwal->lokasi }} |
<i class="icon-calendar me-1"></i> {{ \Carbon\Carbon::parse($jadwal->tanggal)->format('d M Y') }} |
<i class="icon-clock me-1"></i> {{ substr($jadwal->jam_mulai, 0, 5) }} - {{ $jadwal->jam_selesai ? substr($jadwal->jam_selesai, 0, 5) : 'Selesai' }}
</p>
</div>
<div class="col-md-4 text-md-end mt-3 mt-md-0">
<span class="badge bg-white text-primary px-3 py-2 rounded-pill shadow-sm">
Kolat: {{ $jadwal->kolat->nama_kolat ?? '-' }}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
{{-- TABEL PRESENSI --}}
<div class="row">
<div class="col-12">
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
<div class="card-body p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="text-start">
<h5 class="card-title mb-0 fw-bold text-dark">Daftar Absensi Masuk</h5>
<p class="text-muted small mb-0">Klik konfirmasi untuk mensahkan kehadiran anggota.</p>
</div>
{{-- Tombol Buka Modal Tambah Manual --}}
<button class="btn btn-primary px-4 py-2 shadow-sm" style="border-radius: 12px;" data-bs-toggle="modal" data-bs-target="#modalTambahManual">
<i class="bi bi-plus-lg me-1"></i> Tambah Manual
</button>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle main-table">
<thead>
<tr>
<th width="60" class="text-center">No</th>
<th>Identitas Anggota</th>
<th class="text-center">Waktu Absen</th>
<th class="text-center">Status Verifikasi</th>
<th class="text-center" width="180">Aksi</th>
</tr>
</thead>
<tbody>
@forelse ($data_presensi as $no => $item)
<tr>
<td class="text-muted small text-center">{{ $no + 1 }}</td>
<td>
<div class="fw-bold text-dark text-start ps-2">{{ $item->anggota->nama_lengkap }}</div>
<small class="text-muted text-start ps-2 d-block">ID: {{ $item->anggota->no_induk }}</small>
</td>
<td class="text-center">
<span class="badge bg-light text-dark border px-3" style="border-radius: 8px;">
<i class="icon-clock me-1 text-primary"></i> {{ \Carbon\Carbon::parse($item->waktu_presensi)->format('H:i') }} WIB
</span>
</td>
<td class="text-center">
@if($item->is_verified)
<span class="badge bg-success-soft text-success border-success px-3 border rounded-pill">
<i class="bi bi-check-circle-fill me-1"></i> Sah
</span>
<div class="small text-muted mt-1" style="font-size: 10px;">
Oleh: {{ $item->pelatihVerifikator->nama_lengkap ?? 'Pelatih' }}
</div>
@else
<span class="badge bg-warning text-dark px-3 rounded-pill shadow-xs">
<i class="bi bi-hourglass-split me-1"></i> Menunggu
</span>
@endif
</td>
<td class="text-center">
@if(!$item->is_verified)
{{-- Tombol Konfirmasi Hadir --}}
<form action="{{ route('presensi.konfirmasi', $item->id) }}" method="POST" class="d-inline">
@csrf
<button type="submit" class="btn btn-sm btn-action-edit fw-bold px-3 shadow-xs" onclick="return confirm('Konfirmasi kehadiran anggota ini?')">
<i class="bi bi-check2-square me-1"></i> Konfirmasi
</button>
</form>
@else
<button class="btn btn-sm btn-light fw-bold px-3 text-muted border disabled" style="border-radius: 10px;">
Selesai
</button>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5" class="text-center py-5 text-muted small">Belum ada anggota yang melakukan absensi masuk.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
{{-- MODAL TAMBAH MANUAL (KASUS LUPA HP) --}}
<div class="modal fade" id="modalTambahManual" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content" style="border-radius: 20px; border: none; overflow: hidden;">
<div class="modal-header bg-primary text-white border-0 py-3 px-4">
<h5 class="modal-title fw-bold">
<i class="bi bi-person-plus-fill me-2"></i>Input Presensi Manual
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="{{ route('presensi.storeManual') }}" method="POST">
@csrf
{{-- Hidden input untuk ID Jadwal --}}
<input type="hidden" name="jadwal_id" value="{{ $jadwal->id }}">
<div class="modal-body p-4">
<div class="alert alert-info border-0 shadow-sm small" style="border-radius: 10px;">
<i class="bi bi-info-circle-fill me-2"></i> Gunakan form ini untuk anggota yang lupa membawa perangkat atau tidak bisa absen mandiri.
</div>
<div class="mb-3 text-start">
<label class="form-label fw-bold text-dark small">Pilih Nama Anggota</label>
<select name="anggota_id" class="form-select shadow-none" style="border-radius: 10px; border-color: #d0e4ff;" required>
<option value="">-- Silakan Pilih Anggota --</option>
@foreach($daftar_anggota as $anggota)
<option value="{{ $anggota->id }}">{{ $anggota->no_induk }} - {{ $anggota->nama_lengkap }}</option>
@endforeach
</select>
</div>
</div>
<div class="modal-footer border-0 px-4 pb-4 d-flex justify-content-between">
<button type="button" class="btn btn-light px-4 shadow-sm" data-bs-dismiss="modal" style="border-radius: 10px;">Batal</button>
<button type="submit" class="btn btn-success px-4 shadow-sm" style="border-radius: 10px;">
<i class="bi bi-check-lg me-1"></i> Simpan & Sahkan
</button>
</div>
</form>
</div>
</div>
</div>
<style>
.main-table thead th { background-color: #f8faff; padding: 18px 10px; font-size: 0.75rem; color: #8c98a5; letter-spacing: 1px; text-transform: uppercase; border-bottom: 2px solid #edf2f9; }
.main-table tbody td { padding: 20px 10px; border-bottom: 1px solid #f1f4f8; color: #495057; font-size: 0.9rem; }
.bg-success-soft { background-color: #e6fffa; color: #38b2ac; }
.btn-action-edit { background-color: #f0f7ff; color: #0d6efd; border: 1px solid #d0e4ff; border-radius: 10px; transition: 0.3s; }
.btn-action-edit:hover { background-color: #0d6efd !important; color: white !important; transform: translateY(-2px); }
.shadow-xs { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); }
</style>
@endsection

View File

@ -4,6 +4,7 @@
use App\Http\Controllers\JadwalController; use App\Http\Controllers\JadwalController;
use App\Http\Controllers\KolatController; use App\Http\Controllers\KolatController;
use App\Http\Controllers\PelatihController; use App\Http\Controllers\PelatihController;
use App\Http\Controllers\PresensiController;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@ -64,6 +65,7 @@
//prefix diguakan untuk mengelompokkan route yang berhubungan dengan jadwal //prefix diguakan untuk mengelompokkan route yang berhubungan dengan jadwal
Route::prefix('jadwal')->group(function () { Route::prefix('jadwal')->group(function () {
Route::get('/', [JadwalController::class, 'index'])->name('jadwal.index'); 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('/create', [JadwalController::class, 'create'])->name('jadwal.create');
Route::get('/{id}/detail', [JadwalController::class, 'show'])->name('jadwal.show'); Route::get('/{id}/detail', [JadwalController::class, 'show'])->name('jadwal.show');
Route::post('/store', [JadwalController::class, 'store'])->name('jadwal.store'); Route::post('/store', [JadwalController::class, 'store'])->name('jadwal.store');
@ -72,3 +74,14 @@
Route::delete('/{id}/delete', [JadwalController::class, 'destroy'])->name('jadwal.destroy'); 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');
});