This commit is contained in:
Saufi
2026-06-03 08:51:22 +08:00
commit a14d43fe34
347 changed files with 38197 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
@csrf
<div class="row g-3">
<div class="col-md-6">
<label for="election_id" class="form-label">Pilihan Raya</label>
<select id="election_id" name="election_id" class="form-select @error('election_id') is-invalid @enderror" required>
<option value="">Pilih pilihan raya</option>
@foreach ($elections as $election)
<option value="{{ $election->id }}" @selected((string) old('election_id', $pusat->election_id) === (string) $election->id)>
{{ $election->name }}
</option>
@endforeach
</select>
@error('election_id')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-md-6">
<label for="dun_id" class="form-label">Dewan Undangan Negeri (DUN)</label>
<select id="dun_id" name="dun_id" class="form-select @error('dun_id') is-invalid @enderror">
<option value="">Pilih DUN (pilihan)</option>
@foreach ($duns as $dun)
<option value="{{ $dun->id }}" @selected((string) old('dun_id', $pusat->dun_id) === (string) $dun->id)>
{{ $dun->code }} - {{ $dun->name }}
</option>
@endforeach
</select>
@error('dun_id')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-md-4">
<label for="code" class="form-label">Kod Pusat</label>
<input id="code" type="text" name="code" value="{{ old('code', $pusat->code) }}" class="form-control @error('code') is-invalid @enderror" maxlength="50" required>
@error('code')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-md-8">
<label for="name" class="form-label">Nama Pusat Mengundi</label>
<input id="name" type="text" name="name" value="{{ old('name', $pusat->name) }}" class="form-control @error('name') is-invalid @enderror" maxlength="255" required>
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-12">
<label for="address" class="form-label">Alamat</label>
<textarea id="address" name="address" rows="3" class="form-control @error('address') is-invalid @enderror">{{ old('address', $pusat->address) }}</textarea>
@error('address')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
@unless ($pusat->exists)
@php
$operationalFields = [
'saluran_count' => ['label' => 'Bilangan Saluran', 'default' => 1, 'min' => 1],
'ktm_count' => ['label' => 'KTM setiap Saluran', 'default' => 1],
'polis_iring_count' => ['label' => 'Polis Iring setiap Saluran', 'default' => 1],
'kp_count' => ['label' => 'KP setiap Saluran', 'default' => 4],
'ppm_count' => ['label' => 'PPM setiap Pusat', 'default' => 1],
'kpdp_count' => ['label' => 'KPDP setiap Saluran', 'default' => 1],
'papm_count' => ['label' => 'PAPM setiap Pusat', 'default' => 0],
'jkm_count' => ['label' => 'JKM setiap Pusat', 'default' => 1],
'kkm_count' => ['label' => 'KKM setiap Pusat', 'default' => 1],
'calon_tambahan_count' => ['label' => 'Calon Tambahan setiap Saluran', 'default' => 1],
];
@endphp
<div class="col-12 mt-4">
<h2 class="h6 mb-1">Bilangan Operasi</h2>
<p class="text-body-secondary small mb-0">Saluran akan dijana mengikut nombor secara automatik.</p>
</div>
@foreach ($operationalFields as $field => $configuration)
<div class="col-6 col-md-4 col-xl-3">
<label for="{{ $field }}" class="form-label">{{ $configuration['label'] }}</label>
<input
id="{{ $field }}"
type="number"
name="{{ $field }}"
value="{{ old($field, $configuration['default']) }}"
min="{{ $configuration['min'] ?? 0 }}"
max="100"
class="form-control @error($field) is-invalid @enderror"
required
>
@error($field)
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
@endforeach
@endunless
</div>
<div class="d-flex justify-content-end gap-2 mt-4">
<a href="{{ $pusat->exists ? route('admin.setup.pusat.show', $pusat) : route('admin.setup.pusat.index') }}" class="btn btn-outline-secondary">Batal</a>
<button class="btn btn-primary" type="submit">
<i class="bi bi-save me-1"></i>{{ $pusat->exists ? 'Kemas Kini Pusat' : 'Simpan Pusat' }}
</button>
</div>

View File

@@ -0,0 +1,18 @@
@extends('layouts.app')
@section('title', 'Tambah Pusat')
@section('content')
<div class="page-heading">
<div class="eyebrow">Setup</div>
<h1 class="h3 mb-0">Tambah Pusat Mengundi</h1>
</div>
@include('admin.setup._nav')
<div class="content-panel p-3 p-md-4">
<form method="POST" action="{{ route('admin.setup.pusat.store') }}">
@include('admin.setup.pusat._form')
</form>
</div>
@endsection

View File

@@ -0,0 +1,19 @@
@extends('layouts.app')
@section('title', 'Edit Pusat')
@section('content')
<div class="page-heading">
<div class="eyebrow">Setup</div>
<h1 class="h3 mb-0">Edit Pusat Mengundi</h1>
</div>
@include('admin.setup._nav')
<div class="content-panel p-3 p-md-4">
<form method="POST" action="{{ route('admin.setup.pusat.update', $pusat) }}">
@method('PUT')
@include('admin.setup.pusat._form')
</form>
</div>
@endsection

View File

@@ -0,0 +1,47 @@
@extends('layouts.app')
@section('title', 'Pusat Mengundi')
@section('content')
<div class="page-heading">
<div class="eyebrow">Setup</div>
<div class="d-flex justify-content-between flex-column flex-lg-row gap-3">
<div><h1 class="h3 mb-1">Pusat Mengundi</h1><p class="text-secondary mb-0">Pusat Mengundi, QR pendaftaran, dan assignment PPM.</p></div>
<a href="{{ route('admin.setup.pusat.create') }}" class="btn btn-primary"><i class="bi bi-plus-circle me-1"></i>Tambah</a>
</div>
</div>
@include('admin.setup._nav')
<div class="content-panel p-3 p-md-4">
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead><tr><x-sort-th column="code" label="Kod" /><x-sort-th column="name" label="Nama" /><th>DUN</th><th>PPM</th><th>Saluran</th><th>QR</th><th class="text-end no-sort">Tindakan</th></tr></thead>
<tbody>
@forelse ($pusats as $pusat)
<tr>
<td class="fw-semibold">{{ $pusat->code }}</td>
<td>{{ $pusat->name }}</td>
<td>{{ $pusat->dun?->code }}</td>
<td class="small text-secondary">{{ $pusat->ppm_name ?: '-' }}</td>
<td>{{ $pusat->saluran_mengundis_count ?? $pusat->saluranMengundis->count() }}</td>
<td><span class="badge {{ $pusat->qr_code_path ? 'text-bg-success' : 'text-bg-secondary' }}">{{ $pusat->qr_code_path ? 'Ada' : 'Belum' }}</span></td>
<td class="text-end">
<a href="{{ route('admin.setup.pusat.show', $pusat) }}" class="btn btn-sm btn-outline-primary">Buka</a>
<a href="{{ route('admin.setup.pusat.saluran.index', $pusat) }}" class="btn btn-sm btn-outline-info">Saluran</a>
<a href="{{ route('admin.setup.pusat.edit', $pusat) }}" class="btn btn-sm btn-outline-secondary">Edit</a>
<form action="{{ route('admin.setup.pusat.destroy', $pusat) }}" method="POST" class="d-inline"
onsubmit="return confirm('Padam {{ addslashes($pusat->name) }}? Tindakan ini tidak boleh diundur.')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-outline-danger">Padam</button>
</form>
</td>
</tr>
@empty
<tr><td colspan="7" class="text-center text-secondary py-4">Tiada rekod. <a href="{{ route('admin.setup.import.create') }}">Import data pusat</a>.</td></tr>
@endforelse
</tbody>
</table>
</div>
{{ $pusats->links() }}
</div>
@endsection

View File

