presensi
This commit is contained in:
parent
03fa985785
commit
50a5d55169
|
|
@ -84,7 +84,7 @@ public function store(Request $request)
|
||||||
'alamat' => $request->alamat,
|
'alamat' => $request->alamat,
|
||||||
'catatan_medis' => $request->catatan_medis,
|
'catatan_medis' => $request->catatan_medis,
|
||||||
'jabatan' => $nama_jabatan,
|
'jabatan' => $nama_jabatan,
|
||||||
'status' => 'aktif', // Input admin otomatis aktif
|
'status' => 'Aktif', // Input admin otomatis aktif
|
||||||
]);
|
]);
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
|
|
@ -120,7 +120,7 @@ public function update(Request $request, $id)
|
||||||
'no_hp' => 'required',
|
'no_hp' => 'required',
|
||||||
'role_id' => 'required|exists:role,id',
|
'role_id' => 'required|exists:role,id',
|
||||||
'kolat_id' => 'required|exists:kolat,id',
|
'kolat_id' => 'required|exists:kolat,id',
|
||||||
'status' => 'required|in:aktif,Non-Aktif',
|
'status' => 'required|in:Aktif,Non-Aktif',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,17 @@
|
||||||
use App\Models\Jadwal;
|
use App\Models\Jadwal;
|
||||||
use App\Models\Kolat;
|
use App\Models\Kolat;
|
||||||
use App\Models\Anggota;
|
use App\Models\Anggota;
|
||||||
use App\Models\Role;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class JadwalController extends Controller
|
class JadwalController extends Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// 1. Menampilkan Daftar Jadwal
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$data_jadwal = Jadwal::with(['kolat', 'pelatih'])
|
// Tambahkan 'presensi.anggota' agar modal konfirmasi bisa nampilin siapa aja yang hadir
|
||||||
|
$data_jadwal = Jadwal::with(['kolat', 'pelatih', 'presensi.anggota'])
|
||||||
->orderBy('tanggal', 'desc')
|
->orderBy('tanggal', 'desc')
|
||||||
->orderBy('jam_mulai', 'desc')
|
->orderBy('jam_mulai', 'desc')
|
||||||
->get();
|
->get();
|
||||||
|
|
@ -21,33 +23,49 @@ public function index()
|
||||||
return view('jadwal.jadwal', compact('data_jadwal'));
|
return view('jadwal.jadwal', compact('data_jadwal'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function konfirmasiSelesai($id)
|
// 2. Proses Konfirmasi Latihan Selesai (Update Status + Upload Foto Kegiatan)
|
||||||
{
|
public function konfirmasiSelesai(Request $request, $id)
|
||||||
|
{
|
||||||
$jadwal = Jadwal::findOrFail($id);
|
$jadwal = Jadwal::findOrFail($id);
|
||||||
|
|
||||||
// Kita paksa ubah status ke 'selesai'
|
// Validasi input dari modal
|
||||||
|
$request->validate([
|
||||||
|
'foto_bukti' => 'required|image|mimes:jpg,jpeg,png|max:2048',
|
||||||
|
'catatan_latihan' => 'nullable|string'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Proses upload foto kegiatan pelatih ke folder storage/app/public/kegiatan_pelatih
|
||||||
|
if ($request->hasFile('foto_bukti')) {
|
||||||
|
$path = $request->file('foto_bukti')->store('kegiatan_pelatih', 'public');
|
||||||
|
$jadwal->foto_bukti = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simpan catatan dan ubah status menjadi selesai
|
||||||
|
$jadwal->catatan_latihan = $request->catatan_latihan;
|
||||||
$jadwal->status = 'selesai';
|
$jadwal->status = 'selesai';
|
||||||
$jadwal->save();
|
$jadwal->save();
|
||||||
|
|
||||||
return redirect()->route('jadwal.index')
|
return redirect()->route('jadwal.index')
|
||||||
->with('success', 'Latihan ' . $jadwal->judul_kegiatan . ' telah dikonfirmasi selesai!');
|
->with('success', 'Latihan ' . $jadwal->judul_kegiatan . ' telah dikonfirmasi selesai!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 3. Menampilkan Form Tambah Jadwal
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
$data_kolat = Kolat::all();
|
$data_kolat = Kolat::all();
|
||||||
$rolePelatih = Role::where('nama_role', 'Pelatih')->first();
|
|
||||||
|
|
||||||
// Ambil Anggota yang memiliki role 'Pelatih' saja (filter lewat relasi)
|
// Ambil Anggota yang memiliki role 'Pelatih' dan statusnya 'Aktif'
|
||||||
$data_pelatih = Anggota::whereHas('role', function($query) {
|
$data_pelatih = Anggota::whereHas('role', function($query) {
|
||||||
$query->where('nama_role', 'Pelatih');
|
$query->where('nama_role', 'Pelatih');
|
||||||
})->get();
|
})
|
||||||
|
->where('status', 'Aktif')
|
||||||
|
->orderBy('nama_lengkap', 'asc')
|
||||||
|
->get();
|
||||||
|
|
||||||
return view('jadwal.jadwalcreate', compact('data_kolat', 'data_pelatih'));
|
return view('jadwal.jadwalcreate', compact('data_kolat', 'data_pelatih'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4. Proses Simpan Jadwal Baru
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
|
|
@ -66,14 +84,14 @@ public function store(Request $request)
|
||||||
->with('success', 'Jadwal latihan berhasil ditambahkan!');
|
->with('success', 'Jadwal latihan berhasil ditambahkan!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 5. Menampilkan Detail Jadwal (Opsional jika pakai modal)
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
// Ambil satu data dengan relasinya
|
|
||||||
$jadwal = Jadwal::with(['kolat', 'pelatih'])->findOrFail($id);
|
$jadwal = Jadwal::with(['kolat', 'pelatih'])->findOrFail($id);
|
||||||
|
|
||||||
return view('jadwal.show', compact('jadwal'));
|
return view('jadwal.show', compact('jadwal'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 6. Menampilkan Form Edit Jadwal
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
$jadwal = Jadwal::findOrFail($id);
|
$jadwal = Jadwal::findOrFail($id);
|
||||||
|
|
@ -87,6 +105,7 @@ public function edit($id)
|
||||||
return view('jadwal.editjadwal', compact('jadwal', 'data_kolat', 'data_pelatih'));
|
return view('jadwal.editjadwal', compact('jadwal', 'data_kolat', 'data_pelatih'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 7. Proses Update Jadwal
|
||||||
public function update(Request $request, $id)
|
public function update(Request $request, $id)
|
||||||
{
|
{
|
||||||
$jadwal = Jadwal::findOrFail($id);
|
$jadwal = Jadwal::findOrFail($id);
|
||||||
|
|
@ -107,10 +126,16 @@ public function update(Request $request, $id)
|
||||||
->with('success', 'Jadwal berhasil diperbarui!');
|
->with('success', 'Jadwal berhasil diperbarui!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 8. Proses Hapus Jadwal
|
||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
$jadwal = Jadwal::findOrFail($id);
|
$jadwal = Jadwal::findOrFail($id);
|
||||||
|
|
||||||
|
// Cek dan hapus file foto bukti dari storage jika ada, biar hosting nggak penuh
|
||||||
|
if ($jadwal->foto_bukti) {
|
||||||
|
Storage::disk('public')->delete($jadwal->foto_bukti);
|
||||||
|
}
|
||||||
|
|
||||||
$jadwal->delete();
|
$jadwal->delete();
|
||||||
|
|
||||||
return redirect()->route('jadwal.index')
|
return redirect()->route('jadwal.index')
|
||||||
|
|
|
||||||
|
|
@ -2,127 +2,177 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use App\Models\Anggota;
|
||||||
|
|
||||||
// TAMBAHAN WAJIB: Memanggil Facades dan Model yang digunakan
|
// 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\Jadwal;
|
||||||
use App\Models\Presensi;
|
use App\Models\Presensi;
|
||||||
use App\Models\Anggota;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class PresensiController extends Controller
|
class PresensiController extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* AKTOR: PENGURUS/PELATIH
|
||||||
|
* Menampilkan daftar semua jadwal untuk dipilih mana yang mau dicek presensinya
|
||||||
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
// Mengambil semua jadwal secara manual menggunakan Query Builder (JOIN)
|
// Menggunakan Eloquent agar lebih konsisten dengan fungsi lainnya
|
||||||
$data_jadwal = DB::table('jadwals')
|
$data_jadwal = Jadwal::with(['kolat', 'pelatih'])
|
||||||
->leftJoin('anggotas', 'jadwals.pelatih_id', '=', 'anggotas.id')
|
->orderBy('tanggal', 'desc')
|
||||||
->leftJoin('kolat', 'jadwals.kolat_id', '=', 'kolat.id') // Sesuaikan jika nama tabel di database kamu adalah 'kolat'
|
->orderBy('jam_mulai', 'desc')
|
||||||
->select(
|
|
||||||
'jadwals.*',
|
|
||||||
'anggotas.nama_lengkap as nama_pelatih',
|
|
||||||
'kolat.nama_kolat as nama_kolat'
|
|
||||||
)
|
|
||||||
->orderBy('jadwals.tanggal', 'desc')
|
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
// Pastikan nama foldernya konsisten (admin atau pengurus)
|
|
||||||
return view('presensi.pengurus.index', compact('data_jadwal'));
|
return view('presensi.pengurus.index', compact('data_jadwal'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AKTOR: PENGURUS/PELATIH
|
||||||
|
* Menampilkan detail siapa saja yang sudah scan/absen di jadwal tertentu
|
||||||
|
*/
|
||||||
public function kehadiran($jadwal_id)
|
public function kehadiran($jadwal_id)
|
||||||
{
|
{
|
||||||
// Variabel dibuat dengan nama $jadwal (tunggal)
|
|
||||||
$jadwal = Jadwal::with(['kolat', 'pelatih'])->findOrFail($jadwal_id);
|
$jadwal = Jadwal::with(['kolat', 'pelatih'])->findOrFail($jadwal_id);
|
||||||
|
|
||||||
$data_presensi = Presensi::with('anggota', 'pelatihVerifikator')
|
$data_presensi = Presensi::with('anggota', 'pelatihVerifikator')
|
||||||
->where('jadwal_id', $jadwal_id)
|
->where('jadwal_id', $jadwal_id)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
$daftar_anggota = Anggota::where('kolat_id', $jadwal->kolat_id)
|
// 1. Ambil array ID anggota yang SUDAH absen
|
||||||
|
$id_sudah_absen = $data_presensi->pluck('anggota_id')->toArray();
|
||||||
|
|
||||||
|
// 2. Ambil anggota yang se-Kolat, status Aktif, tapi ID-nya BELUM ADA di daftar absen
|
||||||
|
$anggota_belum_absen = Anggota::where('kolat_id', $jadwal->kolat_id)
|
||||||
->where('status', 'Aktif')
|
->where('status', 'Aktif')
|
||||||
|
->whereNotIn('id', $id_sudah_absen)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
// Pastikan di sini tulisannya 'jadwal' (sesuai nama variabel di atas)
|
// Kirim variabel baru ini ke View
|
||||||
return view('presensi.pengurus.kehadiran', compact('jadwal', 'data_presensi', 'daftar_anggota'));
|
return view('presensi.pengurus.kehadiran', compact('jadwal', 'data_presensi', 'anggota_belum_absen'));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
* AKTOR: PENGURUS/PELATIH
|
||||||
|
* Mensahkan (Verify) absensi anggota yang masuk lewat scan QR
|
||||||
|
*/
|
||||||
|
public function konfirmasi(Request $request, $presensi_id)
|
||||||
|
{
|
||||||
|
$presensi = Presensi::findOrFail($presensi_id);
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'action' => 'required|in:sah,tolak',
|
||||||
|
'keterangan' => 'nullable|string' // <-- Tambahan validasi keterangan
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($request->action == 'sah') {
|
||||||
|
$presensi->update([
|
||||||
|
'is_verified' => true,
|
||||||
|
'status' => 'Hadir',
|
||||||
|
'verified_by' => Auth::user()->anggota->id,
|
||||||
|
]);
|
||||||
|
$pesan = 'Kehadiran ' . $presensi->anggota->nama_lengkap . ' berhasil disahkan!';
|
||||||
|
} else {
|
||||||
|
$presensi->update([
|
||||||
|
'is_verified' => true,
|
||||||
|
'status' => 'Alfa',
|
||||||
|
'verified_by' => Auth::user()->anggota->id,
|
||||||
|
'keterangan' => $request->keterangan // <-- Simpan alasan penolakan
|
||||||
|
]);
|
||||||
|
$pesan = 'Absensi ' . $presensi->anggota->nama_lengkap . ' ditolak (Alfa).';
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', $pesan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AKTOR: PENGURUS/PELATIH
|
||||||
|
* Input manual jika anggota lupa bawa HP (Otomatis is_verified = true)
|
||||||
*/
|
*/
|
||||||
public function storeManual(Request $request)
|
public function storeManual(Request $request)
|
||||||
{
|
{
|
||||||
// Validasi input dari form modal
|
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'jadwal_id' => 'required|exists:jadwals,id',
|
'jadwal_id' => 'required|exists:jadwals,id',
|
||||||
'anggota_id' => 'required|exists:anggotas,id',
|
'anggota_id' => 'required|exists:anggotas,id',
|
||||||
|
'status' => 'required|in:Hadir,Izin,Sakit,Alfa',
|
||||||
|
'keterangan' => 'nullable|string' // <-- Tambahan validasi keterangan
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Cek apakah anggota tersebut sudah absen sebelumnya agar tidak ada data ganda (double input)
|
|
||||||
$sudah_absen = Presensi::where('jadwal_id', $request->jadwal_id)
|
$sudah_absen = Presensi::where('jadwal_id', $request->jadwal_id)
|
||||||
->where('anggota_id', $request->anggota_id)
|
->where('anggota_id', $request->anggota_id)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($sudah_absen) {
|
if ($sudah_absen) {
|
||||||
return redirect()->back()->with('error', 'Anggota tersebut sudah tercatat di daftar kehadiran!');
|
return redirect()->back()->with('error', 'Anggota tersebut sudah memiliki catatan kehadiran di jadwal ini!');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simpan data presensi baru
|
|
||||||
// Karena diinput langsung oleh pelatih, is_verified otomatis bernilai true
|
|
||||||
Presensi::create([
|
Presensi::create([
|
||||||
'jadwal_id' => $request->jadwal_id,
|
'jadwal_id' => $request->jadwal_id,
|
||||||
'anggota_id' => $request->anggota_id,
|
'anggota_id' => $request->anggota_id,
|
||||||
'status' => 'Hadir',
|
'status' => $request->status,
|
||||||
'waktu_presensi' => now(), // Waktu dicatat saat form disubmit
|
'keterangan' => $request->keterangan, // <-- Simpan keterangan manual
|
||||||
'is_verified' => true, // Langsung Sah
|
'waktu_presensi' => now(),
|
||||||
'verified_by' => Auth::user()->id
|
'is_verified' => true,
|
||||||
|
'verified_by' => Auth::user()->anggota->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return redirect()->back()->with('success', 'Presensi manual berhasil ditambahkan!');
|
return redirect()->back()->with('success', 'Presensi manual berhasil disimpan!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AKTOR: ANGGOTA
|
||||||
|
* Melihat daftar jadwal latihan hari ini untuk di-scan
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* AKTOR: ANGGOTA
|
||||||
|
* Melihat daftar jadwal latihan hari ini dan riwayat 7 hari terakhir
|
||||||
|
*/
|
||||||
public function indexAnggota()
|
public function indexAnggota()
|
||||||
{
|
{
|
||||||
$now = \Carbon\Carbon::now('Asia/Jakarta');
|
if (!Auth::check()) {
|
||||||
$hari_ini = $now->format('Y-m-d');
|
return redirect()->route('login')->with('error', 'Silakan login terlebih dahulu.');
|
||||||
$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'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$user = Auth::user();
|
||||||
|
$now = \Carbon\Carbon::now('Asia/Jakarta');
|
||||||
|
$hari_ini = $now->format('Y-m-d');
|
||||||
|
|
||||||
|
// Ambil tanggal 7 hari yang lalu
|
||||||
|
$seminggu_lalu = $now->copy()->subDays(7)->format('Y-m-d');
|
||||||
|
|
||||||
|
if (!$user->anggota) {
|
||||||
|
return redirect()->route('presensi.index')->with('error', 'Akun Anda tidak terdaftar sebagai peserta latihan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil jadwal dalam rentang 7 hari terakhir hingga hari ini
|
||||||
|
$jadwal_terbaru = Jadwal::with('pelatih')
|
||||||
|
->whereBetween('tanggal', [$seminggu_lalu, $hari_ini])
|
||||||
|
->where('kolat_id', $user->anggota->kolat_id)
|
||||||
|
->orderBy('tanggal', 'desc')
|
||||||
|
->orderBy('jam_mulai', 'desc')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$presensi_saya = Presensi::where('anggota_id', $user->anggota->id)
|
||||||
|
->whereIn('jadwal_id', $jadwal_terbaru->pluck('id'))
|
||||||
|
->get()
|
||||||
|
->keyBy('jadwal_id');
|
||||||
|
|
||||||
|
return view('presensi.anggota.index', compact('jadwal_terbaru', 'presensi_saya', 'now', 'hari_ini'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AKTOR: ANGGOTA
|
||||||
|
* Menampilkan halaman kamera scanner
|
||||||
|
*/
|
||||||
|
public function scan($jadwal_id)
|
||||||
|
{
|
||||||
|
$jadwal = Jadwal::findOrFail($jadwal_id);
|
||||||
|
return view('presensi.anggota.scan', compact('jadwal'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AKTOR: ANGGOTA
|
||||||
|
* Menyimpan data presensi hasil scan (Menunggu Verifikasi Pelatih)
|
||||||
|
*/
|
||||||
public function storeMandiri(Request $request)
|
public function storeMandiri(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
|
|
@ -130,26 +180,86 @@ public function storeMandiri(Request $request)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
|
$profilAnggota = $user->anggota;
|
||||||
|
|
||||||
// Cek agar tidak bisa klik absen 2 kali (Double submit)
|
if (!$profilAnggota) {
|
||||||
|
return redirect()->back()->with('error', 'Data profil tidak lengkap.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$jadwal = Jadwal::findOrFail($request->jadwal_id);
|
||||||
|
$now = \Carbon\Carbon::now('Asia/Jakarta');
|
||||||
|
|
||||||
|
// Validasi Waktu: Gabungkan tanggal dan jam untuk pengecekan presisi
|
||||||
|
$jam_selesai = $jadwal->jam_selesai
|
||||||
|
? $jadwal->jam_selesai
|
||||||
|
: \Carbon\Carbon::parse($jadwal->jam_mulai)->addHours(3)->format('H:i:s');
|
||||||
|
|
||||||
|
$batas_waktu = \Carbon\Carbon::parse($jadwal->tanggal . ' ' . $jam_selesai, 'Asia/Jakarta');
|
||||||
|
|
||||||
|
if ($now->gt($batas_waktu)) {
|
||||||
|
return redirect()->route('presensi.anggota.index')->with('error', 'Sesi absensi sudah berakhir pada pukul ' . substr($jam_selesai, 0, 5) . ' WIB.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($jadwal->status == 'selesai') {
|
||||||
|
return redirect()->route('presensi.anggota.index')->with('error', 'Sesi latihan sudah ditutup oleh pelatih.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cek apakah sudah absen
|
||||||
$sudah_absen = Presensi::where('jadwal_id', $request->jadwal_id)
|
$sudah_absen = Presensi::where('jadwal_id', $request->jadwal_id)
|
||||||
->where('anggota_id', $user->id)
|
->where('anggota_id', $profilAnggota->id)
|
||||||
->exists();
|
->exists();
|
||||||
|
|
||||||
if ($sudah_absen) {
|
if ($sudah_absen) {
|
||||||
return redirect()->back()->with('error', 'Kamu sudah melakukan absensi untuk jadwal ini!');
|
return redirect()->route('presensi.anggota.index')->with('error', 'Kamu sudah melakukan absensi untuk jadwal ini!');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simpan data presensi dengan status is_verified = false (Menunggu ACC)
|
|
||||||
Presensi::create([
|
Presensi::create([
|
||||||
'jadwal_id' => $request->jadwal_id,
|
'jadwal_id' => $request->jadwal_id,
|
||||||
'anggota_id' => $user->id,
|
'anggota_id' => $profilAnggota->id,
|
||||||
'status' => 'Hadir',
|
'status' => 'Hadir',
|
||||||
'waktu_presensi' => now(),
|
'waktu_presensi' => $now,
|
||||||
'is_verified' => false, // Belum Sah, butuh ACC Pelatih
|
'is_verified' => false,
|
||||||
'verified_by' => null
|
'verified_by' => null,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return redirect()->back()->with('success', 'Berhasil! Kehadiranmu sedang menunggu konfirmasi Pelatih.');
|
return redirect()->route('presensi.anggota.index')->with('success', 'Berhasil scan! Silakan minta Pelatih untuk konfirmasi kehadiran.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AKTOR: ANGGOTA
|
||||||
|
* Menampilkan riwayat lengkap presensi dengan filter bulan dan tahun
|
||||||
|
*/
|
||||||
|
public function riwayatAnggota(Request $request)
|
||||||
|
{
|
||||||
|
if (!Auth::check()) {
|
||||||
|
return redirect()->route('login')->with('error', 'Silakan login terlebih dahulu.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
if (!$user->anggota) {
|
||||||
|
return redirect()->route('presensi.index')->with('error', 'Profil anggota tidak ditemukan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tangkap request filter bulan & tahun (Default: Bulan & Tahun saat ini)
|
||||||
|
$bulan = $request->input('bulan', date('m'));
|
||||||
|
$tahun = $request->input('tahun', date('Y'));
|
||||||
|
|
||||||
|
// Ambil semua jadwal sesuai filter bulan & tahun di Kolat anggota tersebut
|
||||||
|
$jadwal_riwayat = Jadwal::with('pelatih')
|
||||||
|
->where('kolat_id', $user->anggota->kolat_id)
|
||||||
|
->whereMonth('tanggal', $bulan)
|
||||||
|
->whereYear('tanggal', $tahun)
|
||||||
|
->orderBy('tanggal', 'desc')
|
||||||
|
->orderBy('jam_mulai', 'desc')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
// Ambil data presensi anggota pada jadwal-jadwal tersebut
|
||||||
|
$presensi_saya = Presensi::where('anggota_id', $user->anggota->id)
|
||||||
|
->whereIn('jadwal_id', $jadwal_riwayat->pluck('id'))
|
||||||
|
->get()
|
||||||
|
->keyBy('jadwal_id');
|
||||||
|
|
||||||
|
return view('presensi.anggota.riwayat', compact('jadwal_riwayat', 'presensi_saya', 'bulan', 'tahun'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
// controller jadwal //
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Jadwal;
|
||||||
|
use App\Models\Kolat;
|
||||||
|
use App\Models\Anggota;
|
||||||
|
use App\Models\Role;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class JadwalController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$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()
|
||||||
|
{
|
||||||
|
$data_kolat = Kolat::all();
|
||||||
|
$rolePelatih = Role::where('nama_role', 'Pelatih')->first();
|
||||||
|
|
||||||
|
// Ambil Anggota yang memiliki role 'Pelatih' saja (filter lewat relasi)
|
||||||
|
$data_pelatih = Anggota::whereHas('role', function($query) {
|
||||||
|
$query->where('nama_role', 'Pelatih');
|
||||||
|
})
|
||||||
|
->where('status', 'Aktif') // <-- INI BATASAN TAMBAHANNYA
|
||||||
|
->orderBy('nama_lengkap', 'asc') // (Bonus) Biar namanya urut abjad di form
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return view('jadwal.jadwalcreate', compact('data_kolat', 'data_pelatih'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$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::create($request->all());
|
||||||
|
|
||||||
|
return redirect()->route('jadwal.index')
|
||||||
|
->with('success', 'Jadwal latihan berhasil ditambahkan!');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
// Ambil satu data dengan relasinya
|
||||||
|
$jadwal = Jadwal::with(['kolat', 'pelatih'])->findOrFail($id);
|
||||||
|
|
||||||
|
return view('jadwal.show', compact('jadwal'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
$jadwal = Jadwal::findOrFail($id);
|
||||||
|
$data_kolat = Kolat::all();
|
||||||
|
|
||||||
|
// Tetap filter agar hanya muncul daftar pelatih
|
||||||
|
$data_pelatih = Anggota::whereHas('role', function($query) {
|
||||||
|
$query->where('nama_role', 'Pelatih');
|
||||||
|
})->get();
|
||||||
|
|
||||||
|
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|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());
|
||||||
|
|
||||||
|
return redirect()->route('jadwal.index')
|
||||||
|
->with('success', 'Jadwal berhasil diperbarui!');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
$jadwal = Jadwal::findOrFail($id);
|
||||||
|
$jadwal->delete();
|
||||||
|
|
||||||
|
return redirect()->route('jadwal.index')
|
||||||
|
->with('success', 'Jadwal telah dihapus dari sistem.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -19,7 +19,9 @@ class Jadwal extends Model
|
||||||
'jam_mulai',
|
'jam_mulai',
|
||||||
'jam_selesai',
|
'jam_selesai',
|
||||||
'lokasi',
|
'lokasi',
|
||||||
'deskripsi'
|
'deskripsi',
|
||||||
|
'foto_bukti', // Tambahan baru untuk foto kegiatan (Pelatih)
|
||||||
|
'catatan_latihan',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Relasi: Jadwal ini milik Kolat mana?
|
// Relasi: Jadwal ini milik Kolat mana?
|
||||||
|
|
|
||||||
|
|
@ -29,4 +29,9 @@ public function anggota()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Anggota::class, 'anggota_id');
|
return $this->belongsTo(Anggota::class, 'anggota_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function pelatihVerifikator()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Anggota::class, 'verified_by');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,4 +54,5 @@ public function role()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Role::class, 'role_id');
|
return $this->belongsTo(Role::class, 'role_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@
|
||||||
"guzzlehttp/guzzle": "^7.2",
|
"guzzlehttp/guzzle": "^7.2",
|
||||||
"laravel/framework": "^10.10",
|
"laravel/framework": "^10.10",
|
||||||
"laravel/sanctum": "^3.3",
|
"laravel/sanctum": "^3.3",
|
||||||
"laravel/tinker": "^2.8"
|
"laravel/tinker": "^2.8",
|
||||||
|
"simplesoftwareio/simple-qrcode": "^4.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,62 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "9c491b8531eec05ba41a11d9276a5749",
|
"content-hash": "d0e9a868dabf1fd8df971928d0612783",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "bacon/bacon-qr-code",
|
||||||
|
"version": "2.0.8",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Bacon/BaconQrCode.git",
|
||||||
|
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/8674e51bb65af933a5ffaf1c308a660387c35c22",
|
||||||
|
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"dasprid/enum": "^1.0.3",
|
||||||
|
"ext-iconv": "*",
|
||||||
|
"php": "^7.1 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phly/keep-a-changelog": "^2.1",
|
||||||
|
"phpunit/phpunit": "^7 | ^8 | ^9",
|
||||||
|
"spatie/phpunit-snapshot-assertions": "^4.2.9",
|
||||||
|
"squizlabs/php_codesniffer": "^3.4"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-imagick": "to generate QR code images"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"BaconQrCode\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-2-Clause"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Ben Scholzen 'DASPRiD'",
|
||||||
|
"email": "mail@dasprids.de",
|
||||||
|
"homepage": "https://dasprids.de/",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "BaconQrCode is a QR code generator for PHP.",
|
||||||
|
"homepage": "https://github.com/Bacon/BaconQrCode",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/Bacon/BaconQrCode/issues",
|
||||||
|
"source": "https://github.com/Bacon/BaconQrCode/tree/2.0.8"
|
||||||
|
},
|
||||||
|
"time": "2022-12-07T17:46:57+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
"version": "0.12.3",
|
"version": "0.12.3",
|
||||||
|
|
@ -135,6 +189,56 @@
|
||||||
],
|
],
|
||||||
"time": "2023-12-11T17:09:12+00:00"
|
"time": "2023-12-11T17:09:12+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "dasprid/enum",
|
||||||
|
"version": "1.0.7",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DASPRiD/Enum.git",
|
||||||
|
"reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
|
||||||
|
"reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1 <9.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11",
|
||||||
|
"squizlabs/php_codesniffer": "*"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"DASPRiD\\Enum\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-2-Clause"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Ben Scholzen 'DASPRiD'",
|
||||||
|
"email": "mail@dasprids.de",
|
||||||
|
"homepage": "https://dasprids.de/",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP 7.1 enum implementation",
|
||||||
|
"keywords": [
|
||||||
|
"enum",
|
||||||
|
"map"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/DASPRiD/Enum/issues",
|
||||||
|
"source": "https://github.com/DASPRiD/Enum/tree/1.0.7"
|
||||||
|
},
|
||||||
|
"time": "2025-09-16T12:23:56+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "dflydev/dot-access-data",
|
"name": "dflydev/dot-access-data",
|
||||||
"version": "v3.0.3",
|
"version": "v3.0.3",
|
||||||
|
|
@ -3159,6 +3263,74 @@
|
||||||
},
|
},
|
||||||
"time": "2025-12-14T04:43:48+00:00"
|
"time": "2025-12-14T04:43:48+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "simplesoftwareio/simple-qrcode",
|
||||||
|
"version": "4.2.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/SimpleSoftwareIO/simple-qrcode.git",
|
||||||
|
"reference": "916db7948ca6772d54bb617259c768c9cdc8d537"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/SimpleSoftwareIO/simple-qrcode/zipball/916db7948ca6772d54bb617259c768c9cdc8d537",
|
||||||
|
"reference": "916db7948ca6772d54bb617259c768c9cdc8d537",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"bacon/bacon-qr-code": "^2.0",
|
||||||
|
"ext-gd": "*",
|
||||||
|
"php": ">=7.2|^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "~1",
|
||||||
|
"phpunit/phpunit": "~9"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-imagick": "Allows the generation of PNG QrCodes.",
|
||||||
|
"illuminate/support": "Allows for use within Laravel."
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"aliases": {
|
||||||
|
"QrCode": "SimpleSoftwareIO\\QrCode\\Facades\\QrCode"
|
||||||
|
},
|
||||||
|
"providers": [
|
||||||
|
"SimpleSoftwareIO\\QrCode\\QrCodeServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"SimpleSoftwareIO\\QrCode\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Simple Software LLC",
|
||||||
|
"email": "support@simplesoftware.io"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Simple QrCode is a QR code generator made for Laravel.",
|
||||||
|
"homepage": "https://www.simplesoftware.io/#/docs/simple-qrcode",
|
||||||
|
"keywords": [
|
||||||
|
"Simple",
|
||||||
|
"generator",
|
||||||
|
"laravel",
|
||||||
|
"qrcode",
|
||||||
|
"wrapper"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/SimpleSoftwareIO/simple-qrcode/issues",
|
||||||
|
"source": "https://github.com/SimpleSoftwareIO/simple-qrcode/tree/4.2.0"
|
||||||
|
},
|
||||||
|
"time": "2021-02-08T20:43:55+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v6.4.32",
|
"version": "v6.4.32",
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,7 @@
|
||||||
|
|
||||||
'aliases' => Facade::defaultAliases()->merge([
|
'aliases' => Facade::defaultAliases()->merge([
|
||||||
// 'Example' => App\Facades\Example::class,
|
// 'Example' => App\Facades\Example::class,
|
||||||
|
'QrCode' => SimpleSoftwareIO\QrCode\Facades\QrCode::class,
|
||||||
])->toArray(),
|
])->toArray(),
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,8 @@ public function run(): void
|
||||||
{
|
{
|
||||||
$this->call([
|
$this->call([
|
||||||
RoleSeeder::class,
|
RoleSeeder::class,
|
||||||
]);
|
KolatSeeder::class,
|
||||||
// \App\Models\User::factory(10)->create();
|
UserSeeder::class,
|
||||||
|
|
||||||
// \App\Models\User::factory()->create([
|
|
||||||
// 'name' => 'Test User',
|
|
||||||
// 'email' => 'test@example.com',
|
|
||||||
// ]);
|
|
||||||
$this->call([
|
|
||||||
RoleSeeder::class,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class KolatSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
DB::table('kolat')->insert([
|
||||||
|
'id' => 1, // Kita paksa ID 1 biar nyambung sama UserSeeder tadi
|
||||||
|
'nama_kolat' => 'Kolat Polije',
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\Anggota;
|
||||||
|
use App\Models\Role;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
|
class UserSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$rolePelatih = Role::where('nama_role', 'Pelatih')->first();
|
||||||
|
|
||||||
|
// 2. Buat Akun User untuk Pelatih
|
||||||
|
$user = User::create([
|
||||||
|
'role_id' => $rolePelatih->id,
|
||||||
|
'email' => 'pelatih@tapakmp.com',
|
||||||
|
'password' => Hash::make('password123'), // Password default
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 3. Buat Profil Anggota untuk User tersebut
|
||||||
|
Anggota::create([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'role_id' => $rolePelatih->id,
|
||||||
|
'no_induk' => 'MP-2026-001',
|
||||||
|
'nama_lengkap' => 'Siti Afiah Dahliawati',
|
||||||
|
'jenis_kelamin' => 'P',
|
||||||
|
'tempat_lahir' => 'Jember',
|
||||||
|
'tgl_lahir' => '2004-10-29',
|
||||||
|
'no_hp' => '081455057453',
|
||||||
|
'kolat_id' => 1, // Pastikan sudah ada data Kolat ID 1 atau sesuaikan
|
||||||
|
'tingkatan' => 'Balik 1',
|
||||||
|
'tgl_gabung' => now(),
|
||||||
|
'status' => 'Aktif',
|
||||||
|
'alamat' => 'Jl. Merpati Putih No. 1, Jember',
|
||||||
|
'jabatan' => 'Pelatih Kolat',
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,264 +1,121 @@
|
||||||
@extends('layout.app')
|
@extends('layout.app')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="container-fluid py-4">
|
<div class="container-fluid py-4">
|
||||||
<<<<<<< Updated upstream
|
@if ($errors->any())
|
||||||
<!-- Header & Breadcrumb -->
|
<div class="alert alert-danger">
|
||||||
=======
|
<ul>
|
||||||
>>>>>>> Stashed changes
|
@foreach ($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<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') }}"
|
<li class="breadcrumb-item"><a href="{{ route('anggota.anggota') }}" class="text-muted text-decoration-none small">Daftar Anggota</a></li>
|
||||||
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>
|
||||||
<h3 class="fw-bold text-dark">Form Edit Anggota Merpati Putih</h3>
|
<h3 class="fw-bold text-dark">Form Edit Anggota Merpati Putih</h3>
|
||||||
<p class="text-muted small">Perbarui informasi identitas atau legalitas SK anggota di bawah ini.</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<<<<<<< Updated upstream
|
|
||||||
<!-- Form Start - Pastikan enctype ada untuk upload foto SK -->
|
|
||||||
=======
|
|
||||||
>>>>>>> Stashed changes
|
|
||||||
<form action="{{ route('anggota.update', $anggota->id) }}" method="POST" enctype="multipart/form-data">
|
<form action="{{ route('anggota.update', $anggota->id) }}" method="POST" enctype="multipart/form-data">
|
||||||
@csrf
|
@csrf
|
||||||
@method('PUT')
|
@method('PUT')
|
||||||
|
|
||||||
<<<<<<< Updated upstream
|
|
||||||
<!-- CARD 1: INFORMASI PRIBADI -->
|
|
||||||
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
|
<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">
|
<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>Informasi Pribadi</h5>
|
<h5 class="fw-bold text-primary mb-0"><i class="icon-user me-2"></i>Informasi Akun & Pribadi</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<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">Email Login</label>
|
||||||
<input type="text" name="no_induk" class="form-control bg-light fw-bold text-primary"
|
<input type="email" name="email" class="form-control" value="{{ old('email', $anggota->user->email) }}" required>
|
||||||
value="{{ $anggota->no_induk }}" readonly>
|
<small class="text-muted" style="font-size: 11px;">* Email digunakan untuk login sistem</small>
|
||||||
<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">Role / Hak Akses</label>
|
||||||
<input type="text" name="nama_lengkap" class="form-control bg-light"
|
<select name="role_id" class="form-select" required>
|
||||||
value="{{ $anggota->nama_lengkap }}" required>
|
@foreach($data_role as $role)
|
||||||
</div>
|
<option value="{{ $role->id }}" {{ $anggota->role_id == $role->id ? 'selected' : '' }}>
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label fw-bold">No. WhatsApp (HP)</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<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>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label fw-bold">Alamat Lengkap</label>
|
|
||||||
<input type="text" name="alamat" class="form-control" value="{{ $anggota->alamat }}"
|
|
||||||
required>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- CARD 2: INFORMASI ORGANISASI -->
|
|
||||||
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
|
|
||||||
<div class="card-header bg-white border-0 pt-4 px-4">
|
|
||||||
<h5 class="fw-bold text-success mb-0"><i class="icon-badge me-2"></i>Informasi Organisasi</h5>
|
|
||||||
</div>
|
|
||||||
<div class="card-body p-4">
|
|
||||||
<div class="row g-3">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label class="form-label fw-bold">Jabatan Organisasi</label>
|
|
||||||
<select name="jabatan" id="jabatanSelect" class="form-select border-primary"
|
|
||||||
onchange="toggleSKFields()" required>
|
|
||||||
<option value="anggota" {{ $anggota->jabatan == 'anggota' ? 'selected' : '' }}>
|
|
||||||
Anggota</option>
|
|
||||||
<option value="pelatih" {{ $anggota->jabatan == 'pelatih' ? 'selected' : '' }}>
|
|
||||||
Pelatih</option>
|
|
||||||
<option value="pengurus" {{ $anggota->jabatan == 'pengurus' ? 'selected' : '' }}>
|
|
||||||
Pengurus</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label class="form-label fw-bold">Tingkatan</label>
|
|
||||||
<input type="text" name="tingkatan" class="form-control"
|
|
||||||
value="{{ $anggota->tingkatan }}" required>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label class="form-label fw-bold">Status Anggota</label>
|
|
||||||
<select name="status" class="form-select" required>
|
|
||||||
<option value="Aktif" {{ $anggota->status == 'Aktif' ? 'selected' : '' }}>Aktif
|
|
||||||
</option>
|
|
||||||
<option value="Non-Aktif" {{ $anggota->status == 'Non-Aktif' ? 'selected' : '' }}>
|
|
||||||
Non-Aktif</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 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;">
|
|
||||||
<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="col-md-3">
|
|
||||||
<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">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<label class="form-label small fw-bold">Tanggal SK</label>
|
|
||||||
<input type="date" name="tgl_sk" class="form-control"
|
|
||||||
value="{{ $anggota->tgl_sk ?? '' }}">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<label class="form-label small fw-bold">Masa Berlaku</label>
|
|
||||||
<input type="date" name="masa_berlaku" class="form-control"
|
|
||||||
value="{{ $anggota->masa_berlaku ?? '' }}">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<label class="form-label small fw-bold">Upload Scan SK</label>
|
|
||||||
<input type="file" name="foto_sk" class="form-control">
|
|
||||||
@if ($anggota->foto_sk)
|
|
||||||
<small class="text-muted mt-1 d-block">File:
|
|
||||||
{{ $anggota->foto_sk }}</small>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- <div class="col-md-12 mt-3">
|
|
||||||
<label class="form-label fw-bold">Asal Kolat</label>
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<!-- FOOTER CARD UNTUK BUTTON -->
|
|
||||||
<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('anggota.anggota') }}"
|
|
||||||
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
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</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-primary mb-0"><i class="icon-user me-2"></i>Informasi Pribadi & Akun</h5>
|
|
||||||
</div>
|
|
||||||
<div class="card-body p-4">
|
|
||||||
<div class="row g-3">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label fw-bold">No Induk</label>
|
|
||||||
<input type="text" class="form-control bg-light fw-bold text-primary"
|
|
||||||
value="{{ $anggota->no_induk }}" readonly>
|
|
||||||
<small class="text-muted" style="font-size: 11px;">* No. induk permanen</small>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label fw-bold">Nama Lengkap</label>
|
|
||||||
<input type="text" name="nama_lengkap" class="form-control"
|
|
||||||
value="{{ old('nama_lengkap', $anggota->nama_lengkap) }}" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label fw-bold">Alamat Email (Login)</label>
|
|
||||||
<input type="email" name="email" class="form-control"
|
|
||||||
value="{{ old('email', $anggota->user->email ?? '') }}" required>
|
|
||||||
<small class="text-muted" style="font-size: 11px;">* Email digunakan untuk masuk ke sistem</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label fw-bold">No. WhatsApp (HP)</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-text bg-light border-end-0">+62</span>
|
|
||||||
<input type="number" name="no_hp" class="form-control"
|
|
||||||
value="{{ old('no_hp', $anggota->no_hp) }}" placeholder="81234567xxx" required>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-12">
|
|
||||||
<label class="form-label fw-bold">Alamat Lengkap</label>
|
|
||||||
<textarea name="alamat" class="form-control" rows="2" required>{{ old('alamat', $anggota->alamat) }}</textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</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-success mb-0"><i class="icon-badge me-2"></i>Informasi Organisasi</h5>
|
|
||||||
</div>
|
|
||||||
<div class="card-body p-4">
|
|
||||||
<div class="row g-3">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label class="form-label fw-bold">Jabatan / Role</label>
|
|
||||||
<select name="role_id" id="roleSelect" class="form-select border-primary"
|
|
||||||
onchange="toggleSKFields()" required>
|
|
||||||
<option value="" disabled>-- Pilih Jabatan --</option>
|
|
||||||
@foreach ($data_role as $role)
|
|
||||||
<option value="{{ $role->id }}"
|
|
||||||
{{ old('role_id', $anggota->role_id) == $role->id ? 'selected' : '' }}>
|
|
||||||
{{ $role->nama_role }}
|
{{ $role->nama_role }}
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Nama Lengkap</label>
|
||||||
|
<input type="text" name="nama_lengkap" class="form-control" value="{{ old('nama_lengkap', $anggota->nama_lengkap) }}" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">No. WhatsApp</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text bg-light">+62</span>
|
||||||
|
<input type="number" name="no_hp" class="form-control" value="{{ old('no_hp', $anggota->no_hp) }}" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Alamat</label>
|
||||||
|
<input type="text" name="alamat" class="form-control" value="{{ old('alamat', $anggota->alamat) }}" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</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-success mb-0"><i class="icon-badge me-2"></i>Informasi Organisasi</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="row g-3">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label class="form-label fw-bold">Tingkatan Sabuk</label>
|
<label class="form-label fw-bold">Jabatan Khusus</label>
|
||||||
<input type="text" name="tingkatan" class="form-control"
|
<select name="jabatan" id="jabatanSelect" class="form-select border-primary" onchange="toggleSKFields()" required>
|
||||||
value="{{ old('tingkatan', $anggota->tingkatan) }}" required>
|
<option value="anggota" {{ $anggota->jabatan == 'anggota' ? 'selected' : '' }}>Anggota</option>
|
||||||
|
<option value="pelatih" {{ $anggota->jabatan == 'pelatih' ? 'selected' : '' }}>Pelatih</option>
|
||||||
|
<option value="pengurus" {{ $anggota->jabatan == 'pengurus' ? 'selected' : '' }}>Pengurus</option>
|
||||||
|
</select>
|
||||||
</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">Tingkatan</label>
|
||||||
|
<input type="text" name="tingkatan" class="form-control" value="{{ old('tingkatan', $anggota->tingkatan) }}" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label class="form-label fw-bold">Status</label>
|
||||||
<select name="status" class="form-select" required>
|
<select name="status" class="form-select" required>
|
||||||
<option value="aktif" {{ old('status', $anggota->status) == 'aktif' ? 'selected' : '' }}>Aktif</option>
|
<option value="Aktif" {{ $anggota->status == 'Aktif' ? 'selected' : '' }}>Aktif</option>
|
||||||
<option value="Non-Aktif" {{ old('status', $anggota->status) == 'Non-Aktif' ? 'selected' : '' }}>Non-Aktif</option>
|
<option value="Non-Aktif" {{ $anggota->status == 'Non-Aktif' ? 'selected' : '' }}>Non-Aktif</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="boxSK"
|
<div id="boxSK" class="col-12 mt-3 p-4 bg-light rounded-4 border border-dashed border-danger" style="display: none;">
|
||||||
class="col-12 mt-3 p-4 bg-light rounded-4 border border-dashed border-danger"
|
<h6 class="text-danger fw-bold mb-3">Data Legalitas SK</h6>
|
||||||
style="display: none;">
|
|
||||||
<h6 class="text-danger fw-bold mb-3"><i class="icon-certificate me-2"></i>Data Legalitas SK</h6>
|
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-4">
|
<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"
|
<input type="text" name="no_sk" class="form-control" value="{{ $anggota->no_sk }}">
|
||||||
value="{{ old('no_sk', $anggota->no_sk) }}" placeholder="Contoh: SK/001/2026">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-3">
|
||||||
<label class="form-label small fw-bold">Masa Berlaku SK</label>
|
<label class="form-label small fw-bold">Tanggal SK</label>
|
||||||
<input type="date" name="masa_berlaku" class="form-control"
|
<input type="date" name="tgl_sk" class="form-control" value="{{ $anggota->tgl_sk }}">
|
||||||
value="{{ old('masa_berlaku', $anggota->masa_berlaku) }}">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-3">
|
||||||
<label class="form-label small fw-bold">Update File SK (Opsional)</label>
|
<label class="form-label small fw-bold">Masa Berlaku</label>
|
||||||
|
<input type="date" name="masa_berlaku" class="form-control" value="{{ $anggota->masa_berlaku }}">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<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)
|
|
||||||
<small class="text-primary mt-1 d-block"><i class="icon-eye"></i> File saat ini: {{ $anggota->foto_sk }}</small>
|
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -266,10 +123,8 @@ class="col-12 mt-3 p-4 bg-light rounded-4 border border-dashed border-danger"
|
||||||
<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>
|
||||||
<select name="kolat_id" class="form-select" required>
|
<select name="kolat_id" class="form-select" required>
|
||||||
<option value="" disabled>-- Pilih Kolat --</option>
|
|
||||||
@foreach ($data_kolat as $kolat)
|
@foreach ($data_kolat as $kolat)
|
||||||
<option value="{{ $kolat->id }}"
|
<option value="{{ $kolat->id }}" {{ $anggota->kolat_id == $kolat->id ? 'selected' : '' }}>
|
||||||
{{ old('kolat_id', $anggota->kolat_id) == $kolat->id ? 'selected' : '' }}>
|
|
||||||
{{ $kolat->nama_kolat }}
|
{{ $kolat->nama_kolat }}
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
@ -279,117 +134,23 @@ class="col-12 mt-3 p-4 bg-light rounded-4 border border-dashed border-danger"
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<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 gap-3">
|
||||||
<a href="{{ route('anggota.anggota') }}"
|
<a href="{{ route('anggota.anggota') }}" class="btn btn-outline-secondary px-4 fw-bold">Batal</a>
|
||||||
class="btn btn-outline-secondary px-4 fw-bold btn-cancel">
|
<button type="submit" class="btn btn-primary px-5 fw-bold shadow">Simpan Perubahan</button>
|
||||||
<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
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
>>>>>>> Stashed changes
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<<<<<<< Updated upstream
|
<script>
|
||||||
<!-- JAVASCRIPT TOGGLE -->
|
|
||||||
<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');
|
||||||
|
boxSK.style.display = (jabatan === 'pelatih' || jabatan === 'pengurus') ? 'block' : 'none';
|
||||||
if (jabatan === 'pelatih' || jabatan === 'pengurus') {
|
|
||||||
boxSK.style.display = 'block';
|
|
||||||
} else {
|
|
||||||
boxSK.style.display = 'none';
|
|
||||||
}
|
}
|
||||||
}
|
document.addEventListener("DOMContentLoaded", toggleSKFields);
|
||||||
|
</script>
|
||||||
// Jalankan saat pertama kali halaman dimuat
|
|
||||||
=======
|
|
||||||
<script>
|
|
||||||
function toggleSKFields() {
|
|
||||||
const roleSelect = document.getElementById('roleSelect');
|
|
||||||
const boxSK = document.getElementById('boxSK');
|
|
||||||
|
|
||||||
if (roleSelect.selectedIndex >= 0) {
|
|
||||||
const selectedText = roleSelect.options[roleSelect.selectedIndex].text.toLowerCase();
|
|
||||||
|
|
||||||
if (selectedText.includes('pelatih') || selectedText.includes('pengurus')) {
|
|
||||||
boxSK.style.display = 'block';
|
|
||||||
} else {
|
|
||||||
boxSK.style.display = 'none';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
>>>>>>> Stashed changes
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
|
||||||
toggleSKFields();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
<<<<<<< Updated upstream
|
|
||||||
.form-control,
|
|
||||||
.form-select {
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 10px 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-control:focus,
|
|
||||||
.form-select:focus {
|
|
||||||
=======
|
|
||||||
.form-control, .form-select {
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 10px 15px;
|
|
||||||
border: 1px solid #dce1e7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-control:focus, .form-select:focus {
|
|
||||||
>>>>>>> Stashed changes
|
|
||||||
border-color: #0d6efd;
|
|
||||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-cancel {
|
|
||||||
border-radius: 12px;
|
|
||||||
<<<<<<< Updated upstream
|
|
||||||
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: (45deg, #0d6efd);
|
|
||||||
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;
|
|
||||||
=======
|
|
||||||
border: 2px solid #6c757d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-save {
|
|
||||||
border-radius: 12px;
|
|
||||||
background: linear-gradient(45deg, #0d6efd, #004dc0);
|
|
||||||
border: none;
|
|
||||||
color: white;
|
|
||||||
>>>>>>> Stashed changes
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,547 @@
|
||||||
|
// index jadwal.blade.php
|
||||||
|
@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">Jadwal Latihan</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
<h3 class="fw-bold text-dark">Manajemen Latihan TapakMP</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">Agenda PPS Merpati Putih</h5>
|
||||||
|
<p class="text-muted small mb-0">Cabang Jember - Kelola jadwal rutin dan pengumuman latihan.</p>
|
||||||
|
</div>
|
||||||
|
<a href="{{ route('jadwal.create') }}" class="btn btn-primary px-4 py-2 shadow-sm"
|
||||||
|
style="border-radius: 12px;">
|
||||||
|
<i class="icon-plus me-1"></i> Buat Jadwal
|
||||||
|
</a>
|
||||||
|
</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</th>
|
||||||
|
<th>Waktu & Lokasi</th>
|
||||||
|
<th class="text-center">Tipe</th>
|
||||||
|
<th class="text-center" width="220">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">
|
||||||
|
<i class="icon-user small"></i> {{ $item->pelatih->nama_lengkap ?? '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">
|
||||||
|
<div class="d-flex justify-content-center gap-2">
|
||||||
|
|
||||||
|
{{-- TOMBOL KONFIRMASI: Muncul jika sudah masuk jamnya, bukan pengumuman, dan belum selesai --}}
|
||||||
|
@if($dbStatus != 'selesai' && $item->jenis != 'Pengumuman' && $now->greaterThanOrEqualTo($start))
|
||||||
|
<form action="{{ route('jadwal.konfirmasi', $item->id) }}" method="POST" id="form-selesai-{{ $item->id }}" class="d-inline">
|
||||||
|
@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
|
||||||
|
|
||||||
|
<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) }}"
|
||||||
|
class="btn btn-sm btn-action-edit fw-bold px-2 shadow-xs">
|
||||||
|
<i class="icon-pencil"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{{-- MODAL DETAIL JADWAL --}}
|
||||||
|
<div class="modal fade" id="modalDetailJadwal{{ $item->id }}" tabindex="-1" aria-hidden="true">
|
||||||
|
<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-header bg-primary text-white border-0 py-3 px-4">
|
||||||
|
<h5 class="modal-title fw-bold">
|
||||||
|
<i class="icon-calendar me-2"></i>Detail Agenda Latihan
|
||||||
|
</h5>
|
||||||
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body p-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4 text-center border-end">
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="bg-light rounded-circle d-inline-flex align-items-center justify-content-center shadow-sm"
|
||||||
|
style="width: 100px; height: 100px; border: 4px solid #f8f9fa;">
|
||||||
|
<i class="icon-clipboard text-primary" style="font-size: 50px;"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h5 class="fw-bold mb-1 text-dark">{{ $item->judul_kegiatan }}</h5>
|
||||||
|
<p class="text-muted small mb-3">Status: <span class="text-{{ $status_color }} fw-bold">{{ strtoupper($status_label) }}</span></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-8 ps-md-4 text-start">
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-6">
|
||||||
|
<small class="text-muted d-block small">Pelatih</small>
|
||||||
|
<span class="fw-bold text-dark">{{ $item->pelatih->nama_lengkap ?? '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<small class="text-muted d-block small">Kolat</small>
|
||||||
|
<span class="fw-bold text-dark">{{ $item->kolat->nama_kolat ?? '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 mt-3">
|
||||||
|
<h6 class="fw-bold text-primary border-bottom pb-1 small">Deskripsi Kegiatan</h6>
|
||||||
|
<p class="small text-muted mb-0" style="white-space: pre-line;">{{ $item->deskripsi ?? 'Tidak ada deskripsi.' }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" class="text-center py-5 text-muted small">Belum ada jadwal latihan atau pengumuman.</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; }
|
||||||
|
.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: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); }
|
||||||
|
.shadow-xs { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); }
|
||||||
|
</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
|
||||||
|
|
||||||
|
|
||||||
|
{{-- edit --}}
|
||||||
|
@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
|
||||||
|
|
||||||
|
{{-- create --}}
|
||||||
|
@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">Jadwal Latihan</a></li>
|
||||||
|
<li class="breadcrumb-item active text-primary fw-bold small" aria-current="page">Buat Jadwal Baru</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
<h3 class="fw-bold text-dark">Tambah Jadwal Latihan</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-8 col-12">
|
||||||
|
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<form action="{{ route('jadwal.store') }}" method="POST">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12 mb-3">
|
||||||
|
<label class="form-label fw-bold text-dark">Judul Kegiatan / Agenda</label>
|
||||||
|
<input type="text" name="judul_kegiatan" class="form-control @error('judul_kegiatan') is-invalid @enderror"
|
||||||
|
placeholder="Contoh: Latihan Rutin Sabuk Putih" value="{{ old('judul_kegiatan') }}" required>
|
||||||
|
@error('judul_kegiatan')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label fw-bold text-dark">Kelompok Latihan (Kolat)</label>
|
||||||
|
<select name="kolat_id" class="form-select @error('kolat_id') is-invalid @enderror" required>
|
||||||
|
<option value="" selected disabled>Pilih Kolat</option>
|
||||||
|
@foreach($data_kolat as $kolat)
|
||||||
|
<option value="{{ $kolat->id }}" {{ old('kolat_id') == $kolat->id ? 'selected' : '' }}>
|
||||||
|
{{ $kolat->nama_kolat }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
@error('kolat_id')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label fw-bold text-dark">Pelatih Bertugas</label>
|
||||||
|
<select name="pelatih_id" class="form-select @error('pelatih_id') is-invalid @enderror" required>
|
||||||
|
<option value="" selected disabled>Pilih Pelatih</option>
|
||||||
|
@foreach($data_pelatih as $pelatih)
|
||||||
|
<option value="{{ $pelatih->id }}" {{ old('pelatih_id') == $pelatih->id ? 'selected' : '' }}>
|
||||||
|
{{ $pelatih->nama_lengkap }} ({{ $pelatih->no_induk }})
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
@error('pelatih_id')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label fw-bold text-dark">Jenis Kegiatan</label>
|
||||||
|
<select name="jenis" class="form-select @error('jenis') is-invalid @enderror" required>
|
||||||
|
<option value="Rutin" {{ old('jenis') == 'Rutin' ? 'selected' : '' }}>Rutin</option>
|
||||||
|
<option value="Tambahan" {{ old('jenis') == 'Tambahan' ? 'selected' : '' }}>Tambahan</option>
|
||||||
|
<option value="Pengumuman" {{ old('jenis') == 'Pengumuman' ? 'selected' : '' }}>Pengumuman</option>
|
||||||
|
</select>
|
||||||
|
@error('jenis')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label fw-bold text-dark">Tanggal</label>
|
||||||
|
<input type="date" name="tanggal" class="form-control @error('tanggal') is-invalid @enderror"
|
||||||
|
value="{{ old('tanggal') }}" required>
|
||||||
|
@error('tanggal')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label fw-bold text-dark">Jam Mulai</label>
|
||||||
|
<input type="time" name="jam_mulai" class="form-control @error('jam_mulai') is-invalid @enderror"
|
||||||
|
value="{{ old('jam_mulai') }}" required>
|
||||||
|
@error('jam_mulai')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label fw-bold text-dark">Jam Selesai (Opsional)</label>
|
||||||
|
<input type="time" name="jam_selesai" class="form-control @error('jam_selesai') is-invalid @enderror"
|
||||||
|
value="{{ old('jam_selesai') }}">
|
||||||
|
@error('jam_selesai')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12 mb-3">
|
||||||
|
<label class="form-label fw-bold text-dark">Lokasi Latihan</label>
|
||||||
|
<input type="text" name="lokasi" class="form-control @error('lokasi') is-invalid @enderror"
|
||||||
|
placeholder="Contoh: Gedung Serbaguna Lt. 2" value="{{ old('lokasi') }}" required>
|
||||||
|
@error('lokasi')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12 mb-4">
|
||||||
|
<label class="form-label fw-bold text-dark">Deskripsi / Catatan (Opsional)</label>
|
||||||
|
<textarea name="deskripsi" class="form-control @error('deskripsi') is-invalid @enderror"
|
||||||
|
rows="3" placeholder="Masukkan detail tambahan jika ada...">{{ old('deskripsi') }}</textarea>
|
||||||
|
@error('deskripsi')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-end gap-2 border-top pt-4">
|
||||||
|
<a href="{{ route('jadwal.index') }}" class="btn btn-light px-4 py-2 fw-bold" style="border-radius: 12px;">Batal</a>
|
||||||
|
<button type="submit" class="btn btn-primary px-4 py-2 fw-bold shadow-sm" style="border-radius: 12px;">
|
||||||
|
<i class="icon-save me-1"></i> Simpan Jadwal
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-4 col-12 mt-4 mt-lg-0">
|
||||||
|
<div class="card border-0 bg-primary text-white" style="border-radius: 20px;">
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<h5 class="fw-bold mb-3"><i class="icon-info me-2"></i> Tips Pengisian</h5>
|
||||||
|
<ul class="small opacity-75 ps-3">
|
||||||
|
<li class="mb-2">Pastikan memilih <strong>Pelatih</strong> yang sedang aktif.</li>
|
||||||
|
<li class="mb-2">Pilih jenis <strong>Pengumuman</strong> jika hanya ingin memberikan informasi tanpa perlu presensi.</li>
|
||||||
|
<li class="mb-2">Gunakan lokasi yang spesifik agar anggota tidak kesulitan mencari tempat.</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.form-control, .form-select {
|
||||||
|
border: 1px solid #edf2f9;
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
background-color: #f8faff;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
.form-control:focus, .form-select:focus {
|
||||||
|
border-color: #0d6efd;
|
||||||
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.05);
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.form-label {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -22,21 +22,26 @@ class="text-muted text-decoration-none small">Daftar Jadwal</a></li>
|
||||||
|
|
||||||
<div class="card border-0 shadow-sm mb-4" style="border-radius: 20px;">
|
<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">
|
<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>
|
<h5 class="fw-bold text-primary mb-0"><i class="bi bi-calendar-check me-2"></i>Informasi Agenda
|
||||||
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<label class="form-label fw-bold">Judul Kegiatan / Materi Latihan</label>
|
<label class="form-label fw-bold">Judul Kegiatan / Materi Latihan <span
|
||||||
|
class="text-danger">*</span></label>
|
||||||
<input type="text" name="judul_kegiatan" class="form-control"
|
<input type="text" name="judul_kegiatan" class="form-control"
|
||||||
value="{{ old('judul_kegiatan', $jadwal->judul_kegiatan) }}" required>
|
value="{{ old('judul_kegiatan', $jadwal->judul_kegiatan) }}" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Kelompok Latihan (Kolat)</label>
|
<label class="form-label fw-bold">Kelompok Latihan (Kolat) <span
|
||||||
|
class="text-danger">*</span></label>
|
||||||
<select name="kolat_id" class="form-select" required>
|
<select name="kolat_id" class="form-select" required>
|
||||||
@foreach($data_kolat as $kolat)
|
<option value="" disabled>-- Pilih Kolat --</option>
|
||||||
<option value="{{ $kolat->id }}" {{ $jadwal->kolat_id == $kolat->id ? 'selected' : '' }}>
|
@foreach ($data_kolat as $kolat)
|
||||||
|
<option value="{{ $kolat->id }}"
|
||||||
|
{{ $jadwal->kolat_id == $kolat->id ? 'selected' : '' }}>
|
||||||
{{ $kolat->nama_kolat }}
|
{{ $kolat->nama_kolat }}
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
@ -44,10 +49,13 @@ class="text-muted text-decoration-none small">Daftar Jadwal</a></li>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Pelatih Bertugas</label>
|
<label class="form-label fw-bold">Pelatih Bertugas <span
|
||||||
|
class="text-danger">*</span></label>
|
||||||
<select name="pelatih_id" class="form-select" required>
|
<select name="pelatih_id" class="form-select" required>
|
||||||
@foreach($data_pelatih as $pelatih)
|
<option value="" disabled>-- Pilih Pelatih --</option>
|
||||||
<option value="{{ $pelatih->id }}" {{ $jadwal->pelatih_id == $pelatih->id ? 'selected' : '' }}>
|
@foreach ($data_pelatih as $pelatih)
|
||||||
|
<option value="{{ $pelatih->id }}"
|
||||||
|
{{ $jadwal->pelatih_id == $pelatih->id ? 'selected' : '' }}>
|
||||||
{{ $pelatih->nama_lengkap }}
|
{{ $pelatih->nama_lengkap }}
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
@ -55,12 +63,12 @@ class="text-muted text-decoration-none small">Daftar Jadwal</a></li>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label class="form-label fw-bold">Tanggal</label>
|
<label class="form-label fw-bold">Tanggal <span class="text-danger">*</span></label>
|
||||||
<input type="date" name="tanggal" class="form-control"
|
<input type="date" name="tanggal" class="form-control"
|
||||||
value="{{ old('tanggal', $jadwal->tanggal) }}" required>
|
value="{{ old('tanggal', $jadwal->tanggal) }}" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label class="form-label fw-bold">Jam Mulai</label>
|
<label class="form-label fw-bold">Jam Mulai <span class="text-danger">*</span></label>
|
||||||
<input type="time" name="jam_mulai" class="form-control"
|
<input type="time" name="jam_mulai" class="form-control"
|
||||||
value="{{ old('jam_mulai', substr($jadwal->jam_mulai, 0, 5)) }}" required>
|
value="{{ old('jam_mulai', substr($jadwal->jam_mulai, 0, 5)) }}" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -71,23 +79,29 @@ class="text-muted text-decoration-none small">Daftar Jadwal</a></li>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Lokasi / Tempat Latihan</label>
|
<label class="form-label fw-bold">Lokasi / Tempat Latihan <span
|
||||||
|
class="text-danger">*</span></label>
|
||||||
<input type="text" name="lokasi" class="form-control"
|
<input type="text" name="lokasi" class="form-control"
|
||||||
value="{{ old('lokasi', $jadwal->lokasi) }}" placeholder="Contoh: GOR Perjuangan" required>
|
value="{{ old('lokasi', $jadwal->lokasi) }}" placeholder="Contoh: GOR Perjuangan"
|
||||||
|
required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Tipe Agenda</label>
|
<label class="form-label fw-bold">Tipe Agenda <span class="text-danger">*</span></label>
|
||||||
<select name="jenis" class="form-select" required>
|
<select name="jenis" class="form-select" required>
|
||||||
<option value="Rutin" {{ $jadwal->jenis == 'Rutin' ? 'selected' : '' }}>Rutin</option>
|
<option value="Rutin" {{ $jadwal->jenis == 'Rutin' ? 'selected' : '' }}>Rutin
|
||||||
<option value="Tambahan" {{ $jadwal->jenis == 'Tambahan' ? 'selected' : '' }}>Tambahan</option>
|
</option>
|
||||||
<option value="Pengumuman" {{ $jadwal->jenis == 'Pengumuman' ? 'selected' : '' }}>Pengumuman</option>
|
<option value="Tambahan" {{ $jadwal->jenis == 'Tambahan' ? 'selected' : '' }}>
|
||||||
|
Tambahan</option>
|
||||||
|
<option value="Pengumuman" {{ $jadwal->jenis == 'Pengumuman' ? 'selected' : '' }}>
|
||||||
|
Pengumuman</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<label class="form-label fw-bold">Deskripsi / Catatan Tambahan</label>
|
<label class="form-label fw-bold">Deskripsi / Catatan Tambahan</label>
|
||||||
<textarea name="deskripsi" class="form-control" rows="3">{{ old('deskripsi', $jadwal->deskripsi) }}</textarea>
|
<textarea name="deskripsi" class="form-control" rows="3"
|
||||||
|
placeholder="Tuliskan peralatan yang harus dibawa, atau informasi penting lainnya...">{{ old('deskripsi', $jadwal->deskripsi) }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -95,10 +109,18 @@ class="text-muted text-decoration-none small">Daftar Jadwal</a></li>
|
||||||
<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-between align-items-center">
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<div class="small text-muted">
|
<div class="small text-muted">
|
||||||
Status saat ini: <span class="badge bg-{{ $jadwal->status == 'selesai' ? 'success' : 'secondary' }}">{{ strtoupper($jadwal->status) }}</span>
|
Status saat ini:
|
||||||
|
@php
|
||||||
|
$badgeColor = 'secondary';
|
||||||
|
if ($jadwal->status == 'selesai') {
|
||||||
|
$badgeColor = 'success';
|
||||||
|
}
|
||||||
|
@endphp
|
||||||
|
<span class="badge bg-{{ $badgeColor }}">{{ strtoupper($jadwal->status) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex gap-3">
|
<div class="d-flex gap-3">
|
||||||
<a href="{{ route('jadwal.index') }}" class="btn btn-outline-secondary px-4 fw-bold btn-cancel">
|
<a href="{{ route('jadwal.index') }}"
|
||||||
|
class="btn btn-outline-secondary px-4 fw-bold btn-cancel">
|
||||||
Batal
|
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">
|
||||||
|
|
@ -109,24 +131,45 @@ class="text-muted text-decoration-none small">Daftar Jadwal</a></li>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.form-control, .form-select { border-radius: 10px; padding: 10px 15px; }
|
.form-control,
|
||||||
.btn-cancel { border-radius: 12px; transition: 0.3s; border: 2px solid #6c757d; }
|
.form-select {
|
||||||
.btn-save { border-radius: 12px; background: linear-gradient(45deg, #0d6efd, #004fb1); border: none; transition: 0.3s; }
|
border-radius: 10px;
|
||||||
.btn-save:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(13, 110, 253, 0.4) !important; }
|
padding: 10px 15px;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control:focus,
|
||||||
|
.form-select:focus {
|
||||||
|
border-color: #0d6efd;
|
||||||
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-cancel {
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: 0.3s;
|
||||||
|
border: 2px solid #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-cancel:hover {
|
||||||
|
background-color: #6c757d;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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>
|
</style>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,12 @@
|
||||||
<h5 class="card-title mb-0 fw-bold text-dark">Agenda PPS Merpati Putih</h5>
|
<h5 class="card-title mb-0 fw-bold text-dark">Agenda PPS Merpati Putih</h5>
|
||||||
<p class="text-muted small mb-0">Cabang Jember - Kelola jadwal rutin dan pengumuman latihan.</p>
|
<p class="text-muted small mb-0">Cabang Jember - Kelola jadwal rutin dan pengumuman latihan.</p>
|
||||||
</div>
|
</div>
|
||||||
<a href="{{ route('jadwal.create') }}" class="btn btn-primary px-4 py-2 shadow-sm"
|
<a href="{{ route('jadwal.create') }}" class="btn btn-primary px-4 py-2 shadow-sm" style="border-radius: 12px;">
|
||||||
style="border-radius: 12px;">
|
<i class="bi bi-plus-lg me-1"></i> Buat Jadwal
|
||||||
<i class="icon-plus me-1"></i> Buat Jadwal
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- TABEL DATA JADWAL --}}
|
||||||
<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">
|
||||||
<thead>
|
<thead>
|
||||||
|
|
@ -50,7 +50,6 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
@forelse ($data_jadwal as $no => $item)
|
@forelse ($data_jadwal as $no => $item)
|
||||||
@php
|
@php
|
||||||
// Set timezone ke Jakarta agar sinkron dengan waktu Indonesia
|
|
||||||
$now = \Carbon\Carbon::now('Asia/Jakarta');
|
$now = \Carbon\Carbon::now('Asia/Jakarta');
|
||||||
$start = \Carbon\Carbon::parse($item->tanggal . ' ' . $item->jam_mulai, 'Asia/Jakarta');
|
$start = \Carbon\Carbon::parse($item->tanggal . ' ' . $item->jam_mulai, 'Asia/Jakarta');
|
||||||
$end = $item->jam_selesai
|
$end = $item->jam_selesai
|
||||||
|
|
@ -59,7 +58,6 @@
|
||||||
|
|
||||||
$dbStatus = trim(strtolower($item->status));
|
$dbStatus = trim(strtolower($item->status));
|
||||||
|
|
||||||
// Logika Penentuan Label Status
|
|
||||||
if ($dbStatus == 'selesai') {
|
if ($dbStatus == 'selesai') {
|
||||||
$status_label = 'Selesai';
|
$status_label = 'Selesai';
|
||||||
$status_color = 'success';
|
$status_color = 'success';
|
||||||
|
|
@ -84,7 +82,7 @@
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<small class="text-muted text-start ps-2 d-block">
|
<small class="text-muted text-start ps-2 d-block">
|
||||||
<i class="icon-user small"></i> {{ $item->pelatih->nama_lengkap ?? 'Belum Ditentukan' }}
|
<i class="bi bi-person-fill small"></i> {{ $item->pelatih->nama_lengkap ?? 'Belum Ditentukan' }}
|
||||||
</small>
|
</small>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
|
|
@ -94,13 +92,13 @@
|
||||||
</td>
|
</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="bi bi-calendar-event me-1"></i> {{ \Carbon\Carbon::parse($item->tanggal)->format('d M Y') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="small text-muted">
|
<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' }}
|
<i class="bi bi-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 text-danger"></i> {{ $item->lokasi }}
|
<i class="bi bi-geo-alt-fill me-1 text-danger"></i> {{ $item->lokasi }}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
|
|
@ -117,31 +115,148 @@
|
||||||
<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">
|
||||||
|
|
||||||
{{-- TOMBOL KONFIRMASI: Muncul jika sudah masuk jamnya, bukan pengumuman, dan belum selesai --}}
|
|
||||||
@if($dbStatus != 'selesai' && $item->jenis != 'Pengumuman' && $now->greaterThanOrEqualTo($start))
|
@if($dbStatus != 'selesai' && $item->jenis != 'Pengumuman' && $now->greaterThanOrEqualTo($start))
|
||||||
<form action="{{ route('jadwal.konfirmasi', $item->id) }}" method="POST" id="form-selesai-{{ $item->id }}" class="d-inline">
|
<button class="btn btn-sm btn-success fw-bold px-2 shadow-xs" style="border-radius: 10px;" data-bs-toggle="modal" data-bs-target="#modalKonfirmasi{{ $item->id }}">
|
||||||
@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>
|
<i class="bi bi-check2-square"></i>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<button class="btn btn-sm btn-action-detail fw-bold px-2 shadow-xs"
|
<button class="btn btn-sm btn-action-detail fw-bold px-2 shadow-xs" data-bs-toggle="modal" data-bs-target="#modalDetailJadwal{{ $item->id }}">
|
||||||
data-bs-toggle="modal"
|
<i class="bi bi-eye"></i>
|
||||||
data-bs-target="#modalDetailJadwal{{ $item->id }}">
|
|
||||||
<i class="icon-eye"></i>
|
|
||||||
</button>
|
</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-2 shadow-xs">
|
||||||
class="btn btn-sm btn-action-edit fw-bold px-2 shadow-xs">
|
<i class="bi bi-pencil"></i>
|
||||||
<i class="icon-pencil"></i>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<form action="{{ route('jadwal.destroy', $item->id) }}" method="POST" id="form-hapus-{{ $item->id }}" class="d-inline">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button type="button" class="btn btn-sm btn-action-delete fw-bold px-2 shadow-xs" onclick="hapusJadwal('{{ $item->id }}', '{{ addslashes($item->judul_kegiatan) }}')">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" class="text-center py-5 text-muted small">Belum ada jadwal latihan atau pengumuman.</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- KUMPULAN MODAL DITEMPATKAN DI LUAR TABLE --}}
|
||||||
|
@foreach ($data_jadwal as $item)
|
||||||
|
@php
|
||||||
|
// Perlu inisialisasi status lagi untuk tampilan dalam Modal
|
||||||
|
$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));
|
||||||
|
|
||||||
|
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 KONFIRMASI SELESAI --}}
|
||||||
|
<div class="modal fade" id="modalKonfirmasi{{ $item->id }}" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||||
|
<div class="modal-content" style="border-radius: 20px; border: none;">
|
||||||
|
<div class="modal-header bg-success text-white border-0 py-3 px-4">
|
||||||
|
<h5 class="modal-title fw-bold">
|
||||||
|
<i class="bi bi-check-circle me-2"></i>Konfirmasi Latihan Selesai
|
||||||
|
</h5>
|
||||||
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<form action="{{ route('jadwal.konfirmasi', $item->id) }}" method="POST" enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
<div class="modal-body p-4 text-start">
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<h6 class="fw-bold"><i class="bi bi-people-fill me-2"></i>Rekapitulasi Kehadiran</h6>
|
||||||
|
<div class="table-responsive border rounded" style="max-height: 250px; overflow-y: auto;">
|
||||||
|
<table class="table table-sm table-hover mb-0">
|
||||||
|
<thead class="table-light sticky-top">
|
||||||
|
<tr>
|
||||||
|
<th class="ps-3 py-2 text-muted small">No</th>
|
||||||
|
<th class="py-2 text-muted small">Nama Anggota</th>
|
||||||
|
<th class="py-2 text-center text-muted small">Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@php
|
||||||
|
$semua_absen = $item->presensi ? $item->presensi->where('is_verified', true) : collect([]);
|
||||||
|
$total_hadir = $semua_absen->where('status', 'Hadir')->count();
|
||||||
|
@endphp
|
||||||
|
@forelse($semua_absen as $idx => $absen)
|
||||||
|
<tr>
|
||||||
|
<td class="ps-3 py-2 small text-muted">{{ $idx + 1 }}</td>
|
||||||
|
<td class="py-2 small fw-bold text-dark">{{ $absen->anggota->nama_lengkap ?? 'Tidak diketahui' }}</td>
|
||||||
|
<td class="py-2 text-center">
|
||||||
|
@php
|
||||||
|
$bgBadge = 'bg-secondary';
|
||||||
|
if($absen->status == 'Hadir') $bgBadge = 'bg-success';
|
||||||
|
elseif($absen->status == 'Izin') $bgBadge = 'bg-info';
|
||||||
|
elseif($absen->status == 'Sakit') $bgBadge = 'bg-warning text-dark';
|
||||||
|
elseif($absen->status == 'Alfa') $bgBadge = 'bg-danger';
|
||||||
|
@endphp
|
||||||
|
<span class="badge {{ $bgBadge }}">{{ $absen->status }}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" class="text-center py-4 small text-muted">Belum ada data presensi yang diverifikasi.</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 small text-muted">
|
||||||
|
<strong>Total Hadir:</strong> {{ $total_hadir }} Orang
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label fw-bold">Upload Foto Kegiatan (Wajib) <span class="text-danger">*</span></label>
|
||||||
|
<input type="file" name="foto_bukti" class="form-control" accept="image/*" required style="border-radius: 10px;">
|
||||||
|
<small class="text-muted">Upload foto bersama sebagai bukti latihan telah dilaksanakan.</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label fw-bold">Catatan Latihan (Opsional)</label>
|
||||||
|
<textarea name="catatan_latihan" class="form-control" rows="3" placeholder="Tulis evaluasi atau materi yang diajarkan hari ini..." style="border-radius: 10px;"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<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;">Batal</button>
|
||||||
|
<button type="submit" class="btn btn-success px-4 shadow-sm" style="border-radius: 10px;">Sahkan Latihan</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- MODAL DETAIL JADWAL --}}
|
{{-- 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">
|
||||||
|
|
@ -149,7 +264,7 @@ class="btn btn-sm btn-action-edit fw-bold px-2 shadow-xs">
|
||||||
<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">
|
||||||
<i class="icon-calendar me-2"></i>Detail Agenda Latihan
|
<i class="bi bi-calendar-event me-2"></i>Detail Agenda Latihan
|
||||||
</h5>
|
</h5>
|
||||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -157,9 +272,8 @@ class="btn btn-sm btn-action-edit fw-bold px-2 shadow-xs">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<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: 100px; height: 100px; border: 4px solid #f8f9fa;">
|
||||||
style="width: 100px; height: 100px; border: 4px solid #f8f9fa;">
|
<i class="bi bi-clipboard-data text-primary" style="font-size: 50px;"></i>
|
||||||
<i class="icon-clipboard text-primary" style="font-size: 50px;"></i>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h5 class="fw-bold mb-1 text-dark">{{ $item->judul_kegiatan }}</h5>
|
<h5 class="fw-bold mb-1 text-dark">{{ $item->judul_kegiatan }}</h5>
|
||||||
|
|
@ -176,10 +290,35 @@ class="btn btn-sm btn-action-edit fw-bold px-2 shadow-xs">
|
||||||
<small class="text-muted d-block small">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-12 mt-2">
|
||||||
|
<div class="p-3 bg-light rounded" style="border-left: 4px solid #0d6efd;">
|
||||||
|
<small class="text-muted d-block fw-bold mb-1">Waktu Pelaksanaan</small>
|
||||||
|
<div class="d-flex align-items-center gap-3">
|
||||||
|
<div>
|
||||||
|
<i class="bi bi-calendar3 text-primary me-1"></i>
|
||||||
|
<span class="fw-bold text-dark">{{ \Carbon\Carbon::parse($item->tanggal)->isoFormat('dddd, D MMMM Y') }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="border-start ps-3">
|
||||||
|
<i class="bi bi-clock-history text-primary me-1"></i>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-12 mt-3">
|
<div class="col-12 mt-3">
|
||||||
<h6 class="fw-bold text-primary border-bottom pb-1 small">Deskripsi Kegiatan</h6>
|
<h6 class="fw-bold text-primary border-bottom pb-1 small">Deskripsi Kegiatan</h6>
|
||||||
<p class="small text-muted mb-0" style="white-space: pre-line;">{{ $item->deskripsi ?? 'Tidak ada deskripsi.' }}</p>
|
<p class="small text-muted mb-0" style="white-space: pre-line;">{{ $item->deskripsi ?? 'Tidak ada deskripsi.' }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if($item->foto_bukti)
|
||||||
|
<div class="col-12 mt-3">
|
||||||
|
<h6 class="fw-bold text-success border-bottom pb-1 small mt-2">Bukti Kegiatan & Catatan</h6>
|
||||||
|
<p class="small text-muted mb-2">"{{ $item->catatan_latihan ?? 'Tidak ada catatan khusus.' }}"</p>
|
||||||
|
<img src="{{ asset('storage/' . $item->foto_bukti) }}" class="img-fluid rounded shadow-sm" style="max-height: 200px; object-fit: cover;">
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -190,20 +329,7 @@ class="btn btn-sm btn-action-edit fw-bold px-2 shadow-xs">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@empty
|
@endforeach
|
||||||
<tr>
|
|
||||||
<td colspan="6" class="text-center py-5 text-muted small">Belum ada jadwal latihan atau pengumuman.</td>
|
|
||||||
</tr>
|
|
||||||
@endforelse
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
<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 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; }
|
||||||
|
|
@ -214,30 +340,35 @@ class="btn btn-sm btn-action-edit fw-bold px-2 shadow-xs">
|
||||||
.bg-secondary-soft { background-color: #f3f4f6; color: #6b7280; }
|
.bg-secondary-soft { background-color: #f3f4f6; color: #6b7280; }
|
||||||
.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-delete { background-color: #fff5f5; color: #dc3545; border: 1px solid #f8d7da; 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); }
|
||||||
|
.btn-action-delete:hover { background-color: #dc3545 !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); }
|
||||||
|
|
||||||
|
.table-responsive::-webkit-scrollbar { width: 6px; }
|
||||||
|
.table-responsive::-webkit-scrollbar-thumb { background-color: #cbd5e1; border-radius: 10px; }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function konfirmasiLatihan(id, judul) {
|
function hapusJadwal(id, judul) {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: 'Konfirmasi Selesai',
|
title: 'Hapus Jadwal?',
|
||||||
text: "Apakah benar latihan '" + judul + "' telah dilaksanakan?",
|
text: "Jadwal '" + judul + "' akan dihapus permanen beserta semua data presensinya!",
|
||||||
icon: 'question',
|
icon: 'warning',
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
confirmButtonColor: '#198754', // Warna hijau sukses
|
confirmButtonColor: '#dc3545',
|
||||||
cancelButtonColor: '#6c757d',
|
cancelButtonColor: '#6c757d',
|
||||||
confirmButtonText: 'Ya, Sudah Selesai!',
|
confirmButtonText: 'Ya, Hapus!',
|
||||||
cancelButtonText: 'Batal',
|
cancelButtonText: 'Batal',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '20px'
|
borderRadius: '20px'
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
// Submit form jika user klik OK
|
document.getElementById('form-hapus-' + id).submit();
|
||||||
document.getElementById('form-selesai-' + id).submit();
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -212,10 +212,15 @@
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
<a class="dropdown-item d-flex align-items-center" href="{{ route('logout') }}"
|
||||||
|
onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
||||||
<i class="bi bi-box-arrow-right"></i>
|
<i class="bi bi-box-arrow-right"></i>
|
||||||
<span>Sign Out</span>
|
<span>Sign Out</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
|
||||||
|
@csrf
|
||||||
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
</ul><!-- End Profile Dropdown Items -->
|
</ul><!-- End Profile Dropdown Items -->
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
|
@php
|
||||||
|
// Ambil nama role user yang login saat ini
|
||||||
|
$userRole = auth()->user()->role->nama_role ?? 'Anggota';
|
||||||
|
@endphp
|
||||||
|
|
||||||
<aside id="sidebar" class="sidebar">
|
<aside id="sidebar" class="sidebar">
|
||||||
<ul class="sidebar-nav" id="sidebar-nav">
|
<ul class="sidebar-nav" id="sidebar-nav">
|
||||||
|
|
||||||
|
{{-- MENU DASHBOARD (Semua Role Bisa Akses) --}}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {{ request()->routeIs('dashboard') ? '' : 'collapsed' }}" href="{{ route('dashboard') }}">
|
<a class="nav-link {{ request()->routeIs('dashboard') ? '' : 'collapsed' }}" href="{{ route('dashboard') }}">
|
||||||
<i class="bi bi-grid"></i>
|
<i class="bi bi-grid"></i>
|
||||||
|
|
@ -8,6 +14,8 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
{{-- MENU MANAJEMEN ANGGOTA (Hanya Pelatih & Pengurus) --}}
|
||||||
|
@if($userRole != 'Anggota')
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {{ request()->routeIs(['pelatih.*', 'anggota.*', 'kolat.*']) ? '' : 'collapsed' }}"
|
<a class="nav-link {{ request()->routeIs(['pelatih.*', 'anggota.*', 'kolat.*']) ? '' : 'collapsed' }}"
|
||||||
data-bs-target="#anggota-nav" data-bs-toggle="collapse" href="#" aria-expanded="{{ request()->routeIs(['pelatih.*', 'anggota.*', 'kolat.*']) ? 'true' : 'false' }}">
|
data-bs-target="#anggota-nav" data-bs-toggle="collapse" href="#" aria-expanded="{{ request()->routeIs(['pelatih.*', 'anggota.*', 'kolat.*']) ? 'true' : 'false' }}">
|
||||||
|
|
@ -31,15 +39,28 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- MENU MANAJEMEN LATIHAN (Semua Bisa Akses, Tapi Isinya Beda) --}}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {{ request()->routeIs(['presensi.*', 'jadwal.*']) ? '' : 'collapsed' }}"
|
<a class="nav-link {{ request()->routeIs(['presensi.*', 'jadwal.*']) ? '' : 'collapsed' }}"
|
||||||
data-bs-target="#latihan-nav" data-bs-toggle="collapse" href="#" aria-expanded="{{ request()->routeIs(['presensi.*', 'jadwal.*']) ? 'true' : 'false' }}">
|
data-bs-target="#latihan-nav" data-bs-toggle="collapse" href="#" aria-expanded="{{ request()->routeIs(['presensi.*', 'jadwal.*']) ? 'true' : 'false' }}">
|
||||||
<i class="bi bi-journal-check"></i><span>Manajemen Latihan</span><i class="bi bi-chevron-down ms-auto"></i>
|
<i class="bi bi-journal-check"></i><span>Manajemen Latihan</span><i class="bi bi-chevron-down ms-auto"></i>
|
||||||
</a>
|
</a>
|
||||||
<ul id="latihan-nav" class="nav-content collapse {{ request()->routeIs(['presensi.*', 'jadwal.*']) ? 'show' : '' }}" data-bs-parent="#sidebar-nav">
|
<ul id="latihan-nav" class="nav-content collapse {{ request()->routeIs(['presensi.*', 'jadwal.*']) ? 'show' : '' }}" data-bs-parent="#sidebar-nav">
|
||||||
|
|
||||||
|
{{-- Jika Login Sebagai ANGGOTA --}}
|
||||||
|
@if($userRole == 'Anggota')
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ route('presensi.index') }}" class="{{ request()->routeIs('presensi.*') ? 'active' : '' }}">
|
<a href="{{ route('presensi.anggota.index') }}" class="{{ request()->routeIs('presensi.anggota.*') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-circle"></i><span>Kehadiran Latihan</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{{-- Jika Login Sebagai PELATIH / PENGURUS --}}
|
||||||
|
@else
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('presensi.index') }}" class="{{ request()->routeIs('presensi.index', 'presensi.kehadiran') ? 'active' : '' }}">
|
||||||
<i class="bi bi-circle"></i><span>Presensi</span>
|
<i class="bi bi-circle"></i><span>Presensi</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -49,19 +70,25 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#"><i class="bi bi-circle"></i><span>Penilaian Pelatih</span></a></li>
|
<li><a href="#"><i class="bi bi-circle"></i><span>Penilaian Pelatih</span></a></li>
|
||||||
|
@endif
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
{{-- MENU TRANSAKSI (Semua Bisa Akses, Tapi Anggota Cuma Lihat SPP) --}}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link collapsed" data-bs-target="#transaksi-nav" data-bs-toggle="collapse" href="#">
|
<a class="nav-link collapsed" data-bs-target="#transaksi-nav" data-bs-toggle="collapse" href="#">
|
||||||
<i class="bi bi-wallet2"></i><span>Transaksi</span><i class="bi bi-chevron-down ms-auto"></i>
|
<i class="bi bi-wallet2"></i><span>Transaksi</span><i class="bi bi-chevron-down ms-auto"></i>
|
||||||
</a>
|
</a>
|
||||||
<ul id="transaksi-nav" class="nav-content collapse" data-bs-parent="#sidebar-nav">
|
<ul id="transaksi-nav" class="nav-content collapse" data-bs-parent="#sidebar-nav">
|
||||||
|
@if($userRole != 'Anggota')
|
||||||
<li><a href="#"><i class="bi bi-circle"></i><span>Kas Cabang</span></a></li>
|
<li><a href="#"><i class="bi bi-circle"></i><span>Kas Cabang</span></a></li>
|
||||||
|
@endif
|
||||||
<li><a href="#"><i class="bi bi-circle"></i><span>SPP Anggota</span></a></li>
|
<li><a href="#"><i class="bi bi-circle"></i><span>SPP Anggota</span></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
{{-- MENU LAPORAN (Hanya Pelatih & Pengurus) --}}
|
||||||
|
@if($userRole != 'Anggota')
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link collapsed" data-bs-target="#laporan-nav" data-bs-toggle="collapse" href="#">
|
<a class="nav-link collapsed" data-bs-target="#laporan-nav" data-bs-toggle="collapse" href="#">
|
||||||
<i class="bi bi-file-earmark-bar-graph"></i><span>Laporan</span><i class="bi bi-chevron-down ms-auto"></i>
|
<i class="bi bi-file-earmark-bar-graph"></i><span>Laporan</span><i class="bi bi-chevron-down ms-auto"></i>
|
||||||
|
|
@ -73,7 +100,9 @@
|
||||||
<li><a href="#"><i class="bi bi-circle"></i><span>Laporan Penilaian</span></a></li>
|
<li><a href="#"><i class="bi bi-circle"></i><span>Laporan Penilaian</span></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- MENU AKUN (Semua Bisa Akses) --}}
|
||||||
<li class="nav-heading">Akun</li>
|
<li class="nav-heading">Akun</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link collapsed" href="#"><i class="bi bi-person"></i><span>Profile</span></a>
|
<a class="nav-link collapsed" href="#"><i class="bi bi-person"></i><span>Profile</span></a>
|
||||||
|
|
@ -87,15 +116,10 @@
|
||||||
</ul>
|
</ul>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
{{-- SCRIPT PENTING: Supaya menu yang otomatis terbuka BISA DITUTUP KEMBALI --}}
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
// Cari semua dropdown yang punya class 'show' (dibuka otomatis oleh Laravel)
|
|
||||||
var bootstrapCollapseMenus = document.querySelectorAll('.nav-content.collapse.show');
|
var bootstrapCollapseMenus = document.querySelectorAll('.nav-content.collapse.show');
|
||||||
|
|
||||||
bootstrapCollapseMenus.forEach(function (menuElement) {
|
bootstrapCollapseMenus.forEach(function (menuElement) {
|
||||||
// Kita kasih tahu Bootstrap secara manual: "Woi, ini menu udah kebuka!"
|
|
||||||
// Dengan inisialisasi ini, klik berikutnya akan menjalankan fungsi 'hide'
|
|
||||||
new bootstrap.Collapse(menuElement, {
|
new bootstrap.Collapse(menuElement, {
|
||||||
toggle: false
|
toggle: false
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,18 @@
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="container-fluid py-4">
|
<div class="container-fluid py-4">
|
||||||
<div class="page-header mb-4 text-start">
|
<div class="d-flex justify-content-between align-items-end mb-4 text-start">
|
||||||
<h3 class="fw-bold text-dark">Kehadiran Latihan</h3>
|
<div>
|
||||||
<p class="text-muted small">Silakan lakukan absensi mandiri untuk jadwal hari ini.</p>
|
<h3 class="fw-bold text-dark mb-1">Kehadiran Latihan</h3>
|
||||||
|
<p class="text-muted small mb-0">Jadwal hari ini & riwayat 7 hari terakhir.</p>
|
||||||
|
</div>
|
||||||
|
{{-- Tombol menuju route riwayat yang akan kita buat nanti --}}
|
||||||
|
<a href="{{ route('presensi.anggota.riwayat') }}" class="btn btn-outline-primary shadow-sm fw-bold" style="border-radius: 12px;">
|
||||||
|
<i class="bi bi-clock-history me-1"></i> Riwayat Lengkap
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- Notifikasi --}}
|
||||||
@if(session('success'))
|
@if(session('success'))
|
||||||
<div class="alert alert-success alert-dismissible fade show border-0 shadow-sm rounded-3 mb-4">
|
<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') }}
|
<i class="bi bi-check-circle-fill me-2"></i> {{ session('success') }}
|
||||||
|
|
@ -21,57 +28,138 @@
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<div class="row">
|
{{-- PISAHKAN JADWAL HARI INI DAN SEBELUMNYA --}}
|
||||||
@forelse($jadwal_hari_ini as $jadwal)
|
@php
|
||||||
|
$jadwalHariIni = $jadwal_terbaru->where('tanggal', $hari_ini);
|
||||||
|
$jadwalSebelumnya = $jadwal_terbaru->where('tanggal', '!=', $hari_ini);
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
{{-- SEGMEN 1: JADWAL HARI INI --}}
|
||||||
|
<h5 class="fw-bold text-dark mb-3"><i class="bi bi-calendar-event-fill text-primary me-2"></i>Jadwal Hari Ini</h5>
|
||||||
|
<div class="row mb-5">
|
||||||
|
@forelse($jadwalHariIni as $jadwal)
|
||||||
<div class="col-md-6 col-lg-4 mb-4">
|
<div class="col-md-6 col-lg-4 mb-4">
|
||||||
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
|
<div class="card border-0 shadow-sm h-100" style="border-radius: 20px; transition: 0.3s; border-top: 5px solid #0d6efd !important;">
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4 d-flex flex-column">
|
||||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
<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">
|
<span class="badge bg-primary-soft text-primary px-3 py-2 rounded-pill shadow-xs">
|
||||||
{{ $jadwal->jenis }}
|
{{ $jadwal->jenis }}
|
||||||
</span>
|
</span>
|
||||||
<span class="small fw-bold text-muted">{{ \Carbon\Carbon::parse($jadwal->tanggal)->format('d M Y') }}</span>
|
<span class="small fw-bold text-dark text-end">Hari Ini</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h5 class="fw-bold text-dark mb-1">{{ $jadwal->judul_kegiatan }}</h5>
|
<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>
|
<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="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 fw-bold text-dark mb-1">
|
||||||
<div class="small text-muted"><i class="bi bi-geo-alt-fill me-2 text-danger"></i>{{ $jadwal->lokasi }}</div>
|
<i class="bi bi-clock me-2 text-primary"></i>
|
||||||
|
{{ substr($jadwal->jam_mulai, 0, 5) }} - {{ $jadwal->jam_selesai ? substr($jadwal->jam_selesai, 0, 5) : 'Selesai' }} WIB
|
||||||
|
</div>
|
||||||
|
<div class="small text-muted text-truncate">
|
||||||
|
<i class="bi bi-geo-alt-fill me-2 text-danger"></i>{{ $jadwal->lokasi }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- LOGIKA TOMBOL ABSEN --}}
|
<div class="mt-auto">
|
||||||
@if(isset($presensi_saya[$jadwal->id]))
|
@if(isset($presensi_saya[$jadwal->id]))
|
||||||
{{-- Jika sudah absen --}}
|
{{-- Sudah Absen Hari Ini --}}
|
||||||
@if($presensi_saya[$jadwal->id]->is_verified)
|
@if($presensi_saya[$jadwal->id]->is_verified)
|
||||||
<button class="btn btn-success w-100 fw-bold disabled py-2" style="border-radius: 12px;">
|
<div class="text-center p-2 rounded-3 bg-success-soft text-success border border-success fw-bold">
|
||||||
<i class="bi bi-check2-all me-1"></i> Kehadiran Disahkan
|
<i class="bi bi-patch-check-fill me-1"></i> Kehadiran Disahkan
|
||||||
</button>
|
</div>
|
||||||
@else
|
@else
|
||||||
<button class="btn btn-warning w-100 fw-bold disabled py-2" style="border-radius: 12px; color: #854d0e; background-color: #fef08a; border:none;">
|
<div class="text-center p-2 rounded-3 bg-warning-soft text-warning border border-warning fw-bold">
|
||||||
<i class="bi bi-hourglass-split me-1"></i> Menunggu Konfirmasi
|
<i class="bi bi-hourglass-split me-1"></i> Menunggu Konfirmasi
|
||||||
</button>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@else
|
@else
|
||||||
{{-- Jika belum absen, tampilkan tombol submit --}}
|
{{-- Belum Absen Hari Ini --}}
|
||||||
<form action="{{ route('anggota.presensi.store') }}" method="POST">
|
@php
|
||||||
@csrf
|
$end = $jadwal->jam_selesai
|
||||||
<input type="hidden" name="jadwal_id" value="{{ $jadwal->id }}">
|
? \Carbon\Carbon::parse($jadwal->tanggal . ' ' . $jadwal->jam_selesai, 'Asia/Jakarta')
|
||||||
<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?')">
|
: \Carbon\Carbon::parse($jadwal->tanggal . ' ' . $jadwal->jam_mulai, 'Asia/Jakarta')->addHours(3);
|
||||||
<i class="bi bi-hand-index-thumb me-1"></i> Absen Sekarang
|
@endphp
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
|
@if($now->gt($end))
|
||||||
|
<button class="btn btn-secondary w-100 fw-bold py-2 disabled" style="border-radius: 12px; opacity: 0.6;">
|
||||||
|
<i class="bi bi-lock-fill me-1"></i> Sesi Absen Berakhir
|
||||||
|
</button>
|
||||||
|
@elseif($jadwal->status == 'selesai')
|
||||||
|
<button class="btn btn-secondary w-100 fw-bold py-2 disabled" style="border-radius: 12px; opacity: 0.6;">
|
||||||
|
<i class="bi bi-x-circle me-1"></i> Latihan Ditutup Pelatih
|
||||||
|
</button>
|
||||||
|
@else
|
||||||
|
<a href="{{ route('presensi.anggota.scan', $jadwal->id) }}" class="btn btn-primary w-100 fw-bold py-2 shadow-sm btn-scan" style="border-radius: 12px;">
|
||||||
|
<i class="bi bi-qr-code-scan me-2"></i> Scan Barcode Sekarang
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@empty
|
@empty
|
||||||
<div class="col-12 text-center py-5">
|
<div class="col-12">
|
||||||
<img src="https://cdn-icons-png.flaticon.com/512/7486/7486747.png" width="120" class="mb-3 opacity-50" alt="No Schedule">
|
<div class="card border-0 shadow-sm" style="border-radius: 20px; background-color: #f8f9fa;">
|
||||||
<h5 class="text-muted fw-bold">Tidak ada jadwal latihan hari ini.</h5>
|
<div class="card-body text-center py-5">
|
||||||
<p class="text-muted small">Selamat istirahat atau berlatih mandiri di rumah!</p>
|
<i class="bi bi-calendar-x text-muted mb-3 d-block" style="font-size: 3rem; opacity: 0.5;"></i>
|
||||||
|
<h6 class="fw-bold text-secondary mb-0">Tidak ada jadwal latihan untuk Anda hari ini.</h6>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforelse
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- SEGMEN 2: RIWAYAT 7 HARI TERAKHIR --}}
|
||||||
|
<h5 class="fw-bold text-dark mb-3"><i class="bi bi-clock-history text-secondary me-2"></i>Riwayat Minggu Ini</h5>
|
||||||
|
<div class="row">
|
||||||
|
@forelse($jadwalSebelumnya as $jadwal)
|
||||||
|
<div class="col-md-6 col-lg-4 mb-4">
|
||||||
|
<div class="card border-0 shadow-sm h-100" style="border-radius: 20px; background-color: #fafbfc;">
|
||||||
|
<div class="card-body p-4 d-flex flex-column">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
<h6 class="fw-bold text-dark mb-0 text-truncate">{{ $jadwal->judul_kegiatan }}</h6>
|
||||||
|
<span class="small text-muted" style="font-size: 0.75rem;">{{ \Carbon\Carbon::parse($jadwal->tanggal)->isoFormat('D MMM YYYY') }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-auto">
|
||||||
|
@if(isset($presensi_saya[$jadwal->id]))
|
||||||
|
@php
|
||||||
|
$presensi = $presensi_saya[$jadwal->id];
|
||||||
|
$statusColor = match($presensi->status) {
|
||||||
|
'Hadir' => 'success',
|
||||||
|
'Izin' => 'info',
|
||||||
|
'Sakit' => 'warning',
|
||||||
|
'Alfa' => 'danger',
|
||||||
|
default => 'secondary'
|
||||||
|
};
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
@if($presensi->is_verified)
|
||||||
|
<div class="d-flex align-items-center justify-content-between p-2 rounded-3 bg-{{ $statusColor }}-soft text-{{ $statusColor }} fw-bold" style="font-size: 0.85rem;">
|
||||||
|
<span><i class="bi bi-check-circle-fill me-1"></i> Disahkan</span>
|
||||||
|
<span>{{ $presensi->status }}</span>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="d-flex align-items-center justify-content-between p-2 rounded-3 bg-warning-soft text-warning fw-bold" style="font-size: 0.85rem;">
|
||||||
|
<span><i class="bi bi-hourglass-split me-1"></i> Menunggu</span>
|
||||||
|
<span>Hadir</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@else
|
||||||
|
<div class="d-flex align-items-center justify-content-between p-2 rounded-3 bg-danger-soft text-danger fw-bold" style="font-size: 0.85rem;">
|
||||||
|
<span><i class="bi bi-x-circle-fill me-1"></i> Tidak Absen</span>
|
||||||
|
<span>Alfa</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@empty
|
||||||
|
<div class="col-12 text-center py-4">
|
||||||
|
<p class="text-muted small">Belum ada riwayat latihan dalam 7 hari terakhir.</p>
|
||||||
</div>
|
</div>
|
||||||
@endforelse
|
@endforelse
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -79,5 +167,12 @@
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.bg-primary-soft { background-color: #e0f2fe; color: #0ea5e9; }
|
.bg-primary-soft { background-color: #e0f2fe; color: #0ea5e9; }
|
||||||
|
.bg-success-soft { background-color: #d1e7dd; color: #0f5132; }
|
||||||
|
.bg-warning-soft { background-color: #fff3cd; color: #664d03; }
|
||||||
|
.bg-info-soft { background-color: #cff4fc; color: #055160; }
|
||||||
|
.bg-danger-soft { background-color: #f8d7da; color: #842029; }
|
||||||
|
.btn-scan { background: linear-gradient(45deg, #0d6efd, #004fb1); border: none; transition: 0.3s; }
|
||||||
|
.btn-scan:hover { transform: translateY(-3px); box-shadow: 0 8px 15px rgba(13, 110, 253, 0.3) !important; }
|
||||||
|
.card:hover { transform: translateY(-3px); }
|
||||||
</style>
|
</style>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
@extends('layout.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid py-4">
|
||||||
|
{{-- HEADER & BREADCRUMB --}}
|
||||||
|
<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.anggota.index') }}" class="text-muted text-decoration-none small">Kehadiran</a></li>
|
||||||
|
<li class="breadcrumb-item active text-primary fw-bold small" aria-current="page">Riwayat Lengkap</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<div>
|
||||||
|
<h3 class="fw-bold text-dark mb-1">Riwayat Kehadiran</h3>
|
||||||
|
<p class="text-muted small mb-0">Rekap seluruh partisipasi latihan Anda.</p>
|
||||||
|
</div>
|
||||||
|
<a href="{{ route('presensi.anggota.index') }}" class="btn btn-light border shadow-sm fw-bold" style="border-radius: 12px;">
|
||||||
|
<i class="bi bi-arrow-left me-1"></i> Kembali
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- FILTER BULAN & TAHUN --}}
|
||||||
|
<div class="row mb-4">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
|
||||||
|
<div class="card-body p-4 text-start">
|
||||||
|
<form action="{{ route('presensi.anggota.riwayat') }}" method="GET" class="row g-3 align-items-end">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label class="form-label fw-bold small text-muted">Pilih Bulan</label>
|
||||||
|
<select name="bulan" class="form-select border-2 shadow-none" style="border-radius: 10px;">
|
||||||
|
@php
|
||||||
|
$namaBulan = ['01'=>'Januari', '02'=>'Februari', '03'=>'Maret', '04'=>'April', '05'=>'Mei', '06'=>'Juni', '07'=>'Juli', '08'=>'Agustus', '09'=>'September', '10'=>'Oktober', '11'=>'November', '12'=>'Desember'];
|
||||||
|
@endphp
|
||||||
|
@foreach($namaBulan as $angka => $nama)
|
||||||
|
<option value="{{ $angka }}" {{ $bulan == $angka ? 'selected' : '' }}>{{ $nama }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label class="form-label fw-bold small text-muted">Pilih Tahun</label>
|
||||||
|
<select name="tahun" class="form-select border-2 shadow-none" style="border-radius: 10px;">
|
||||||
|
@for($i = date('Y'); $i >= 2024; $i--)
|
||||||
|
<option value="{{ $i }}" {{ $tahun == $i ? 'selected' : '' }}>{{ $i }}</option>
|
||||||
|
@endfor
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<button type="submit" class="btn btn-primary w-100 fw-bold shadow-sm" style="border-radius: 10px;">
|
||||||
|
<i class="bi bi-funnel-fill me-1"></i> Terapkan Filter
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- TABEL RIWAYAT --}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card border-0 shadow-sm" style="border-radius: 20px;">
|
||||||
|
<div class="card-body p-4 text-start">
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<h5 class="fw-bold text-dark mb-0">Data Bulan {{ $namaBulan[$bulan] }} {{ $tahun }}</h5>
|
||||||
|
<span class="badge bg-primary-soft text-primary px-3 py-2 rounded-pill">Total: {{ $jadwal_riwayat->count() }} Pertemuan</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover align-middle main-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th width="5%" class="text-center">No</th>
|
||||||
|
<th width="20%">Tanggal Latihan</th>
|
||||||
|
<th width="30%">Materi / Kegiatan</th>
|
||||||
|
<th width="15%" class="text-center">Status</th>
|
||||||
|
<th width="15%" class="text-center">Verifikasi</th>
|
||||||
|
<th width="15%">Keterangan</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@forelse($jadwal_riwayat as $no => $jadwal)
|
||||||
|
@php
|
||||||
|
// Pengecekan apakah jadwal sudah lewat waktunya
|
||||||
|
$end = $jadwal->jam_selesai
|
||||||
|
? \Carbon\Carbon::parse($jadwal->tanggal . ' ' . $jadwal->jam_selesai, 'Asia/Jakarta')
|
||||||
|
: \Carbon\Carbon::parse($jadwal->tanggal . ' ' . $jadwal->jam_mulai, 'Asia/Jakarta')->addHours(3);
|
||||||
|
$sudah_lewat = \Carbon\Carbon::now('Asia/Jakarta')->gt($end);
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td class="text-muted small text-center">{{ $no + 1 }}</td>
|
||||||
|
<td>
|
||||||
|
<div class="fw-bold text-dark">{{ \Carbon\Carbon::parse($jadwal->tanggal)->isoFormat('D MMM YYYY') }}</div>
|
||||||
|
<small class="text-muted"><i class="bi bi-clock me-1"></i>{{ substr($jadwal->jam_mulai, 0, 5) }} WIB</small>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="fw-bold text-dark text-truncate" style="max-width: 250px;">{{ $jadwal->judul_kegiatan }}</div>
|
||||||
|
<span class="badge bg-light text-secondary border mt-1" style="font-size: 0.65rem;">{{ $jadwal->jenis }}</span>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
@if(isset($presensi_saya[$jadwal->id]))
|
||||||
|
@php
|
||||||
|
$presensi = $presensi_saya[$jadwal->id];
|
||||||
|
$statusColor = match($presensi->status) {
|
||||||
|
'Hadir' => 'success',
|
||||||
|
'Izin' => 'info',
|
||||||
|
'Sakit' => 'warning',
|
||||||
|
'Alfa' => 'danger',
|
||||||
|
default => 'secondary'
|
||||||
|
};
|
||||||
|
@endphp
|
||||||
|
<span class="badge bg-{{ $statusColor }}-soft text-{{ $statusColor }} px-3 py-2 rounded-pill fw-bold">
|
||||||
|
{{ $presensi->status }}
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
@if($sudah_lewat || $jadwal->status == 'selesai')
|
||||||
|
<span class="badge bg-danger-soft text-danger px-3 py-2 rounded-pill fw-bold">Alfa</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-light text-muted px-3 py-2 rounded-pill border">Belum Mulai</span>
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
@if(isset($presensi_saya[$jadwal->id]))
|
||||||
|
@if($presensi_saya[$jadwal->id]->is_verified)
|
||||||
|
<span class="text-success small fw-bold"><i class="bi bi-check-circle-fill me-1"></i>Sah</span>
|
||||||
|
@else
|
||||||
|
<span class="text-warning small fw-bold"><i class="bi bi-hourglass-split me-1"></i>Menunggu</span>
|
||||||
|
@endif
|
||||||
|
@else
|
||||||
|
<span class="text-muted small">-</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if(isset($presensi_saya[$jadwal->id]) && $presensi_saya[$jadwal->id]->keterangan)
|
||||||
|
<span class="small text-muted" style="font-size: 0.75rem;">
|
||||||
|
<i class="bi bi-chat-left-text me-1"></i>{{ $presensi_saya[$jadwal->id]->keterangan }}
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
<span class="text-muted small">-</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" class="text-center py-5">
|
||||||
|
<div class="mb-3">
|
||||||
|
<i class="bi bi-folder-x text-muted" style="font-size: 3rem; opacity: 0.5;"></i>
|
||||||
|
</div>
|
||||||
|
<h6 class="fw-bold text-secondary mb-1">Tidak ada data di bulan ini</h6>
|
||||||
|
<p class="text-muted small">Silakan pilih bulan atau tahun lain pada filter di atas.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.main-table thead th { background-color: #f8faff; padding: 16px 12px; font-size: 0.75rem; color: #6c757d; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase; border-bottom: 2px solid #edf2f9; }
|
||||||
|
.main-table tbody td { padding: 16px 12px; border-bottom: 1px solid #f1f4f8; vertical-align: middle; }
|
||||||
|
.bg-primary-soft { background-color: #e0f2fe; color: #0ea5e9; }
|
||||||
|
.bg-success-soft { background-color: #d1e7dd; color: #0f5132; }
|
||||||
|
.bg-warning-soft { background-color: #fff3cd; color: #664d03; }
|
||||||
|
.bg-info-soft { background-color: #cff4fc; color: #055160; }
|
||||||
|
.bg-danger-soft { background-color: #f8d7da; color: #842029; }
|
||||||
|
.form-select:focus { border-color: #0d6efd; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); }
|
||||||
|
</style>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
@extends('layout.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid py-4">
|
||||||
|
<div class="page-header mb-4 text-start">
|
||||||
|
<a href="{{ route('presensi.anggota.index') }}" class="text-decoration-none text-muted small mb-2 d-inline-block">
|
||||||
|
<i class="bi bi-arrow-left me-1"></i> Kembali
|
||||||
|
</a>
|
||||||
|
<h3 class="fw-bold text-dark">Scan Barcode Kehadiran</h3>
|
||||||
|
<p class="text-muted small">Arahkan kamera Anda ke QR Code yang ditampilkan oleh Pelatih.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6 col-lg-5">
|
||||||
|
<div class="card border-0 shadow-sm overflow-hidden" style="border-radius: 25px;">
|
||||||
|
{{-- Area Kamera --}}
|
||||||
|
<div id="reader" style="width: 100%; border: none;"></div>
|
||||||
|
|
||||||
|
<div class="card-body p-4 text-center">
|
||||||
|
<div id="result-info">
|
||||||
|
<div class="spinner-grow text-primary spinner-grow-sm me-2" role="status"></div>
|
||||||
|
<span class="text-muted small">Mencari kamera...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4 p-3 bg-light rounded-3 text-start">
|
||||||
|
<h6 class="fw-bold text-dark small mb-1"><i class="bi bi-info-circle me-2 text-primary"></i>Informasi Jadwal:</h6>
|
||||||
|
<p class="mb-0 small text-muted">{{ $jadwal->judul_kegiatan }}</p>
|
||||||
|
<p class="mb-0 small text-muted"><i class="bi bi-geo-alt small"></i> {{ $jadwal->lokasi }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Form Tersembunyi untuk Submit Data --}}
|
||||||
|
<form id="form-scan" action="{{ route('presensi.storeMandiri') }}" method="POST" style="display: none;">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="jadwal_id" id="jadwal_id_input">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Script QR Scanner --}}
|
||||||
|
<script src="https://unpkg.com/html5-qrcode"></script>
|
||||||
|
<script>
|
||||||
|
function onScanSuccess(decodedText, decodedResult) {
|
||||||
|
// decodedText biasanya berisi URL, misal: http://tapakmp.test/presensi/scan-absen/12
|
||||||
|
// Kita hanya butuh ID Jadwal-nya.
|
||||||
|
|
||||||
|
// Logika sederhana: Kita bandingkan apakah URL yang discan mengandung ID jadwal yang benar
|
||||||
|
const expectedUrl = "{{ route('presensi.anggota.scan', $jadwal->id) }}";
|
||||||
|
|
||||||
|
if (decodedText === expectedUrl) {
|
||||||
|
// Berhenti scan agar tidak submit berkali-kali
|
||||||
|
html5QrcodeScanner.clear();
|
||||||
|
|
||||||
|
// Masukkan ID ke form dan submit
|
||||||
|
document.getElementById('jadwal_id_input').value = "{{ $jadwal->id }}";
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Berhasil Mendeteksi!',
|
||||||
|
text: 'Sedang memproses absensi Anda...',
|
||||||
|
icon: 'success',
|
||||||
|
showConfirmButton: false,
|
||||||
|
timer: 2000
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('form-scan').submit();
|
||||||
|
} else {
|
||||||
|
// Jika barcode yang discan salah/milik jadwal lain
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Barcode Tidak Valid',
|
||||||
|
text: 'Pastikan Anda men-scan barcode pelatih untuk latihan ini.',
|
||||||
|
icon: 'error',
|
||||||
|
confirmButtonColor: '#0d6efd'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onScanFailure(error) {
|
||||||
|
// Kegagalan scan (biasanya karena kamera tidak fokus atau barcode belum terlihat)
|
||||||
|
// Kita biarkan saja agar dia terus mencoba scan otomatis
|
||||||
|
}
|
||||||
|
|
||||||
|
let html5QrcodeScanner = new Html5QrcodeScanner(
|
||||||
|
"reader",
|
||||||
|
{
|
||||||
|
fps: 10,
|
||||||
|
qrbox: {width: 250, height: 250},
|
||||||
|
aspectRatio: 1.0
|
||||||
|
},
|
||||||
|
/* verbose= */ false
|
||||||
|
);
|
||||||
|
|
||||||
|
html5QrcodeScanner.render(onScanSuccess, onScanFailure);
|
||||||
|
|
||||||
|
// Update status UI
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
setTimeout(() => {
|
||||||
|
document.getElementById('result-info').innerHTML =
|
||||||
|
'<span class="badge bg-success-soft text-success rounded-pill px-3 py-2">' +
|
||||||
|
'<i class="bi bi-camera-video me-2"></i>Kamera Aktif</span>';
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Styling Scanner agar terlihat seperti aplikasi modern */
|
||||||
|
#reader {
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
#reader__dashboard_section_csr button {
|
||||||
|
background-color: #0d6efd !important;
|
||||||
|
color: white !important;
|
||||||
|
border: none !important;
|
||||||
|
padding: 8px 20px !important;
|
||||||
|
border-radius: 10px !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
margin: 10px 0 !important;
|
||||||
|
}
|
||||||
|
#reader__status_span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
video {
|
||||||
|
border-radius: 0 0 0 0 !important;
|
||||||
|
}
|
||||||
|
.bg-success-soft { background-color: #f0fdf4; color: #16a34a; }
|
||||||
|
</style>
|
||||||
|
@endsection
|
||||||
|
|
@ -12,8 +12,9 @@
|
||||||
<h3 class="fw-bold text-dark">Rekap Presensi Latihan</h3>
|
<h3 class="fw-bold text-dark">Rekap Presensi Latihan</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if(session('success'))
|
@if (session('success'))
|
||||||
<div class="alert alert-success alert-dismissible fade show border-0 shadow-sm mb-4" role="alert" style="border-radius: 15px;">
|
<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') }}
|
<strong>Berhasil!</strong> {{ session('success') }}
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -27,7 +28,8 @@
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<div class="text-start">
|
<div class="text-start">
|
||||||
<h5 class="card-title mb-0 fw-bold text-dark">Pilih Jadwal Latihan</h5>
|
<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>
|
<p class="text-muted small mb-0">Klik tombol cek kehadiran untuk memverifikasi absen anggota
|
||||||
|
dan mengelola data manual.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -48,9 +50,15 @@
|
||||||
@php
|
@php
|
||||||
// Set timezone ke Jakarta agar sinkron dengan waktu Indonesia
|
// Set timezone ke Jakarta agar sinkron dengan waktu Indonesia
|
||||||
$now = \Carbon\Carbon::now('Asia/Jakarta');
|
$now = \Carbon\Carbon::now('Asia/Jakarta');
|
||||||
$start = \Carbon\Carbon::parse($item->tanggal . ' ' . $item->jam_mulai, 'Asia/Jakarta');
|
$start = \Carbon\Carbon::parse(
|
||||||
|
$item->tanggal . ' ' . $item->jam_mulai,
|
||||||
|
'Asia/Jakarta',
|
||||||
|
);
|
||||||
$end = $item->jam_selesai
|
$end = $item->jam_selesai
|
||||||
? \Carbon\Carbon::parse($item->tanggal . ' ' . $item->jam_selesai, 'Asia/Jakarta')
|
? \Carbon\Carbon::parse(
|
||||||
|
$item->tanggal . ' ' . $item->jam_selesai,
|
||||||
|
'Asia/Jakarta',
|
||||||
|
)
|
||||||
: $start->copy()->addHours(2);
|
: $start->copy()->addHours(2);
|
||||||
|
|
||||||
$dbStatus = trim(strtolower($item->status));
|
$dbStatus = trim(strtolower($item->status));
|
||||||
|
|
@ -59,7 +67,10 @@
|
||||||
if ($dbStatus == 'selesai') {
|
if ($dbStatus == 'selesai') {
|
||||||
$status_label = 'Selesai';
|
$status_label = 'Selesai';
|
||||||
$status_color = 'success';
|
$status_color = 'success';
|
||||||
} elseif ($now->greaterThanOrEqualTo($start) && $now->lessThanOrEqualTo($end)) {
|
} elseif (
|
||||||
|
$now->greaterThanOrEqualTo($start) &&
|
||||||
|
$now->lessThanOrEqualTo($end)
|
||||||
|
) {
|
||||||
$status_label = 'Berlangsung';
|
$status_label = 'Berlangsung';
|
||||||
$status_color = 'primary';
|
$status_color = 'primary';
|
||||||
} elseif ($now->lt($start)) {
|
} elseif ($now->lt($start)) {
|
||||||
|
|
@ -75,39 +86,48 @@
|
||||||
<td>
|
<td>
|
||||||
<div class="fw-bold text-dark text-start ps-2">
|
<div class="fw-bold text-dark text-start ps-2">
|
||||||
{{ $item->judul_kegiatan }}
|
{{ $item->judul_kegiatan }}
|
||||||
@if($dbStatus == 'selesai')
|
@if ($dbStatus == 'selesai')
|
||||||
<i class="bi bi-check-circle-fill text-success ms-1"></i>
|
<i class="bi bi-check-circle-fill text-success ms-1"></i>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<small class="text-muted text-start ps-2 d-block">
|
<small class="text-muted text-start ps-2 d-block">
|
||||||
{{-- Pemanggilan dari Query Builder Manual --}}
|
{{-- Pemanggilan dari Query Builder Manual --}}
|
||||||
<i class="icon-user small"></i> {{ $item->nama_pelatih ?? 'Belum Ditentukan' }}
|
<i class="bi bi-person-fill small"></i>
|
||||||
|
{{ $item->nama_pelatih ?? 'Belum Ditentukan' }}
|
||||||
</small>
|
</small>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<span class="badge bg-{{ $status_color }} px-3 py-2" style="border-radius: 8px; font-size: 11px;">
|
<span class="badge bg-{{ $status_color }} px-3 py-2"
|
||||||
|
style="border-radius: 8px; font-size: 11px;">
|
||||||
{{ $status_label }}
|
{{ $status_label }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</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="bi bi-calendar-event me-1"></i>
|
||||||
|
{{ \Carbon\Carbon::parse($item->tanggal)->format('d M Y') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="small text-muted">
|
<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' }}
|
<i class="bi bi-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 text-danger"></i> {{ $item->lokasi }}
|
<i class="bi bi-geo-alt-fill me-1 text-danger"></i> {{ $item->lokasi }}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
@php
|
@php
|
||||||
$bg_type = 'bg-secondary-soft text-secondary';
|
$bg_type = 'bg-secondary-soft text-secondary';
|
||||||
if($item->jenis == 'Rutin') $bg_type = 'bg-success-soft text-success border-success';
|
if ($item->jenis == 'Rutin') {
|
||||||
elseif($item->jenis == 'Tambahan') $bg_type = 'bg-info-soft text-info border-info';
|
$bg_type = 'bg-success-soft text-success border-success';
|
||||||
elseif($item->jenis == 'Pengumuman') $bg_type = 'bg-danger-soft text-danger border-danger';
|
} 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
|
@endphp
|
||||||
<span class="badge rounded-pill {{ $bg_type }} px-3 border" style="font-size: 10px;">
|
<span class="badge rounded-pill {{ $bg_type }} px-3 border"
|
||||||
|
style="font-size: 10px;">
|
||||||
{{ $item->jenis }}
|
{{ $item->jenis }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -122,7 +142,8 @@ class="btn btn-sm btn-info fw-bold px-3 shadow-xs text-white"
|
||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="6" class="text-center py-5 text-muted small">Belum ada jadwal latihan tersedia.</td>
|
<td colspan="6" class="text-center py-5 text-muted small">Belum ada jadwal
|
||||||
|
latihan tersedia.</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -136,14 +157,56 @@ class="btn btn-sm btn-info fw-bold px-3 shadow-xs text-white"
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<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 thead th {
|
||||||
.main-table tbody td { padding: 15px 10px; border-bottom: 1px solid #f1f4f8; color: #495057; font-size: 0.85rem; }
|
background-color: #f8faff;
|
||||||
.bg-success-soft { background-color: #e6fffa; color: #38b2ac; }
|
padding: 15px 10px;
|
||||||
.bg-info-soft { background-color: #e0f2fe; color: #0ea5e9; }
|
font-size: 0.7rem;
|
||||||
.bg-danger-soft { background-color: #fff5f5; color: #e53e3e; }
|
color: #8c98a5;
|
||||||
.bg-secondary-soft { background-color: #f3f4f6; color: #6b7280; }
|
letter-spacing: 1px;
|
||||||
.shadow-xs { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); }
|
text-transform: uppercase;
|
||||||
.btn-info { background-color: #0ea5e9; border: none; transition: 0.3s; }
|
border-bottom: 2px solid #edf2f9;
|
||||||
.btn-info:hover { background-color: #0284c7; transform: translateY(-2px); }
|
}
|
||||||
|
|
||||||
|
.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>
|
</style>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="container-fluid py-4">
|
<div class="container-fluid py-4">
|
||||||
|
{{-- 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">
|
||||||
|
|
@ -13,40 +14,58 @@
|
||||||
<h3 class="fw-bold text-dark">Verifikasi Kehadiran Anggota</h3>
|
<h3 class="fw-bold text-dark">Verifikasi Kehadiran Anggota</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Menampilkan Pesan Sukses --}}
|
{{-- NOTIFIKASI --}}
|
||||||
@if(session('success'))
|
@if (session('success'))
|
||||||
<div class="alert alert-success alert-dismissible fade show border-0 shadow-sm mb-4" role="alert" style="border-radius: 15px;">
|
<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') }}
|
<i class="bi bi-check-circle-fill me-2"></i><strong>Berhasil!</strong> {{ session('success') }}
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{-- Menampilkan Pesan Error (Misal: Input manual ganda) --}}
|
@if (session('error'))
|
||||||
@if(session('error'))
|
|
||||||
<div class="alert alert-danger alert-dismissible fade show border-0 shadow-sm mb-4" role="alert" style="border-radius: 15px;">
|
<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') }}
|
<i class="bi bi-exclamation-triangle-fill me-2"></i><strong>Gagal!</strong> {{ session('error') }}
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@php
|
||||||
|
$now = \Carbon\Carbon::now('Asia/Jakarta');
|
||||||
|
$start = \Carbon\Carbon::parse($jadwal->tanggal . ' ' . $jadwal->jam_mulai, 'Asia/Jakarta');
|
||||||
|
$end = $jadwal->jam_selesai
|
||||||
|
? \Carbon\Carbon::parse($jadwal->tanggal . ' ' . $jadwal->jam_selesai, 'Asia/Jakarta')
|
||||||
|
: $start->copy()->addHours(3);
|
||||||
|
|
||||||
|
$is_active = $now->between($start, $end);
|
||||||
|
@endphp
|
||||||
|
|
||||||
{{-- KARTU INFORMASI JADWAL --}}
|
{{-- KARTU INFORMASI JADWAL --}}
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="col-12">
|
<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 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="card-body p-4 text-white">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-md-8">
|
<div class="col-md-7 text-start">
|
||||||
<h5 class="fw-bold mb-1">{{ $jadwal->judul_kegiatan }}</h5>
|
<span class="badge bg-white text-primary px-3 py-2 rounded-pill shadow-sm mb-3">
|
||||||
|
<i class="bi bi-shield-fill-check me-1"></i> Kolat: {{ $jadwal->kolat->nama_kolat ?? '-' }}
|
||||||
|
</span>
|
||||||
|
<h4 class="fw-bold mb-2">{{ $jadwal->judul_kegiatan }}</h4>
|
||||||
<p class="mb-0 small" style="opacity: 0.9;">
|
<p class="mb-0 small" style="opacity: 0.9;">
|
||||||
<i class="icon-map-pin me-1"></i> {{ $jadwal->lokasi }} |
|
<i class="bi bi-geo-alt-fill me-1"></i> {{ $jadwal->lokasi }} |
|
||||||
<i class="icon-calendar me-1"></i> {{ \Carbon\Carbon::parse($jadwal->tanggal)->format('d M Y') }} |
|
<i class="bi bi-calendar-event me-1"></i> {{ \Carbon\Carbon::parse($jadwal->tanggal)->translatedFormat('d F Y') }} |
|
||||||
<i class="icon-clock me-1"></i> {{ substr($jadwal->jam_mulai, 0, 5) }} - {{ $jadwal->jam_selesai ? substr($jadwal->jam_selesai, 0, 5) : 'Selesai' }}
|
<i class="bi bi-clock me-1"></i> {{ substr($jadwal->jam_mulai, 0, 5) }} - {{ $jadwal->jam_selesai ? substr($jadwal->jam_selesai, 0, 5) : 'Selesai' }} WIB
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 text-md-end mt-3 mt-md-0">
|
<div class="col-md-5 text-md-end mt-4 mt-md-0">
|
||||||
<span class="badge bg-white text-primary px-3 py-2 rounded-pill shadow-sm">
|
@if ($is_active && $jadwal->status != 'selesai')
|
||||||
Kolat: {{ $jadwal->kolat->nama_kolat ?? '-' }}
|
<button class="btn btn-light text-primary fw-bold px-4 py-3 shadow" style="border-radius: 15px;" data-bs-toggle="modal" data-bs-target="#modalQRCode">
|
||||||
</span>
|
<i class="bi bi-qr-code-scan me-2" style="font-size: 1.2rem;"></i> Tampilkan Barcode
|
||||||
|
</button>
|
||||||
|
@else
|
||||||
|
<button class="btn btn-light text-muted fw-bold px-4 py-3 shadow disabled" style="border-radius: 15px; opacity: 0.7;">
|
||||||
|
<i class="bi bi-lock-fill me-2"></i> Waktu Absen Berakhir
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -54,33 +73,31 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- TABEL PRESENSI --}}
|
{{-- TABEL DAFTAR ABSENSI MASUK --}}
|
||||||
<div class="row">
|
<div class="row mb-4">
|
||||||
<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;">
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<div class="text-start">
|
<div class="text-start">
|
||||||
<h5 class="card-title mb-0 fw-bold text-dark">Daftar Absensi Masuk</h5>
|
<h5 class="card-title mb-1 fw-bold text-dark">Daftar Absensi Masuk</h5>
|
||||||
<p class="text-muted small mb-0">Klik konfirmasi untuk mensahkan kehadiran anggota.</p>
|
<p class="text-muted small mb-0">Verifikasi kehadiran anggota yang sudah melakukan absensi.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="btn btn-primary px-4 py-2 shadow-sm fw-bold" style="border-radius: 12px;" data-bs-toggle="modal" data-bs-target="#modalTambahManual">
|
||||||
{{-- Tombol Buka Modal Tambah Manual --}}
|
<i class="bi bi-person-plus-fill me-1"></i> 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>
|
</button>
|
||||||
</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-start">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="60" class="text-center">No</th>
|
<th width="5%" class="text-center">No</th>
|
||||||
<th>Identitas Anggota</th>
|
<th width="30%">Identitas Anggota</th>
|
||||||
<th class="text-center">Waktu Absen</th>
|
<th width="15%" class="text-center">Waktu Absen</th>
|
||||||
<th class="text-center">Status Verifikasi</th>
|
<th width="15%" class="text-center">Status Kehadiran</th>
|
||||||
<th class="text-center" width="180">Aksi</th>
|
<th width="15%" class="text-center">Verifikasi</th>
|
||||||
|
<th width="20%" class="text-center">Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
@ -88,106 +105,259 @@
|
||||||
<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-2">{{ $item->anggota->nama_lengkap }}</div>
|
<div class="fw-bold text-dark" style="font-size: 0.95rem;">{{ $item->anggota->nama_lengkap }}</div>
|
||||||
<small class="text-muted text-start ps-2 d-block">ID: {{ $item->anggota->no_induk }}</small>
|
<small class="text-muted"><i class="bi bi-person-badge me-1"></i>{{ $item->anggota->no_induk }}</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-light text-dark border px-3 py-2" style="border-radius: 8px;">
|
||||||
<i class="icon-clock me-1 text-primary"></i> {{ \Carbon\Carbon::parse($item->waktu_presensi)->format('H:i') }} WIB
|
<i class="bi bi-clock me-1"></i>{{ \Carbon\Carbon::parse($item->waktu_presensi)->format('H:i') }} WIB
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
@if($item->is_verified)
|
@php
|
||||||
<span class="badge bg-success-soft text-success border-success px-3 border rounded-pill">
|
$statusColor = match($item->status) {
|
||||||
<i class="bi bi-check-circle-fill me-1"></i> Sah
|
'Hadir' => 'success',
|
||||||
|
'Izin' => 'info',
|
||||||
|
'Sakit' => 'warning',
|
||||||
|
'Alfa' => 'danger',
|
||||||
|
default => 'secondary'
|
||||||
|
};
|
||||||
|
@endphp
|
||||||
|
<span class="badge bg-{{ $statusColor }}-soft text-{{ $statusColor }} px-3 py-2 rounded-pill fw-bold">
|
||||||
|
{{ $item->status }}
|
||||||
</span>
|
</span>
|
||||||
<div class="small text-muted mt-1" style="font-size: 10px;">
|
|
||||||
Oleh: {{ $item->pelatihVerifikator->nama_lengkap ?? 'Pelatih' }}
|
@if($item->keterangan)
|
||||||
|
<div class="small text-muted mt-2" style="font-size: 0.75rem;">
|
||||||
|
<i class="bi bi-chat-left-text text-{{ $statusColor }} me-1"></i> {{ $item->keterangan }}
|
||||||
</div>
|
</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
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
@if(!$item->is_verified)
|
@if ($item->is_verified)
|
||||||
{{-- Tombol Konfirmasi Hadir --}}
|
<span class="text-success small fw-bold"><i class="bi bi-check-circle-fill me-1"></i>Sah</span>
|
||||||
<form action="{{ route('presensi.konfirmasi', $item->id) }}" method="POST" class="d-inline">
|
<div class="small text-muted mt-1" style="font-size: 0.7rem;">
|
||||||
|
Oleh: {{ $item->pelatihVerifikator->nama_lengkap ?? 'Sistem' }}
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<span class="text-warning small fw-bold"><i class="bi bi-hourglass-split me-1"></i>Menunggu</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
@if (!$item->is_verified)
|
||||||
|
<div class="d-flex justify-content-center gap-2">
|
||||||
|
<form action="{{ route('presensi.konfirmasi', $item->id) }}" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
<button type="submit" class="btn btn-sm btn-action-edit fw-bold px-3 shadow-xs" onclick="return confirm('Konfirmasi kehadiran anggota ini?')">
|
<input type="hidden" name="action" value="sah">
|
||||||
<i class="bi bi-check2-square me-1"></i> Konfirmasi
|
<button type="submit" class="btn btn-sm btn-success fw-bold px-3 shadow-sm" style="border-radius: 8px;">
|
||||||
|
<i class="bi bi-check-lg"></i> Sah
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
@else
|
<button type="button" class="btn btn-sm btn-danger fw-bold px-3 shadow-sm" style="border-radius: 8px;" data-bs-toggle="modal" data-bs-target="#modalTolak{{ $item->id }}">
|
||||||
<button class="btn btn-sm btn-light fw-bold px-3 text-muted border disabled" style="border-radius: 10px;">
|
<i class="bi bi-x-lg"></i> Tolak
|
||||||
Selesai
|
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Modal Khusus Penolakan --}}
|
||||||
|
<div class="modal fade text-start" id="modalTolak{{ $item->id }}" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content" style="border-radius: 20px; border: none;">
|
||||||
|
<div class="modal-header bg-danger text-white border-0 py-3 px-4">
|
||||||
|
<h5 class="modal-title fw-bold"><i class="bi bi-exclamation-octagon me-2"></i>Tolak Absensi</h5>
|
||||||
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<form action="{{ route('presensi.konfirmasi', $item->id) }}" method="POST">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="action" value="tolak">
|
||||||
|
<div class="modal-body p-4">
|
||||||
|
<p class="text-muted small mb-3">Anda akan menolak kehadiran <strong>{{ $item->anggota->nama_lengkap }}</strong>. Status akan diubah menjadi Alfa.</p>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label fw-bold small text-dark">Alasan Penolakan <span class="text-danger">*</span></label>
|
||||||
|
<textarea name="keterangan" class="form-control" rows="3" placeholder="Misal: Scan dari luar area latihan / Titip absen" required style="border-radius: 10px;"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer bg-light border-0 px-4 py-3">
|
||||||
|
<button type="button" class="btn btn-secondary px-4 fw-bold" data-bs-dismiss="modal" style="border-radius: 10px;">Batal</button>
|
||||||
|
<button type="submit" class="btn btn-danger px-4 fw-bold shadow-sm" style="border-radius: 10px;"><i class="bi bi-x-circle me-1"></i> Tolak Kehadiran</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-light text-muted border px-3 py-2" style="border-radius: 8px;">
|
||||||
|
<i class="bi bi-lock-fill me-1"></i> Selesai
|
||||||
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="5" class="text-center py-5 text-muted small">Belum ada anggota yang melakukan absensi masuk.</td>
|
<td colspan="6" class="text-center py-5">
|
||||||
|
<img src="https://cdn-icons-png.flaticon.com/512/7486/7486747.png" width="80" class="mb-3 opacity-50" alt="No Data">
|
||||||
|
<h6 class="text-muted fw-bold mb-1">Belum ada absensi masuk</h6>
|
||||||
|
<p class="text-muted small">Anggota yang men-scan barcode akan muncul di sini.</p>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- TABEL DAFTAR ANGGOTA BELUM ABSEN --}}
|
||||||
|
<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-1 fw-bold text-dark">
|
||||||
|
Belum Melakukan Presensi
|
||||||
|
@if(isset($anggota_belum_absen) && $anggota_belum_absen->count() > 0)
|
||||||
|
<span class="badge bg-danger ms-2 rounded-pill">{{ $anggota_belum_absen->count() }} Orang</span>
|
||||||
|
@endif
|
||||||
|
</h5>
|
||||||
|
<p class="text-muted small mb-0">Daftar anggota aktif di kolat ini yang belum tercatat kehadirannya.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover align-middle text-start main-table">
|
||||||
|
<thead style="background-color: #fff5f5; border-bottom: 2px solid #ffe3e3;">
|
||||||
|
<tr>
|
||||||
|
<th width="5%" class="text-center" style="color: #dc3545;">No</th>
|
||||||
|
<th width="45%" style="color: #dc3545;">Identitas Anggota</th>
|
||||||
|
<th width="30%" style="color: #dc3545;">No. HP (WhatsApp)</th>
|
||||||
|
<th width="20%" class="text-center" style="color: #dc3545;">Aksi Cepat</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@if(isset($anggota_belum_absen))
|
||||||
|
@forelse ($anggota_belum_absen as $no => $belum)
|
||||||
|
<tr>
|
||||||
|
<td class="text-muted small text-center">{{ $no + 1 }}</td>
|
||||||
|
<td>
|
||||||
|
<div class="fw-bold text-dark">{{ $belum->nama_lengkap }}</div>
|
||||||
|
<small class="text-muted"><i class="bi bi-person-badge me-1"></i>{{ $belum->no_induk }}</small>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if($belum->no_hp)
|
||||||
|
<a href="https://wa.me/{{ preg_replace('/^0/', '62', $belum->no_hp) }}" target="_blank" class="text-decoration-none text-success small fw-bold btn btn-sm btn-light border" style="border-radius: 8px;">
|
||||||
|
<i class="bi bi-whatsapp me-1"></i> Hubungi
|
||||||
|
</a>
|
||||||
|
@else
|
||||||
|
<span class="text-muted small">-</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<button class="btn btn-sm btn-outline-primary fw-bold px-3 shadow-sm" style="border-radius: 8px;" data-bs-toggle="modal" data-bs-target="#modalTambahManual" onclick="document.getElementById('pilih_anggota').value = '{{ $belum->id }}'">
|
||||||
|
<i class="bi bi-pencil-square me-1"></i> Input
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="4" class="text-center py-5">
|
||||||
|
<div class="text-success fw-bold"><i class="bi bi-check-circle-fill me-2 fs-4"></i><br>Mantap! Semua anggota aktif sudah tercatat kehadirannya.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
@endif
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- MODAL TAMBAH MANUAL (KASUS LUPA HP) --}}
|
{{-- MODAL QR CODE --}}
|
||||||
|
<div class="modal fade" id="modalQRCode" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content text-center p-4" style="border-radius: 20px; border: none;">
|
||||||
|
<div class="modal-header border-0 pb-0 justify-content-center position-relative">
|
||||||
|
<h5 class="modal-title fw-bold text-dark">Scan Barcode Kehadiran</h5>
|
||||||
|
<button type="button" class="btn-close position-absolute end-0 me-3" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p class="small text-muted mb-4">Barcode ini hanya berlaku selama jadwal latihan berlangsung.</p>
|
||||||
|
<div class="bg-white p-3 d-inline-block rounded-4 shadow-sm border">
|
||||||
|
{{-- MENGGUNAKAN ROUTE HELPER AGAR SINKRON DENGAN SCANNER --}}
|
||||||
|
{!! QrCode::size(250)->gradient(2, 132, 199, 0, 79, 177, 'diagonal')->margin(1)->generate(route('presensi.anggota.scan', $jadwal->id)) !!}
|
||||||
|
</div>
|
||||||
|
<div class="mt-4">
|
||||||
|
<h6 class="fw-bold mb-0">{{ $jadwal->judul_kegiatan }}</h6>
|
||||||
|
<span class="badge bg-danger mt-2 px-3 py-2 rounded-pill">Batas Waktu: {{ $jadwal->jam_selesai ?: 'Selesai' }} WIB</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- MODAL TAMBAH MANUAL --}}
|
||||||
<div class="modal fade" id="modalTambahManual" tabindex="-1" aria-hidden="true">
|
<div class="modal fade" id="modalTambahManual" tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
<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"><i class="bi bi-person-plus-fill me-2"></i>Input Manual Kehadiran</h5>
|
||||||
<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>
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<form action="{{ route('presensi.storeManual') }}" method="POST">
|
<form action="{{ route('presensi.storeManual') }}" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
{{-- Hidden input untuk ID Jadwal --}}
|
|
||||||
<input type="hidden" name="jadwal_id" value="{{ $jadwal->id }}">
|
<input type="hidden" name="jadwal_id" value="{{ $jadwal->id }}">
|
||||||
|
<div class="modal-body p-4 text-start">
|
||||||
|
|
||||||
<div class="modal-body p-4">
|
<div class="mb-3">
|
||||||
<div class="alert alert-info border-0 shadow-sm small" style="border-radius: 10px;">
|
<label class="form-label fw-bold text-dark small">Nama Anggota <span class="text-danger">*</span></label>
|
||||||
<i class="bi bi-info-circle-fill me-2"></i> Gunakan form ini untuk anggota yang lupa membawa perangkat atau tidak bisa absen mandiri.
|
<select name="anggota_id" id="pilih_anggota" class="form-select border-2 shadow-none" style="border-radius: 10px;" required>
|
||||||
</div>
|
<option value="" disabled selected>-- Pilih Anggota (Kolat {{ $jadwal->kolat->nama_kolat }}) --</option>
|
||||||
|
@if(isset($anggota_belum_absen))
|
||||||
<div class="mb-3 text-start">
|
@foreach ($anggota_belum_absen as $anggota)
|
||||||
<label class="form-label fw-bold text-dark small">Pilih Nama Anggota</label>
|
<option value="{{ $anggota->id }}">{{ $anggota->nama_lengkap }} ({{ $anggota->no_induk }})</option>
|
||||||
<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
|
@endforeach
|
||||||
|
@endif
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label fw-bold text-dark small">Status Kehadiran <span class="text-danger">*</span></label>
|
||||||
|
<select name="status" class="form-select border-2 shadow-none" style="border-radius: 10px;" required>
|
||||||
|
<option value="Hadir">Hadir</option>
|
||||||
|
<option value="Izin">Izin</option>
|
||||||
|
<option value="Sakit">Sakit</option>
|
||||||
|
<option value="Alfa">Alfa</option>
|
||||||
|
</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>
|
<div class="mb-2">
|
||||||
<button type="submit" class="btn btn-success px-4 shadow-sm" style="border-radius: 10px;">
|
<label class="form-label fw-bold text-dark small">Keterangan <span class="text-muted fw-normal">(Opsional)</span></label>
|
||||||
<i class="bi bi-check-lg me-1"></i> Simpan & Sahkan
|
<textarea name="keterangan" class="form-control border-2 shadow-none" rows="2" placeholder="Tuliskan alasan izin/sakit atau catatan lain..." style="border-radius: 10px;"></textarea>
|
||||||
</button>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer bg-light border-0 px-4 py-3">
|
||||||
|
<button type="button" class="btn btn-secondary px-4 fw-bold" data-bs-dismiss="modal" style="border-radius: 10px;">Batal</button>
|
||||||
|
<button type="submit" class="btn btn-primary px-4 fw-bold shadow-sm" style="border-radius: 10px;"><i class="bi bi-save me-1"></i> Simpan Data</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- KUMPULAN CSS --}}
|
||||||
<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: 16px 12px; font-size: 0.75rem; color: #6c757d; font-weight: 700; letter-spacing: 0.5px; 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: 16px 12px; border-bottom: 1px solid #f1f4f8; vertical-align: middle; }
|
||||||
.bg-success-soft { background-color: #e6fffa; color: #38b2ac; }
|
.bg-success-soft { background-color: #d1e7dd; color: #0f5132; }
|
||||||
.btn-action-edit { background-color: #f0f7ff; color: #0d6efd; border: 1px solid #d0e4ff; border-radius: 10px; transition: 0.3s; }
|
.bg-info-soft { background-color: #cff4fc; color: #055160; }
|
||||||
.btn-action-edit:hover { background-color: #0d6efd !important; color: white !important; transform: translateY(-2px); }
|
.bg-warning-soft { background-color: #fff3cd; color: #664d03; }
|
||||||
|
.bg-danger-soft { background-color: #f8d7da; color: #842029; }
|
||||||
.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); }
|
||||||
|
.form-select:focus, .form-control:focus { border-color: #0d6efd; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); }
|
||||||
</style>
|
</style>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
use App\Http\Controllers\PresensiController;
|
use App\Http\Controllers\PresensiController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Web Routes
|
| Web Routes
|
||||||
|
|
@ -51,17 +50,15 @@
|
||||||
|
|
||||||
// Route dashboard atau menu lainnya masukkan di sini
|
// Route dashboard atau menu lainnya masukkan di sini
|
||||||
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
|
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
|
||||||
});
|
|
||||||
|
|
||||||
//anggota
|
// anggota
|
||||||
Route::get('/anggota', [AnggotaController::class, 'anggota'])->name('anggota.anggota');
|
Route::get('/anggota', [AnggotaController::class, 'anggota'])->name('anggota.anggota');
|
||||||
Route::get('/anggota/tambah', [AnggotaController::class, 'create'])->name('anggota.create');
|
Route::get('/anggota/tambah', [AnggotaController::class, 'create'])->name('anggota.create');
|
||||||
Route::post('/anggota/simpan', [AnggotaController::class, 'store'])->name('anggota.store');
|
Route::post('/anggota/simpan', [AnggotaController::class, 'store'])->name('anggota.store');
|
||||||
Route::get('/anggota/{id}/edit', [AnggotaController::class, 'edit'])->name('anggota.edit');
|
Route::get('/anggota/{id}/edit', [AnggotaController::class, 'edit'])->name('anggota.edit');
|
||||||
Route::put('/anggota/{id}', [AnggotaController::class, 'update'])->name('anggota.update');
|
Route::put('/anggota/{id}', [AnggotaController::class, 'update'])->name('anggota.update');
|
||||||
|
|
||||||
|
// kolat
|
||||||
//kolat
|
|
||||||
Route::get('/kolat', [KolatController::class, 'kolat'])->name('kolat.index');
|
Route::get('/kolat', [KolatController::class, 'kolat'])->name('kolat.index');
|
||||||
Route::get('/kolat/tambah', [KolatController::class, 'create'])->name('kolat.create');
|
Route::get('/kolat/tambah', [KolatController::class, 'create'])->name('kolat.create');
|
||||||
Route::post('/kolat/simpan', [KolatController::class, 'store'])->name('kolat.store');
|
Route::post('/kolat/simpan', [KolatController::class, 'store'])->name('kolat.store');
|
||||||
|
|
@ -69,8 +66,8 @@
|
||||||
Route::put('/kolat/{id}', [KolatController::class, 'update'])->name('kolat.update');
|
Route::put('/kolat/{id}', [KolatController::class, 'update'])->name('kolat.update');
|
||||||
Route::delete('/kolat/{id}', [KolatController::class, 'destroy'])->name('kolat.destroy');
|
Route::delete('/kolat/{id}', [KolatController::class, 'destroy'])->name('kolat.destroy');
|
||||||
|
|
||||||
//pelatih
|
// pelatih
|
||||||
//prefix diguakan untuk mengelompokkan route yang berhubungan dengan pelatih, sehingga URL nya menjadi /manajemen-pelatih/...
|
// prefix diguakan untuk mengelompokkan route yang berhubungan dengan pelatih, sehingga URL nya menjadi /manajemen-pelatih/...
|
||||||
Route::prefix('manajemen-pelatih')->group(function () {
|
Route::prefix('manajemen-pelatih')->group(function () {
|
||||||
Route::get('/', [PelatihController::class, 'index'])->name('pelatih.index');
|
Route::get('/', [PelatihController::class, 'index'])->name('pelatih.index');
|
||||||
Route::get('/upgrade', [PelatihController::class, 'create'])->name('pelatih.upgrade');
|
Route::get('/upgrade', [PelatihController::class, 'create'])->name('pelatih.upgrade');
|
||||||
|
|
@ -79,8 +76,8 @@
|
||||||
Route::put('/{id}', [PelatihController::class, 'update'])->name('pelatih.update');
|
Route::put('/{id}', [PelatihController::class, 'update'])->name('pelatih.update');
|
||||||
});
|
});
|
||||||
|
|
||||||
//jadwal
|
// jadwal
|
||||||
//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::post('/jadwal/{id}/konfirmasi', [JadwalController::class, 'konfirmasiSelesai'])->name('jadwal.konfirmasi');
|
||||||
|
|
@ -92,14 +89,35 @@
|
||||||
Route::delete('/{id}/delete', [JadwalController::class, 'destroy'])->name('jadwal.destroy');
|
Route::delete('/{id}/delete', [JadwalController::class, 'destroy'])->name('jadwal.destroy');
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- ROUTE PRESENSI (ABSENSI) ---
|
// Rute untuk Presensi
|
||||||
Route::prefix('presensi')->name('presensi.')->group(function () {
|
Route::prefix('presensi')->name('presensi.')->group(function () {
|
||||||
|
|
||||||
|
// --- AKTOR: PENGURUS / PELATIH ---
|
||||||
|
// Halaman utama rekap jadwal (untuk pilih jadwal mana yang mau dicek)
|
||||||
Route::get('/', [PresensiController::class, 'index'])->name('index');
|
Route::get('/', [PresensiController::class, 'index'])->name('index');
|
||||||
// Halaman daftar kehadiran (View Admin/Pelatih)
|
|
||||||
|
// Halaman daftar kehadiran anggota pada jadwal tertentu (tampil QR Code & List)
|
||||||
Route::get('/kehadiran/{jadwal_id}', [PresensiController::class, 'kehadiran'])->name('kehadiran');
|
Route::get('/kehadiran/{jadwal_id}', [PresensiController::class, 'kehadiran'])->name('kehadiran');
|
||||||
// konfirmasi pelatih
|
|
||||||
|
// Proses konfirmasi/verifikasi pelatih klik tombol "Sah"
|
||||||
Route::post('/konfirmasi/{presensi_id}', [PresensiController::class, 'konfirmasi'])->name('konfirmasi');
|
Route::post('/konfirmasi/{presensi_id}', [PresensiController::class, 'konfirmasi'])->name('konfirmasi');
|
||||||
|
|
||||||
// Proses tambah presensi manual (Kasus Lupa HP)
|
// Proses tambah presensi manual (Kasus Lupa HP)
|
||||||
Route::post('/tambah-manual', [PresensiController::class, 'storeManual'])->name('storeManual');
|
Route::post('/tambah-manual', [PresensiController::class, 'storeManual'])->name('storeManual');
|
||||||
});
|
|
||||||
|
|
||||||
|
// --- AKTOR: ANGGOTA ---
|
||||||
|
// Halaman daftar jadwal hari ini di sisi anggota (Tampil tombol "Scan Absen")
|
||||||
|
Route::get('/anggota', [PresensiController::class, 'indexAnggota'])->name('anggota.index');
|
||||||
|
|
||||||
|
Route::get('/riwayat', [PresensiController::class, 'riwayatAnggota'])->name('anggota.riwayat');
|
||||||
|
|
||||||
|
// Halaman Kamera Scanner (Tempat anggota men-scan QR Code pelatih)
|
||||||
|
Route::get('/scan/{jadwal_id}', [PresensiController::class, 'scan'])->name('anggota.scan');
|
||||||
|
|
||||||
|
// Proses penyimpanan absen mandiri setelah sukses scan
|
||||||
|
Route::post('/store-mandiri', [PresensiController::class, 'storeMandiri'])->name('storeMandiri');
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue