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,188 @@
<?php
namespace App\Http\Controllers;
use App\Models\ChecklistFormula;
use App\Models\ChecklistItem;
use App\Models\ChecklistScope;
use App\Models\ChecklistSection;
use App\Models\ChecklistTemplate;
use Illuminate\Http\Request;
/**
* Mengurus elemen bersarang templat senarai semak (seksyen, skop, item, formula).
* Semua tindakan memerlukan kebenaran 'templat.urus'.
*/
class ChecklistBuilderController extends Controller
{
// Kebenaran 'templat.urus' dikuatkuasakan pada peringkat laluan (route group).
// ---------------- Seksyen ----------------
public function storeSection(Request $request, ChecklistTemplate $template)
{
$data = $this->validateSection($request);
$template->sections()->create($data);
return back()->with('success', 'Seksyen ditambah.');
}
public function updateSection(Request $request, ChecklistSection $section)
{
$section->update($this->validateSection($request));
return back()->with('success', 'Seksyen dikemas kini.');
}
public function destroySection(ChecklistSection $section)
{
$section->delete();
return back()->with('success', 'Seksyen dipadam.');
}
protected function validateSection(Request $request): array
{
$data = $request->validate([
'code' => ['required', 'string', 'max:50'],
'title' => ['required', 'string', 'max:255'],
'description' => ['nullable', 'string', 'max:1000'],
'order' => ['nullable', 'integer', 'min:0'],
'is_formula_enabled' => ['nullable', 'boolean'],
]);
$data['is_formula_enabled'] = $request->boolean('is_formula_enabled');
$data['order'] ??= 0;
return $data;
}
// ---------------- Skop ----------------
public function storeScope(Request $request, ChecklistSection $section)
{
$section->scopes()->create($this->validateScope($request));
return back()->with('success', 'Skop ditambah.');
}
public function updateScope(Request $request, ChecklistScope $scope)
{
$scope->update($this->validateScope($request));
return back()->with('success', 'Skop dikemas kini.');
}
public function destroyScope(ChecklistScope $scope)
{
$scope->delete();
return back()->with('success', 'Skop dipadam.');
}
protected function validateScope(Request $request): array
{
$data = $request->validate([
'code' => ['required', 'string', 'max:50'],
'title' => ['required', 'string', 'max:255'],
'description' => ['nullable', 'string', 'max:1000'],
'order' => ['nullable', 'integer', 'min:0'],
]);
$data['order'] ??= 0;
return $data;
}
// ---------------- Item ----------------
public function storeItem(Request $request, ChecklistSection $section)
{
$data = $this->validateItem($request);
$section->items()->create($data);
return back()->with('success', 'Item ditambah.');
}
public function updateItem(Request $request, ChecklistItem $item)
{
$item->update($this->validateItem($request));
return back()->with('success', 'Item dikemas kini.');
}
public function destroyItem(ChecklistItem $item)
{
$item->delete();
return back()->with('success', 'Item dipadam.');
}
protected function validateItem(Request $request): array
{
$data = $request->validate([
'checklist_scope_id' => ['nullable', 'exists:checklist_scopes,id'],
'code' => ['required', 'string', 'max:50'],
'formula_token' => ['nullable', 'string', 'max:50', 'regex:/^[A-Za-z_][A-Za-z0-9_]*$/'],
'label' => ['required', 'string', 'max:500'],
'description' => ['nullable', 'string', 'max:1000'],
'input_type' => ['required', 'in:'.implode(',', array_keys(ChecklistItem::INPUT_TYPES))],
'options' => ['nullable', 'string'],
'unit' => ['nullable', 'string', 'max:50'],
'is_required' => ['nullable', 'boolean'],
'is_calculated' => ['nullable', 'boolean'],
'formula' => ['nullable', 'string', 'max:500'],
'order' => ['nullable', 'integer', 'min:0'],
], [], ['formula_token' => 'token formula']);
$data['is_required'] = $request->boolean('is_required');
$data['is_calculated'] = $request->boolean('is_calculated');
$data['order'] ??= 0;
// Tukar senarai pilihan (satu baris satu pilihan) kepada array.
if (! empty($data['options'])) {
$data['options'] = collect(preg_split('/\r\n|\r|\n/', $data['options']))
->map(fn ($v) => trim($v))->filter()->values()->all();
} else {
$data['options'] = null;
}
return $data;
}
// ---------------- Formula ----------------
public function storeFormula(Request $request, ChecklistTemplate $template)
{
$data = $this->validateFormula($request);
$template->formulas()->create($data);
return back()->with('success', 'Formula ditambah.');
}
public function updateFormula(Request $request, ChecklistFormula $formula)
{
$formula->update($this->validateFormula($request));
return back()->with('success', 'Formula dikemas kini.');
}
public function destroyFormula(ChecklistFormula $formula)
{
$formula->delete();
return back()->with('success', 'Formula dipadam.');
}
protected function validateFormula(Request $request): array
{
$data = $request->validate([
'checklist_section_id' => ['nullable', 'exists:checklist_sections,id'],
'result_token' => ['required', 'string', 'max:50', 'regex:/^[A-Za-z_][A-Za-z0-9_]*$/'],
'label' => ['nullable', 'string', 'max:255'],
'expression' => ['required', 'string', 'max:500'],
'unit' => ['nullable', 'string', 'max:50'],
'guard_div_zero' => ['nullable', 'boolean'],
'order' => ['nullable', 'integer', 'min:0'],
], [], ['result_token' => 'token hasil', 'expression' => 'ungkapan']);
$data['guard_div_zero'] = $request->boolean('guard_div_zero');
$data['order'] ??= 0;
return $data;
}
}