@@ -0,0 +1,87 @@
@extends('layouts.app')
@section('title', $pusat->name)
@section('content')
<div class="page-heading">
<div class="eyebrow">Pusat Mengundi</div>
<div class="d-flex justify-content-between flex-column flex-lg-row gap-3">
<div>
<h1 class="h3 mb-1">{{ $pusat->name }}</h1>
<p class="text-secondary mb-0">{{ $pusat->code }} - {{ $pusat->daerahMengundi?->name }}</p>
</div>
<div class="d-flex gap-2">
<a href="{{ route('admin.setup.pusat.edit', $pusat) }}" class="btn btn-outline-primary"><i class="bi bi-pencil me-1"></i>Edit</a>
<form method="POST" action="{{ route('admin.setup.pusat.generate-qr', $pusat) }}">
@csrf
<button class="btn btn-primary" type="submit"><i class="bi bi-qr-code me-1"></i>Jana QR</button>
</form>
</div>
</div>
</div>
@include('admin.setup._nav')
<div class="row g-4">
<div class="col-12 col-xl-7">
<div class="content-panel p-3 p-md-4 mb-4">
<h2 class="h5 mb-3">Maklumat Pusat</h2>
<dl class="row mb-0">
<dt class="col-sm-4">Election</dt><dd class="col-sm-8">{{ $pusat->election?->name }}</dd>
<dt class="col-sm-4">Alamat</dt><dd class="col-sm-8">{{ $pusat->address ?: '-' }}</dd>
<dt class="col-sm-4">Public UUID</dt><dd class="col-sm-8"><code>{{ $pusat->public_uuid }}</code></dd>
<dt class="col-sm-4">Link QR</dt>
<dd class="col-sm-8">
@if ($pusat->registration_url)
<a href="{{ $pusat->registration_url }}" target="_blank">{{ $pusat->registration_url }}</a>
@else
<span class="text-secondary">Belum dijana.</span>
@endif
</dd>
</dl>
</div>
<div class="content-panel p-3 p-md-4">
<h2 class="h5 mb-3">Saluran</h2>
<div class="table-responsive">
<table class="table table-sm align-middle">
<thead><tr><th>No.</th><th>Nama</th><th>Pengundi</th></tr></thead>
<tbody>
@forelse ($pusat->saluranMengundis as $saluran)
<tr><td>{{ $saluran->number }}</td><td>{{ $saluran->name }}</td><td>{{ $saluran->voter_count ?? '-' }}</td></tr>
@empty
<tr><td colspan="3" class="text-secondary text-center py-3">Tiada saluran.</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
<div class="col-12 col-xl-5">
<div class="content-panel p-3 p-md-4 mb-4">
<h2 class="h5 mb-3">QR Pendaftaran</h2>
@if ($pusat->qr_code_path)
<img class="img-fluid border rounded bg-white p-2 mb-3" style="max-width: 220px" src="{{ route('admin.setup.pusat.qr-svg', $pusat) }}" alt="QR Pusat Mengundi">
@else
<p class="text-secondary">QR belum dijana.</p>
@endif
<div class="small text-secondary">QR menunjuk ke pautan awam Pusat Mengundi ini.</div>
</div>
<div class="content-panel p-3 p-md-4">
<h2 class="h5 mb-3">Tetapan PPM</h2>
<p class="mb-3">PPM semasa: <span class="fw-semibold">{{ $ppmAssignment?->user?->name ?? 'Belum ditetapkan' }}</span></p>
<form method="POST" action="{{ route('admin.setup.pusat.assign-ppm', $pusat) }}">
@csrf
<label for="user_id" class="form-label">Pilih pengguna</label>
<select id="user_id" name="user_id" class="form-select mb-3" required data-tom-select>
@foreach ($users as $user)
<option value="{{ $user->id }}" @selected($ppmAssignment?->user_id === $user->id)>{{ $user->name }} - {{ $user->email }}</option>
@endforeach
</select>
<button class="btn btn-primary" type="submit"><i class="bi bi-person-check me-1"></i>Simpan PPM</button>
</form>
</div>
</div>
</div>
@endsection