- ProgramController: full CRUD, publish, close, delete (guarded if attendance exists) - StoreProgramRequest + UpdateProgramRequest with Malay attribute names - AuditLogService: logs admin actions, redacts sensitive fields (no_kp, token, password) - Program index: search, status filter, pagination (Bootstrap 5) - Program create/edit: shared _form partial with all fields (dates, sessions, walk-in toggle) - Program show: tab layout (participants, qr, template, questionnaire, statistics) - Bootstrap 5 pagination via Paginator::useBootstrapFive() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
175 lines
12 KiB
PHP
175 lines
12 KiB
PHP
{{--
|
|
Shared form partial.
|
|
Variables expected:
|
|
$program — Program model (or null for create)
|
|
$action — form action URL
|
|
$method — PUT for edit, omit for create (POST)
|
|
--}}
|
|
<form method="POST" action="{{ $action }}">
|
|
@csrf
|
|
@isset($method) @method($method) @endisset
|
|
|
|
<div class="row g-4">
|
|
|
|
{{-- ── Maklumat Asas ── --}}
|
|
<div class="col-12">
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-header bg-white border-bottom py-3">
|
|
<span class="fw-semibold"><i class="bi bi-info-circle me-2 text-primary"></i>Maklumat Asas</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-12">
|
|
<label class="form-label fw-medium">Nama Program <span class="text-danger">*</span></label>
|
|
<input type="text" name="title" class="form-control @error('title') is-invalid @enderror"
|
|
value="{{ old('title', $program->title ?? '') }}"
|
|
placeholder="Contoh: Kursus Pengurusan Projek 2025">
|
|
@error('title')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label fw-medium">Penganjur <span class="text-danger">*</span></label>
|
|
<input type="text" name="organizer" class="form-control @error('organizer') is-invalid @enderror"
|
|
value="{{ old('organizer', $program->organizer ?? 'MBIP') }}"
|
|
placeholder="Contoh: Jabatan Sumber Manusia">
|
|
@error('organizer')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label fw-medium">Lokasi <span class="text-danger">*</span></label>
|
|
<input type="text" name="location" class="form-control @error('location') is-invalid @enderror"
|
|
value="{{ old('location', $program->location ?? '') }}"
|
|
placeholder="Contoh: Dewan Bandaraya Ipoh">
|
|
@error('location')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
|
|
<div class="col-12">
|
|
<label class="form-label fw-medium">Deskripsi</label>
|
|
<textarea name="description" rows="3"
|
|
class="form-control @error('description') is-invalid @enderror"
|
|
placeholder="Huraian ringkas tentang program...">{{ old('description', $program->description ?? '') }}</textarea>
|
|
@error('description')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- ── Tarikh & Masa ── --}}
|
|
<div class="col-12">
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-header bg-white border-bottom py-3">
|
|
<span class="fw-semibold"><i class="bi bi-calendar-range me-2 text-primary"></i>Tarikh & Masa</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label fw-medium">Tarikh Mula <span class="text-danger">*</span></label>
|
|
<input type="date" name="start_date" class="form-control @error('start_date') is-invalid @enderror"
|
|
value="{{ old('start_date', isset($program->start_date) ? $program->start_date->format('Y-m-d') : '') }}">
|
|
@error('start_date')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label fw-medium">Tarikh Tamat <span class="text-danger">*</span></label>
|
|
<input type="date" name="end_date" class="form-control @error('end_date') is-invalid @enderror"
|
|
value="{{ old('end_date', isset($program->end_date) ? $program->end_date->format('Y-m-d') : '') }}">
|
|
@error('end_date')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
|
|
<div class="col-12"><hr class="my-1"><p class="text-muted small mb-2">Tempoh Check-In (kosongkan jika tidak ditetapkan)</p></div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label fw-medium">Mula Check-In</label>
|
|
<input type="datetime-local" name="checkin_start_at"
|
|
class="form-control @error('checkin_start_at') is-invalid @enderror"
|
|
value="{{ old('checkin_start_at', isset($program->checkin_start_at) ? $program->checkin_start_at->format('Y-m-d\TH:i') : '') }}">
|
|
@error('checkin_start_at')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label fw-medium">Tamat Check-In</label>
|
|
<input type="datetime-local" name="checkin_end_at"
|
|
class="form-control @error('checkin_end_at') is-invalid @enderror"
|
|
value="{{ old('checkin_end_at', isset($program->checkin_end_at) ? $program->checkin_end_at->format('Y-m-d\TH:i') : '') }}">
|
|
@error('checkin_end_at')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
|
|
<div class="col-12"><hr class="my-1"><p class="text-muted small mb-2">Tempoh Download eCert (kosongkan jika tidak ditetapkan)</p></div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label fw-medium">Mula Download Sijil</label>
|
|
<input type="datetime-local" name="ecert_download_start_at"
|
|
class="form-control @error('ecert_download_start_at') is-invalid @enderror"
|
|
value="{{ old('ecert_download_start_at', isset($program->ecert_download_start_at) ? $program->ecert_download_start_at->format('Y-m-d\TH:i') : '') }}">
|
|
@error('ecert_download_start_at')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label fw-medium">Tamat Download Sijil</label>
|
|
<input type="datetime-local" name="ecert_download_end_at"
|
|
class="form-control @error('ecert_download_end_at') is-invalid @enderror"
|
|
value="{{ old('ecert_download_end_at', isset($program->ecert_download_end_at) ? $program->ecert_download_end_at->format('Y-m-d\TH:i') : '') }}">
|
|
@error('ecert_download_end_at')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- ── Tetapan Kehadiran ── --}}
|
|
<div class="col-12">
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-header bg-white border-bottom py-3">
|
|
<span class="fw-semibold"><i class="bi bi-person-check me-2 text-primary"></i>Tetapan Kehadiran</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-4">
|
|
<div class="form-check form-switch mt-2">
|
|
<input type="hidden" name="allow_walk_in" value="0">
|
|
<input class="form-check-input" type="checkbox" id="allow_walk_in" name="allow_walk_in" value="1"
|
|
{{ old('allow_walk_in', $program->allow_walk_in ?? true) ? 'checked' : '' }}>
|
|
<label class="form-check-label fw-medium" for="allow_walk_in">
|
|
Benarkan Daftar Walk-in
|
|
</label>
|
|
</div>
|
|
<div class="text-muted small mt-1">Orang luar boleh daftar sendiri semasa program.</div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label class="form-label fw-medium">Sesi Default (Kakitangan)</label>
|
|
<select name="default_staff_session" class="form-select @error('default_staff_session') is-invalid @enderror">
|
|
<option value="">— Pilih Sesi —</option>
|
|
<option value="pagi" {{ old('default_staff_session', $program->default_staff_session ?? '') === 'pagi' ? 'selected' : '' }}>Pagi</option>
|
|
<option value="petang" {{ old('default_staff_session', $program->default_staff_session ?? '') === 'petang' ? 'selected' : '' }}>Petang</option>
|
|
<option value="full_day" {{ old('default_staff_session', $program->default_staff_session ?? '') === 'full_day' ? 'selected' : '' }}>Sehari Penuh</option>
|
|
</select>
|
|
@error('default_staff_session')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label class="form-label fw-medium">Sesi Default (Peserta Luar)</label>
|
|
<select name="default_external_session" class="form-select @error('default_external_session') is-invalid @enderror">
|
|
<option value="">— Pilih Sesi —</option>
|
|
<option value="pagi" {{ old('default_external_session', $program->default_external_session ?? '') === 'pagi' ? 'selected' : '' }}>Pagi</option>
|
|
<option value="petang" {{ old('default_external_session', $program->default_external_session ?? '') === 'petang' ? 'selected' : '' }}>Petang</option>
|
|
<option value="full_day" {{ old('default_external_session', $program->default_external_session ?? '') === 'full_day' ? 'selected' : '' }}>Sehari Penuh</option>
|
|
</select>
|
|
@error('default_external_session')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- ── Butang Submit ── --}}
|
|
<div class="col-12 d-flex justify-content-end gap-2">
|
|
<a href="{{ route('admin.programs.index') }}" class="btn btn-outline-secondary">
|
|
<i class="bi bi-x-lg me-1"></i> Batal
|
|
</a>
|
|
<button type="submit" class="btn btn-primary px-4">
|
|
<i class="bi bi-check-lg me-1"></i>
|
|
{{ isset($program) ? 'Simpan Perubahan' : 'Tambah Program' }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|