first commit

This commit is contained in:
Saufi
2026-06-24 20:32:14 +08:00
commit 10fb30ad69
201 changed files with 21356 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
<div class="modal fade" id="editFormula{{ $formula->id }}" tabindex="-1"><div class="modal-dialog"><div class="modal-content">
<form method="POST" action="{{ route('checklist.formulas.update', $formula) }}">
@csrf @method('PUT')
<div class="modal-header"><h5 class="modal-title">Kemaskini Formula {{ $formula->result_token }}</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
<div class="modal-body">
<div class="mb-2"><label class="form-label">Token Hasil</label><input name="result_token" value="{{ $formula->result_token }}" class="form-control" required></div>
<div class="mb-2"><label class="form-label">Label</label><input name="label" value="{{ $formula->label }}" class="form-control"></div>
<div class="mb-2"><label class="form-label">Ungkapan</label><input name="expression" value="{{ $formula->expression }}" class="form-control" required></div>
<div class="row g-2 mb-2">
<div class="col-6"><label class="form-label">Unit</label><input name="unit" value="{{ $formula->unit }}" class="form-control"></div>
<div class="col-6"><label class="form-label">Turutan</label><input name="order" type="number" value="{{ $formula->order }}" class="form-control"></div>
</div>
<div class="form-check mb-2"><input type="checkbox" name="guard_div_zero" value="1" class="form-check-input" id="guard{{ $formula->id }}" @checked($formula->guard_div_zero)><label for="guard{{ $formula->id }}" class="form-check-label">Lindung pembahagian dengan sifar</label></div>
<div class="mb-2"><label class="form-label">Seksyen berkaitan</label>
<select name="checklist_section_id" class="form-select">
<option value=""> Tiada </option>
@foreach ($template->sections as $s)<option value="{{ $s->id }}" @selected($formula->checklist_section_id==$s->id)>{{ $s->code }} {{ $s->title }}</option>@endforeach
</select>
</div>
</div>
<div class="modal-footer"><button class="btn btn-success">Simpan</button></div>
</form>
</div></div></div>

View File

