235 lines
12 KiB
PHP
235 lines
12 KiB
PHP
@extends('layouts.admin')
|
||
|
||
@section('title', 'Peserta — ' . $program->title)
|
||
@section('header', 'Senarai Peserta')
|
||
|
||
@section('breadcrumb')
|
||
<li class="breadcrumb-item"><a href="{{ route('admin.programs.index') }}">Program</a></li>
|
||
<li class="breadcrumb-item"><a href="{{ route('admin.programs.show', $program) }}">{{ Str::limit($program->title, 25) }}</a></li>
|
||
<li class="breadcrumb-item active">Peserta</li>
|
||
@endsection
|
||
|
||
@section('header-actions')
|
||
<div class="d-flex gap-2">
|
||
<a href="{{ route('admin.programs.participants.export', $program) }}" class="btn btn-sm btn-outline-success">
|
||
<i class="bi bi-download me-1"></i> Export CSV
|
||
</a>
|
||
<a href="{{ route('admin.programs.participants.import.form', $program) }}" class="btn btn-sm btn-outline-secondary">
|
||
<i class="bi bi-upload me-1"></i> Import CSV
|
||
</a>
|
||
<a href="{{ route('admin.programs.participants.create', $program) }}" class="btn btn-sm btn-primary">
|
||
<i class="bi bi-person-plus me-1"></i> Tambah
|
||
</a>
|
||
</div>
|
||
@endsection
|
||
|
||
@section('content')
|
||
|
||
{{-- Summary Cards --}}
|
||
<div class="row g-3 mb-4">
|
||
@foreach([
|
||
['label' => 'Jumlah Peserta', 'value' => $counts['total'], 'icon' => 'bi-people', 'color' => 'primary'],
|
||
['label' => 'Pra-Daftar', 'value' => $counts['pre_registered'], 'icon' => 'bi-person-check', 'color' => 'info'],
|
||
['label' => 'Walk-In', 'value' => $counts['walk_in'], 'icon' => 'bi-person-walking', 'color' => 'warning'],
|
||
['label' => 'Hadir', 'value' => $counts['checked_in'], 'icon' => 'bi-patch-check', 'color' => 'success'],
|
||
] as $card)
|
||
<div class="col-6 col-md-3">
|
||
<div class="card border-0 shadow-sm text-center p-3">
|
||
<i class="bi {{ $card['icon'] }} text-{{ $card['color'] }} fs-4 mb-1"></i>
|
||
<div class="fs-4 fw-bold">{{ $card['value'] }}</div>
|
||
<div class="text-muted small">{{ $card['label'] }}</div>
|
||
</div>
|
||
</div>
|
||
@endforeach
|
||
</div>
|
||
|
||
{{-- Filter --}}
|
||
<div class="card border-0 shadow-sm mb-3">
|
||
<div class="card-body py-3">
|
||
<form method="GET" class="row g-2 align-items-end">
|
||
<div class="col-sm-5">
|
||
<div class="input-group input-group-sm">
|
||
<span class="input-group-text"><i class="bi bi-search"></i></span>
|
||
<input type="text" name="search" class="form-control"
|
||
placeholder="Nama, agensi..." value="{{ request('search') }}">
|
||
</div>
|
||
</div>
|
||
<div class="col-sm-3">
|
||
<select name="source" class="form-select form-select-sm">
|
||
<option value="">Semua Sumber</option>
|
||
<option value="pre_registered" {{ request('source') === 'pre_registered' ? 'selected' : '' }}>Pra-Daftar</option>
|
||
<option value="import" {{ request('source') === 'import' ? 'selected' : '' }}>Import</option>
|
||
<option value="walk_in" {{ request('source') === 'walk_in' ? 'selected' : '' }}>Walk-In</option>
|
||
<option value="admin_manual" {{ request('source') === 'admin_manual' ? 'selected' : '' }}>Manual Admin</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-sm-2">
|
||
<select name="status" class="form-select form-select-sm">
|
||
<option value="">Semua Status</option>
|
||
<option value="registered" {{ request('status') === 'registered' ? 'selected' : '' }}>Berdaftar</option>
|
||
<option value="checked_in" {{ request('status') === 'checked_in' ? 'selected' : '' }}>Hadir</option>
|
||
<option value="cancelled" {{ request('status') === 'cancelled' ? 'selected' : '' }}>Dibatalkan</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button type="submit" class="btn btn-primary btn-sm">Tapis</button>
|
||
@if(request()->hasAny(['search', 'source', 'status']))
|
||
<a href="{{ route('admin.programs.participants.index', $program) }}" class="btn btn-outline-secondary btn-sm ms-1">Reset</a>
|
||
@endif
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
{{-- Table --}}
|
||
<div class="card border-0 shadow-sm">
|
||
<div class="card-body p-0">
|
||
@if($programParticipants->isEmpty())
|
||
<div class="text-center py-5 text-muted">
|
||
<i class="bi bi-people fs-1 opacity-25 d-block mb-2"></i>
|
||
Belum ada peserta.
|
||
</div>
|
||
@else
|
||
<div class="table-responsive">
|
||
<table class="table table-hover align-middle mb-0">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th>#</th>
|
||
<th>Nama</th>
|
||
<th>Agensi</th>
|
||
<th>Sesi</th>
|
||
<th>Sumber</th>
|
||
<th>Status</th>
|
||
<th>E-Sijil</th>
|
||
<th class="text-end">Tindakan</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach($programParticipants as $i => $pp)
|
||
@php
|
||
$p = $pp->participant;
|
||
$cert = $certificates[$pp->participant_id] ?? null;
|
||
@endphp
|
||
<tr>
|
||
<td class="text-muted small">{{ $programParticipants->firstItem() + $i }}</td>
|
||
<td>
|
||
<div class="fw-medium">{{ $p->name }}</div>
|
||
<small class="text-muted">{{ $p->email ?: '—' }}</small>
|
||
</td>
|
||
<td><small>{{ $p->agency ?: '—' }}</small></td>
|
||
<td>
|
||
@if($pp->pre_registered_session)
|
||
<span class="badge bg-light text-dark border">
|
||
{{ Str::ucfirst($pp->pre_registered_session) }}
|
||
</span>
|
||
@else
|
||
<span class="text-muted">—</span>
|
||
@endif
|
||
</td>
|
||
<td>
|
||
@php
|
||
$sourceMap = [
|
||
'pre_registered' => ['secondary', 'Pra-Daftar'],
|
||
'import' => ['info', 'Import'],
|
||
'walk_in' => ['warning', 'Walk-In'],
|
||
'admin_manual' => ['dark', 'Manual'],
|
||
];
|
||
[$sc, $sl] = $sourceMap[$pp->registration_source] ?? ['light', $pp->registration_source];
|
||
@endphp
|
||
<span class="badge bg-{{ $sc }}">{{ $sl }}</span>
|
||
</td>
|
||
<td>
|
||
@if($pp->status === 'checked_in')
|
||
<span class="badge bg-success"><i class="bi bi-check-lg me-1"></i>Hadir</span>
|
||
@elseif($pp->status === 'cancelled')
|
||
<span class="badge bg-danger">Dibatalkan</span>
|
||
@else
|
||
<span class="badge bg-light text-dark border">Berdaftar</span>
|
||
@endif
|
||
</td>
|
||
<td style="min-width:130px;">
|
||
@if(! $cert)
|
||
<span class="text-muted small">—</span>
|
||
@else
|
||
{{-- Sijil --}}
|
||
@if(in_array($cert->status, ['generated','emailed','downloaded']))
|
||
<span class="badge bg-success-subtle text-success border border-success-subtle">
|
||
<i class="bi bi-award-fill me-1"></i>Jana ✓
|
||
</span>
|
||
@elseif($cert->status === 'pending')
|
||
<span class="badge bg-warning-subtle text-warning border border-warning-subtle">
|
||
<i class="bi bi-hourglass-split me-1"></i>Menjana...
|
||
</span>
|
||
@elseif($cert->status === 'failed')
|
||
<span class="badge bg-danger-subtle text-danger border border-danger-subtle">
|
||
<i class="bi bi-x-circle me-1"></i>Gagal Jana
|
||
</span>
|
||
@endif
|
||
|
||
{{-- Emel --}}
|
||
@if($pp->status_sent_emel === 'sent')
|
||
<div class="text-success mt-1" style="font-size:.7rem;">
|
||
<i class="bi bi-envelope-check me-1"></i>Emel Dihantar
|
||
</div>
|
||
@elseif($pp->status_sent_emel === 'failed')
|
||
<div class="text-danger mt-1" style="font-size:.7rem;">
|
||
<i class="bi bi-envelope-x me-1"></i>Emel Gagal
|
||
</div>
|
||
@elseif($pp->status_sent_emel === 'pending')
|
||
<div class="text-warning mt-1" style="font-size:.7rem;">
|
||
<i class="bi bi-hourglass-split me-1"></i>Dalam Antrian
|
||
</div>
|
||
@elseif($cert && $cert->isGenerated() && ! $cert->emailed_at)
|
||
<div class="text-muted mt-1" style="font-size:.7rem;">
|
||
<i class="bi bi-clock me-1"></i>Belum Dihantar
|
||
</div>
|
||
@endif
|
||
|
||
{{-- Muat turun --}}
|
||
@if($cert->download_count > 0)
|
||
<div class="text-primary mt-1" style="font-size:.7rem;">
|
||
<i class="bi bi-download me-1"></i>{{ $cert->download_count }}× Muat Turun
|
||
</div>
|
||
@endif
|
||
@endif
|
||
</td>
|
||
<td class="text-end">
|
||
<div class="d-flex justify-content-end gap-1">
|
||
@if($cert && $cert->isGenerated())
|
||
<a href="{{ route('admin.programs.certificates.download', [$program, $cert]) }}"
|
||
class="btn btn-sm btn-outline-primary" title="Muat Turun Sijil">
|
||
<i class="bi bi-download"></i>
|
||
</a>
|
||
@endif
|
||
<a href="{{ route('admin.programs.participants.edit', [$program, $pp]) . (request()->hasAny(['search','source','status','page']) ? '?' . http_build_query(request()->only(['search','source','status','page'])) : '') }}"
|
||
class="btn btn-sm btn-outline-secondary" title="Edit Peserta">
|
||
<i class="bi bi-pencil"></i>
|
||
</a>
|
||
@if($pp->status !== 'checked_in')
|
||
<form method="POST"
|
||
action="{{ route('admin.programs.participants.destroy', [$program, $pp]) }}"
|
||
onsubmit="return confirm('Keluarkan peserta {{ $p->name }} daripada program?')">
|
||
@csrf @method('DELETE')
|
||
<button class="btn btn-sm btn-outline-danger" title="Keluarkan">
|
||
<i class="bi bi-person-dash"></i>
|
||
</button>
|
||
</form>
|
||
@endif
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
@endforeach
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
@if($programParticipants->hasPages())
|
||
<div class="px-3 py-3 border-top">
|
||
{{ $programParticipants->links() }}
|
||
</div>
|
||
@endif
|
||
@endif
|
||
</div>
|
||
</div>
|
||
|
||
@endsection
|