@@ -0,0 +1,49 @@
@php
$isEdit = (bool) $item;
$modalId = $isEdit ? 'editItem'.$item->id : 'addItem'.$section->id;
$action = $isEdit ? route('checklist.items.update', $item) : route('checklist.items.store', $section);
$optsText = $isEdit && is_array($item->options) ? implode("\n", $item->options) : '';
@endphp
<div class="modal fade" id="{{ $modalId }}" tabindex="-1"><div class="modal-dialog modal-lg"><div class="modal-content">
<form method="POST" action="{{ $action }}">
@csrf
@if($isEdit) @method('PUT') @endif
<div class="modal-header">
<h5 class="modal-title">{{ $isEdit ? 'Kemaskini Item '.$item->code : 'Tambah Item — Seksyen '.$section->code }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="row g-2">
<div class="col-12"><label class="form-label">Letak dalam Skop</label>
<select name="checklist_scope_id" class="form-select" {{ $section->scopes->isEmpty() ? 'disabled' : '' }}>
<option value=""> Tiada (terus di bawah seksyen) </option>
@foreach ($section->scopes as $sc)<option value="{{ $sc->id }}" @selected(($item->checklist_scope_id ?? null)==$sc->id)>{{ $sc->code }} {{ $sc->title }}</option>@endforeach
</select>
@if($section->scopes->isEmpty())
<div class="form-text text-warning">Seksyen ini belum ada skop. Tambah skop dahulu untuk meletakkan item dalam skop.</div>
@else
<div class="form-text">Pilih skop atau biarkan "Tiada" untuk item terus di bawah seksyen.</div>
@endif
</div>
<div class="col-md-3"><label class="form-label">Kod <span class="text-danger">*</span></label><input name="code" value="{{ $item->code ?? '' }}" class="form-control" placeholder="A.1.i" required></div>
<div class="col-md-3"><label class="form-label">Token Formula</label><input name="formula_token" value="{{ $item->formula_token ?? '' }}" class="form-control" placeholder="SKOP1"></div>
<div class="col-md-3"><label class="form-label">Unit</label><input name="unit" value="{{ $item->unit ?? '' }}" class="form-control" placeholder="tCO2e"></div>
<div class="col-md-3"><label class="form-label">Turutan</label><input name="order" type="number" value="{{ $item->order ?? ($section->items->count()+1) }}" class="form-control"></div>
<div class="col-12"><label class="form-label">Label <span class="text-danger">*</span></label><input name="label" value="{{ $item->label ?? '' }}" class="form-control" required></div>
<div class="col-12"><label class="form-label">Penerangan</label><textarea name="description" class="form-control">{{ $item->description ?? '' }}</textarea></div>
<div class="col-md-6"><label class="form-label">Jenis Input</label>
<select name="input_type" class="form-select">
@foreach ($inputTypes as $val => $lbl)<option value="{{ $val }}" @selected(($item->input_type ?? 'number')===$val)>{{ $lbl }}</option>@endforeach
</select>
</div>
<div class="col-md-6 d-flex align-items-end gap-3">
<div class="form-check"><input type="checkbox" name="is_required" value="1" class="form-check-input" id="{{ $modalId }}req" @checked($item->is_required ?? false)><label for="{{ $modalId }}req" class="form-check-label">Wajib</label></div>
<div class="form-check"><input type="checkbox" name="is_calculated" value="1" class="form-check-input" id="{{ $modalId }}calc" @checked($item->is_calculated ?? false)><label for="{{ $modalId }}calc" class="form-check-label">Dikira</label></div>
</div>
<div class="col-12"><label class="form-label">Formula item (jika dikira)</label><input name="formula" value="{{ $item->formula ?? '' }}" class="form-control" placeholder="A - B"></div>
<div class="col-12"><label class="form-label">Pilihan (untuk jenis select) satu baris satu pilihan</label><textarea name="options" rows="3" class="form-control" placeholder="GBI&#10;GreenRE&#10;LEED">{{ $optsText }}</textarea></div>
</div>
</div>
<div class="modal-footer"><button class="btn btn-success">Simpan</button></div>
</form>
</div></div></div>

View File

@@ -0,0 +1,17 @@
{{-- Modal edit seksyen --}}
<div class="modal fade" id="editSection{{ $section->id }}" tabindex="-1"><div class="modal-dialog"><div class="modal-content">
<form method="POST" action="{{ route('checklist.sections.update', $section) }}">
@csrf @method('PUT')
<div class="modal-header"><h5 class="modal-title">Kemaskini Seksyen {{ $section->code }}</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
<div class="modal-body">
<div class="row g-2">
<div class="col-4"><label class="form-label">Kod</label><input name="code" value="{{ $section->code }}" class="form-control" required></div>
<div class="col-8"><label class="form-label">Tajuk</label><input name="title" value="{{ $section->title }}" class="form-control" required></div>
<div class="col-12"><label class="form-label">Penerangan</label><textarea name="description" class="form-control">{{ $section->description }}</textarea></div>
<div class="col-6"><label class="form-label">Turutan</label><input name="order" type="number" value="{{ $section->order }}" class="form-control"></div>
<div class="col-6 d-flex align-items-end"><div class="form-check form-switch"><input type="checkbox" name="is_formula_enabled" value="1" class="form-check-input" id="secFormula{{ $section->id }}" @checked($section->is_formula_enabled)><label for="secFormula{{ $section->id }}" class="form-check-label">Formula didayakan</label></div></div>
</div>
</div>
<div class="modal-footer"><button class="btn btn-success">Simpan</button></div>
</form>
</div></div></div>

View File

@@ -0,0 +1,175 @@
@extends('layouts.app')
@section('title', 'Pembina Templat')
@section('heading', 'Templat Senarai Semak')
@section('page-title', 'Pembina: '.$template->name)
@section('subtitle', 'Versi '.$template->version.($template->is_active ? ' • Aktif' : ''))
@section('actions')
<button class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#editTemplateModal"><i class="bi bi-gear me-1"></i> Tetapan Templat</button>
<a href="{{ route('checklist-templates.index') }}" class="btn btn-link">Kembali</a>
@endsection
@section('content')
@php($inputTypes = App\Models\ChecklistItem::INPUT_TYPES)
<div class="row g-3">
<div class="col-lg-8">
{{-- ============ SEKSYEN ============ --}}
@foreach ($template->sections as $section)
<div class="card mb-3">
<div class="card-header checklist-section-header d-flex justify-content-between align-items-center">
<div>
<span class="badge bg-success me-1">{{ $section->code }}</span>
<strong>{{ $section->title }}</strong>
@if($section->is_formula_enabled)<span class="badge bg-info ms-1">Formula</span>@endif
</div>
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#editSection{{ $section->id }}"><i class="bi bi-pencil"></i></button>
<form method="POST" action="{{ route('checklist.sections.destroy', $section) }}" data-confirm="Padam seksyen '{{ $section->code }}' beserta skop & item?">@csrf @method('DELETE')<button class="btn btn-outline-danger"><i class="bi bi-trash"></i></button></form>
</div>
</div>
<div class="card-body">
@if($section->description)<p class="small text-muted">{{ $section->description }}</p>@endif
{{-- Skop --}}
@if($section->scopes->isNotEmpty())
<div class="mb-2">
<h6 class="small text-uppercase text-muted">Skop</h6>
@foreach ($section->scopes as $scope)
<div class="d-flex justify-content-between align-items-center border rounded px-2 py-1 mb-1">
<span><span class="badge bg-secondary">{{ $scope->code }}</span> {{ $scope->title }}</span>
<form method="POST" action="{{ route('checklist.scopes.destroy', $scope) }}" data-confirm="Padam skop ini?">@csrf @method('DELETE')<button class="btn btn-sm btn-link text-danger p-0"><i class="bi bi-x-lg"></i></button></form>
</div>
@endforeach
</div>
@endif
{{-- Borang tambah skop --}}
<details class="mb-3"><summary class="small text-primary" style="cursor:pointer">+ Tambah skop</summary>
<form method="POST" action="{{ route('checklist.scopes.store', $section) }}" class="row g-2 mt-1">
@csrf
<div class="col-3"><input name="code" class="form-control form-control-sm" placeholder="Kod (SKOP1)" required></div>
<div class="col-5"><input name="title" class="form-control form-control-sm" placeholder="Tajuk skop" required></div>
<div class="col-2"><input name="order" type="number" class="form-control form-control-sm" placeholder="Turutan" value="0"></div>
<div class="col-2 d-grid"><button class="btn btn-sm btn-outline-success">Tambah</button></div>
</form>
</details>
{{-- Item --}}
<h6 class="small text-uppercase text-muted">Item</h6>
<div class="table-responsive">
<table class="table table-sm align-middle">
<thead><tr><th>Kod</th><th>Label</th><th>Skop</th><th>Token</th><th>Jenis</th><th>Unit</th><th>Wajib</th><th></th></tr></thead>
<tbody>
@forelse ($section->items as $item)
<tr>
<td>{{ $item->code }}</td>
<td>{{ $item->label }}@if($item->is_calculated)<span class="badge bg-info ms-1">dikira</span>@endif</td>
<td>@if($item->scope)<span class="badge bg-secondary">{{ $item->scope->code }}</span>@else<span class="text-muted small"> Tiada </span>@endif</td>
<td><code>{{ $item->formula_token ?: '—' }}</code></td>
<td><span class="small">{{ $inputTypes[$item->input_type] ?? $item->input_type }}</span></td>
<td>{{ $item->unit ?: '—' }}</td>
<td>{!! $item->is_required ? '<i class="bi bi-check-lg text-success"></i>' : '—' !!}</td>
<td class="text-end">
<button class="btn btn-sm btn-link p-0 me-1" data-bs-toggle="modal" data-bs-target="#editItem{{ $item->id }}"><i class="bi bi-pencil"></i></button>
<form method="POST" action="{{ route('checklist.items.destroy', $item) }}" class="d-inline" data-confirm="Padam item ini?">@csrf @method('DELETE')<button class="btn btn-sm btn-link text-danger p-0"><i class="bi bi-trash"></i></button></form>
</td>
</tr>
@empty
<tr><td colspan="8" class="text-center text-muted">Tiada item.</td></tr>
@endforelse
</tbody>
</table>
</div>
{{-- Borang tambah item --}}
<button class="btn btn-sm btn-outline-primary" data-bs-toggle="modal" data-bs-target="#addItem{{ $section->id }}"><i class="bi bi-plus-lg"></i> Tambah Item</button>
</div>
</div>
{{-- Modal edit seksyen --}}
@include('checklist.templates._section_modal', ['section' => $section, 'mode' => 'edit'])
{{-- Modal tambah item --}}
@include('checklist.templates._item_modal', ['section' => $section, 'item' => null, 'inputTypes' => $inputTypes])
{{-- Modal edit item --}}
@foreach ($section->items as $item)
@include('checklist.templates._item_modal', ['section' => $section, 'item' => $item, 'inputTypes' => $inputTypes])
@endforeach
@endforeach
{{-- Tambah seksyen --}}
<div class="card">
<div class="card-body">
<h6>Tambah Seksyen Baharu</h6>
<form method="POST" action="{{ route('checklist.sections.store', $template) }}" class="row g-2">
@csrf
<div class="col-md-2"><input name="code" class="form-control" placeholder="Kod (A)" required></div>
<div class="col-md-5"><input name="title" class="form-control" placeholder="Tajuk seksyen" required></div>
<div class="col-md-2"><input name="order" type="number" class="form-control" placeholder="Turutan" value="{{ $template->sections->count() + 1 }}"></div>
<div class="col-md-2"><div class="form-check mt-2"><input type="checkbox" name="is_formula_enabled" value="1" class="form-check-input" id="newSecFormula"><label for="newSecFormula" class="form-check-label small">Formula</label></div></div>
<div class="col-md-1 d-grid"><button class="btn btn-success">+</button></div>
</form>
</div>
</div>
</div>
{{-- ============ FORMULA ============ --}}
<div class="col-lg-4">
<div class="card position-sticky" style="top:70px">
<div class="card-header bg-white fw-semibold">Formula Seksyen</div>
<div class="card-body">
<p class="small text-muted">Token tersedia: <em>formula_token</em> setiap item & <em>result_token</em> formula sebelumnya. Cth: <code>SKOP1 + SKOP2 + SKOP3</code>, <code>A - B</code>, <code>D / A * 100</code>.</p>
@forelse ($template->formulas as $f)
<div class="border rounded p-2 mb-2">
<div class="d-flex justify-content-between">
<strong><code>{{ $f->result_token }}</code> = {{ $f->expression }}</strong>
<div>
<button class="btn btn-sm btn-link p-0 me-1" data-bs-toggle="modal" data-bs-target="#editFormula{{ $f->id }}"><i class="bi bi-pencil"></i></button>
<form method="POST" action="{{ route('checklist.formulas.destroy', $f) }}" class="d-inline" data-confirm="Padam formula?">@csrf @method('DELETE')<button class="btn btn-sm btn-link text-danger p-0"><i class="bi bi-trash"></i></button></form>
</div>
</div>
<div class="small text-muted">{{ $f->label }} @if($f->unit)({{ $f->unit }})@endif @if($f->guard_div_zero)<span class="badge bg-warning text-dark">guard ÷0</span>@endif</div>
</div>
@include('checklist.templates._formula_modal', ['template' => $template, 'formula' => $f])
@empty
<p class="text-muted small">Tiada formula.</p>
@endforelse
<hr>
<h6 class="small">Tambah Formula</h6>
<form method="POST" action="{{ route('checklist.formulas.store', $template) }}">
@csrf
<div class="mb-2"><input name="result_token" class="form-control form-control-sm" placeholder="Token hasil (cth: A)" required></div>
<div class="mb-2"><input name="label" class="form-control form-control-sm" placeholder="Label"></div>
<div class="mb-2"><input name="expression" class="form-control form-control-sm" placeholder="Ungkapan (cth: A - B)" required></div>
<div class="row g-2 mb-2">
<div class="col-6"><input name="unit" class="form-control form-control-sm" placeholder="Unit"></div>
<div class="col-6"><input name="order" type="number" class="form-control form-control-sm" placeholder="Turutan" value="{{ $template->formulas->count()+1 }}"></div>
</div>
<div class="form-check mb-2"><input type="checkbox" name="guard_div_zero" value="1" class="form-check-input" id="guardNew"><label for="guardNew" class="form-check-label small">Lindung pembahagian dengan sifar</label></div>
<select name="checklist_section_id" class="form-select form-select-sm mb-2">
<option value=""> Kaitkan seksyen (pilihan) </option>
@foreach ($template->sections as $s)<option value="{{ $s->id }}">{{ $s->code }} {{ $s->title }}</option>@endforeach
</select>
<button class="btn btn-sm btn-success w-100">Tambah Formula</button>
</form>
</div>
</div>
</div>
</div>
{{-- Modal tetapan templat --}}
<div class="modal fade" id="editTemplateModal" tabindex="-1"><div class="modal-dialog"><div class="modal-content">
<form method="POST" action="{{ route('checklist-templates.update', $template) }}">
@csrf @method('PUT')
<div class="modal-header"><h5 class="modal-title">Tetapan Templat</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
<div class="modal-body">
<div class="mb-2"><label class="form-label">Nama</label><input name="name" value="{{ $template->name }}" class="form-control" required></div>
<div class="mb-2"><label class="form-label">Versi</label><input name="version" value="{{ $template->version }}" class="form-control" required></div>
<div class="mb-2"><label class="form-label">Penerangan</label><textarea name="description" class="form-control">{{ $template->description }}</textarea></div>
<div class="form-check form-switch"><input type="checkbox" name="is_active" value="1" class="form-check-input" id="tplActive" @checked($template->is_active)><label for="tplActive" class="form-check-label">Templat aktif</label></div>
</div>
<div class="modal-footer"><button class="btn btn-success">Simpan</button></div>
</form>
</div></div></div>
@endsection

View File

@@ -0,0 +1,18 @@
@extends('layouts.app')
@section('title', 'Templat Baharu')
@section('heading', 'Templat Senarai Semak')
@section('page-title', 'Cipta Templat Baharu')
@section('content')
<div class="card"><div class="card-body">
<form method="POST" action="{{ route('checklist-templates.store') }}">
@csrf
<div class="row g-3">
<div class="col-md-8"><label class="form-label">Nama Templat <span class="text-danger">*</span></label><input type="text" name="name" value="{{ old('name') }}" class="form-control" required></div>
<div class="col-md-4"><label class="form-label">Versi</label><input type="text" name="version" value="{{ old('version','1.0') }}" class="form-control"></div>
<div class="col-12"><label class="form-label">Penerangan</label><textarea name="description" rows="2" class="form-control">{{ old('description') }}</textarea></div>
<div class="col-12"><div class="form-check form-switch"><input type="checkbox" name="is_active" value="1" id="isActive" class="form-check-input" @checked(old('is_active'))><label for="isActive" class="form-check-label">Tetapkan sebagai templat aktif</label></div></div>
</div>
<div class="mt-4"><button class="btn btn-success"><i class="bi bi-save me-1"></i> Simpan & Bina</button><a href="{{ route('checklist-templates.index') }}" class="btn btn-link">Batal</a></div>
</form>
</div></div>
@endsection

View File

@@ -0,0 +1,35 @@
@extends('layouts.app')
@section('title', 'Templat Senarai Semak')
@section('heading', 'Templat Senarai Semak')
@section('page-title', 'Templat Senarai Semak')
@section('subtitle', 'Reka bentuk borang senarai semak secara dinamik — JPP boleh ubah seksyen, item & formula tanpa perubahan kod.')
@section('actions')
<a href="{{ route('checklist-templates.create') }}" class="btn btn-success"><i class="bi bi-plus-lg me-1"></i> Templat Baharu</a>
@endsection
@section('content')
<div class="card"><div class="card-body p-0">
<table class="table table-hover align-middle mb-0">
<thead><tr><th class="ps-3">Nama Templat</th><th>Versi</th><th>Seksyen</th><th>Status</th><th></th></tr></thead>
<tbody>
@forelse ($templates as $t)
<tr>
<td class="ps-3 fw-semibold">{{ $t->name }}</td>
<td>{{ $t->version }}</td>
<td><span class="badge bg-light text-dark">{{ $t->sections_count }}</span></td>
<td>@if($t->is_active)<span class="badge bg-success">Aktif</span>@else<span class="badge bg-secondary">Tidak Aktif</span>@endif</td>
<td class="text-end pe-3">
<a href="{{ route('checklist-templates.builder', $t) }}" class="btn btn-sm btn-primary"><i class="bi bi-tools me-1"></i> Bina</a>
@unless($t->is_active)
<form method="POST" action="{{ route('checklist-templates.activate', $t) }}" class="d-inline">@csrf<button class="btn btn-sm btn-outline-success">Aktifkan</button></form>
@endunless
</td>
</tr>
@empty
<tr><td colspan="5" class="text-center text-muted py-3">Tiada templat.</td></tr>
@endforelse
</tbody>
</table>
</div></div>
@endsection