diff --git a/app/Http/Controllers/Web/Ekosistem/KolomBasisDataController.php b/app/Http/Controllers/Web/Ekosistem/KolomBasisDataController.php index 0167462..d832187 100644 --- a/app/Http/Controllers/Web/Ekosistem/KolomBasisDataController.php +++ b/app/Http/Controllers/Web/Ekosistem/KolomBasisDataController.php @@ -49,18 +49,27 @@ class KolomBasisDataController extends Controller 'kolom' => ['required', 'string', 'regex:/^[a-z0-9]+(_[a-z0-9]+)*$/', - Rule::unique('ekosistem_basis_data_kolom')->where(function ($query) use ($request) { - return $query->where('tabel_id', $request->tabel_id)->whereNull('deleted_at'); + Rule::unique('ekosistem_basis_data_kolom')->where(function ($query) use ($tabelId) { + return $query->where('tabel_id', $tabelId)->whereNull('deleted_at'); }) ], 'label' => ['required', 'string'], - 'tipe' => ['required', 'string', Rule::in(['varchar', 'integer', 'text', 'date', 'boolean', 'datetime', 'float', 'foreign_key'])], + 'tipe' => ['required', 'string', + Rule::in(['varchar', 'integer', 'text', 'date', 'boolean', 'datetime', 'float', 'foreign_key', 'enum'])], 'validasi' => ['nullable', 'json'], 'relasi_tabel' => ['nullable', 'string'], 'relasi_kolom_id' => ['nullable', 'string'], 'relasi_kolom_label' => ['nullable', 'string'], + 'enum_opsi' => ['nullable', 'json'], ]); + if (!empty($validated['enum_opsi'])) { + $validated['enum_opsi'] = json_decode($validated['enum_opsi'], true); + } + if (!empty($validated['validasi'])) { + $validated['validasi'] = json_decode($validated['validasi'], true); + } + KolomBasisData::create([...$validated, 'tabel_id' => $tabelId, 'created_by' => auth()->id(), @@ -123,11 +132,13 @@ class KolomBasisDataController extends Controller }) ], 'label' => ['required', 'string'], - 'tipe' => ['required', 'string', Rule::in(['varchar', 'integer', 'text', 'date', 'boolean', 'datetime', 'float', 'foreign_key'])], + 'tipe' => ['required', 'string', + Rule::in(['varchar', 'integer', 'text', 'date', 'boolean', 'datetime', 'float', 'foreign_key', 'enum'])], 'validasi' => ['nullable', 'json'], 'relasi_tabel' => ['nullable', 'string'], 'relasi_kolom_id' => ['nullable', 'string'], 'relasi_kolom_label' => ['nullable', 'string'], + 'enum_opsi' => ['nullable', 'json'], ]); $kolom->update([...$validated, diff --git a/app/Http/Controllers/Web/Ekosistem/PetaniCPMController.php b/app/Http/Controllers/Web/Ekosistem/PetaniCPMController.php index b5d25e2..6509798 100644 --- a/app/Http/Controllers/Web/Ekosistem/PetaniCPMController.php +++ b/app/Http/Controllers/Web/Ekosistem/PetaniCPMController.php @@ -13,6 +13,7 @@ use Illuminate\Http\JsonResponse; use App\Models\Ekosistem\PetaniCPM; use App\Models\Wilayah\Provinsi; use App\Models\Pertanian\Komoditas; +use App\Models\Core\Program; use App\Enums\Pendidikan; use App\Enums\Pekerjaan; @@ -30,15 +31,34 @@ class PetaniCPMController extends Controller $perPage = $request->query('per_page', 10); $search = strtolower($request->query('search', '')); + + + $program = null; + $programList = Program::get(); + if (app()->has('SystemProgram')) { + $program = app('SystemProgram'); + } else { + if ($request->has('program_id') && $request->query('program_id')) { + $programId = $request->query('program_id'); + $program = Program::find($programId); + if (!$program) { + abort(400, 'Program tidak ditemukan.'); + } + } + } + $petani = PetaniCPM::when($search, function ($query, $search) { return $query->where('nama', 'like', "%{$search}%"); }) + ->when($program, function ($query) use ($program) { + return $query->where('program_id', $program->id); + }) ->paginate($perPage); - return view('ekosistem.petani-cpm.index', compact('petani')); + return view('ekosistem.petani-cpm.index', compact('petani', 'program', 'programList')); } - public function create(): View + public function create(Request $request): View { if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) { abort(403); @@ -52,8 +72,21 @@ class PetaniCPMController extends Controller $provinsi = Provinsi::all(); $komoditas = Komoditas::all(); + $program = null; + if (app()->has('SystemProgram')) { + $program = app('SystemProgram'); + } else { + if ($request->has('program_id') && $request->query('program_id')) { + $programId = $request->query('program_id'); + $program = Program::find($programId); + } + } + if (!$program) { + abort(400, 'Program tidak ditemukan.'); + } + return view('ekosistem.petani-cpm.add', compact('pendidikan', 'pekerjaan', - 'pernikahan', 'statusKeluarga', 'provinsi', 'komoditas')); + 'pernikahan', 'statusKeluarga', 'provinsi', 'komoditas', 'program')); } /** @@ -65,6 +98,20 @@ class PetaniCPMController extends Controller abort(403); } + if (app()->has('SystemProgram')) { + $program = app('SystemProgram'); + } else { + if ($request->has('program_id') && $request->query('program_id')) { + $programId = $request->query('program_id'); + $program = Program::find($programId); + if (!$program) { + abort(400, 'Program tidak ditemukan.'); + } + } else { + abort(400, 'Program tidak ditemukan.'); + } + } + $validatedData = $request->validate([ 'nama' => ['required','string','max:255'], 'jenis_kelamin' => ['required','boolean'], @@ -88,16 +135,17 @@ class PetaniCPMController extends Controller ]); PetaniCPM::create([...$validatedData, + 'program_id' => $program->id, 'created_by' => auth()->id(), 'updated_by' => auth()->id()]); - return redirect()->route('petani-cpm.index')->with('success', 'Data petani CPM berhasil ditambahkan.'); + return redirect()->route('petani-cpm.index', ['program_id' => $program->id])->with('success', 'Data petani CPM berhasil ditambahkan.'); } /** * Display the specified resource. */ - public function show(string $id) + public function show(string $id): View { if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) { abort(403); @@ -111,12 +159,26 @@ class PetaniCPMController extends Controller /** * Show the form for editing the specified resource. */ - public function edit(string $id) + public function edit(Request $request, string $id): View { if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) { abort(403); } + if (app()->has('SystemProgram')) { + $program = app('SystemProgram'); + } else { + if ($request->has('program_id') && $request->query('program_id')) { + $programId = $request->query('program_id'); + $program = Program::find($programId); + if (!$program) { + abort(400, 'Program tidak ditemukan.'); + } + } else { + abort(400, 'Program tidak ditemukan.'); + } + } + $petani = PetaniCPM::findOrFail($id); $pendidikan = Pendidikan::options(); @@ -128,7 +190,7 @@ class PetaniCPMController extends Controller $komoditas = Komoditas::all(); return view('ekosistem.petani-cpm.edit', compact('petani', 'pendidikan', 'pekerjaan', - 'pernikahan', 'statusKeluarga', 'provinsi', 'komoditas')); + 'pernikahan', 'statusKeluarga', 'provinsi', 'komoditas', 'program')); } /** @@ -140,6 +202,20 @@ class PetaniCPMController extends Controller abort(403); } + if (app()->has('SystemProgram')) { + $program = app('SystemProgram'); + } else { + if ($request->has('program_id') && $request->query('program_id')) { + $programId = $request->query('program_id'); + $program = Program::find($programId); + if (!$program) { + abort(400, 'Program tidak ditemukan.'); + } + } else { + abort(400, 'Program tidak ditemukan.'); + } + } + $petani = PetaniCPM::findOrFail($id); $validatedData = $request->validate([ diff --git a/app/Http/Controllers/Web/Ekosistem/ValueBasisDataController.php b/app/Http/Controllers/Web/Ekosistem/ValueBasisDataController.php index 0048cc8..61b45b7 100644 --- a/app/Http/Controllers/Web/Ekosistem/ValueBasisDataController.php +++ b/app/Http/Controllers/Web/Ekosistem/ValueBasisDataController.php @@ -75,6 +75,23 @@ class ValueBasisDataController extends Controller END ) AS \"{$k->kolom}\" "; + } elseif ($k->tipe == 'enum') { + $selects[] = " + MAX( + CASE + WHEN kolom_id = {$k->id} + THEN ( + SELECT elem->>'label' + FROM ekosistem_basis_data_kolom k, + jsonb_array_elements(k.enum_opsi::jsonb) AS elem + WHERE k.id = kolom_id + AND elem->>'value' = value_enum + LIMIT 1 + ) + ELSE NULL + END + ) AS \"{$k->kolom}\" + "; } else { $selects[] = " MAX( @@ -150,6 +167,7 @@ class ValueBasisDataController extends Controller abort(404, 'Data kolom tidak ditemukan untuk tabel ini.'); } + $program = null; if (app()->has('SystemProgram')) { $program = app('SystemProgram'); } else { @@ -177,6 +195,7 @@ class ValueBasisDataController extends Controller } } $list_relasi = collect($list_relasi); + // dd($kolom->where('tipe', 'enum')->first()?->enum_opsi); return view('ekosistem.value-basis-data.add', compact('tabel', 'kolom', 'program', 'list_relasi')); } @@ -249,12 +268,63 @@ class ValueBasisDataController extends Controller /** * Display the specified resource. */ - public function show(string $id) + public function show(Request $request, string $tabelId, string $id): View { - // + if (!Gate::any(['super_admin', 'admin'])) { + abort(403); + } + + $tabel = TabelBasisData::find($tabelId); + if (!$tabel) { + abort(404, 'Data tabel tidak ditemukan.'); + } + $kolom = KolomBasisData::where('tabel_id', $tabelId)->get(); + if ($kolom->isEmpty()) { + abort(404, 'Data kolom tidak ditemukan untuk tabel ini.'); + } + + if (app()->has('SystemProgram')) { + $program = app('SystemProgram'); + } else { + if ($request->has('program_id') && $request->query('program_id')) { + $programId = $request->query('program_id'); + $program = Program::find($programId); + if (!$program) { + abort(400, 'Program tidak ditemukan.'); + } + } else { + abort(400, 'Program tidak ditemukan.'); + } + } + + $values = ValueBasisData::query() + ->where('tabel_id', $tabelId) + ->where('value_id', $id) + ->where('program_id', $program->id) + ->get(); + if ($values->isEmpty()) { + abort(404, 'Data tidak ditemukan.'); + } + + foreach ($values as $v) { + $k = $kolom->where('id', $v->kolom_id)->first(); + if ($k->tipe == 'foreign_key') { + $v->value_relasi_label = DB::table($k->relasi_tabel)->where($k->relasi_kolom_id, $v->value_relasi)->value($k->relasi_kolom_label); + } else if ($k->tipe == 'enum') { + $opsi = collect($k->enum_opsi); + $found = $opsi->first(function ($item) use ($v) { + return (string) $item['value'] === (string) $v->value_enum; + }); + $v->value_enum_label = $found['label'] ?? null; + } + } + + $value_id = $id; + + return view('ekosistem.value-basis-data.view', compact('tabel', 'kolom', 'program', 'values', 'value_id')); } - public function edit(Request $request, string $tabelId, string $id) + public function edit(Request $request, string $tabelId, string $id): View { if (!Gate::any(['super_admin', 'admin'])) { abort(403); @@ -316,7 +386,7 @@ class ValueBasisDataController extends Controller /** * Update the specified resource in storage. */ - public function update(Request $request, string $tabelId, string $id) + public function update(Request $request, string $tabelId, string $id): RedirectResponse { if (!Gate::any(['super_admin', 'admin'])) { abort(403); @@ -407,7 +477,7 @@ class ValueBasisDataController extends Controller /** * Remove the specified resource from storage. */ - public function destroy(Request $request, string $tabelId, string $id) + public function destroy(Request $request, string $tabelId, string $id): RedirectResponse { if (!Gate::any(['super_admin', 'admin'])) { abort(403); diff --git a/app/Http/Controllers/Web/Master/KeluargaController.php b/app/Http/Controllers/Web/Master/KeluargaController.php index 907fb53..3603af4 100644 --- a/app/Http/Controllers/Web/Master/KeluargaController.php +++ b/app/Http/Controllers/Web/Master/KeluargaController.php @@ -13,6 +13,12 @@ class KeluargaController extends Controller { public function index(Request $request) { + // 1. Ambil data dinamis untuk Summary Cards + $totalKeluarga = Keluarga::count(); + $dokumenLengkap = Keluarga::whereNotNull('file_kk')->count(); + $totalDesa = Keluarga::distinct('desa_kelurahan_id')->count('desa_kelurahan_id'); + + // 2. Query bawaan untuk tabel $query = Keluarga::with(['desakelurahan', 'adat'])->orderBy('created_at', 'desc'); if ($request->search) { @@ -20,48 +26,9 @@ class KeluargaController extends Controller } $keluarga = $query->paginate($request->per_page ?? 10); - return view('master.keluarga.index', compact('keluarga')); - } - - public function create() - { - $provinsi = Provinsi::orderBy('nama', 'asc')->get(); - return view('master.keluarga.add', compact('provinsi')); - } - - public function store(Request $request) - { - $validator = Validator::make($request->all(), [ - 'kk' => ['required', 'string', 'min:16', 'max:16'], - 'desa_kelurahan_id' => ['required'], - 'adat_id' => ['nullable'], - 'file_kk' => ['nullable', 'file', 'mimes:jpeg,jpg,png,pdf', 'max:2048'], - ]); - - if ($validator->fails()) { - return response()->json(['status' => 'error', 'errors' => $validator->errors()], 422); - } - - $pathKk = null; - $fileNameKk = null; - - if ($request->hasFile('file_kk')) { - $file = $request->file('file_kk'); - $fileNameKk = $file->getClientOriginalName(); - $pathKk = $file->store('uploads/keluarga', 'public'); - } - - Keluarga::create([ - 'kk' => $request->kk, - 'desa_kelurahan_id' => $request->desa_kelurahan_id, - 'adat_id' => $request->adat_id, - 'path_kk' => $pathKk, - 'file_kk' => $fileNameKk, - 'created_by' => auth()->id(), - 'updated_by' => auth()->id(), - ]); - - return response()->json(['status' => 'success', 'message' => 'Data Keluarga berhasil ditambahkan.']); + + // 3. Tambahkan variabel card ke dalam compact() + return view('master.keluarga.index', compact('keluarga', 'totalKeluarga', 'dokumenLengkap', 'totalDesa')); } public function show($id) diff --git a/app/Models/Ekosistem/KolomBasisData.php b/app/Models/Ekosistem/KolomBasisData.php index d472ad3..e5c4b4a 100644 --- a/app/Models/Ekosistem/KolomBasisData.php +++ b/app/Models/Ekosistem/KolomBasisData.php @@ -25,10 +25,12 @@ class KolomBasisData extends Model 'relasi_tabel', 'relasi_kolom_id', 'relasi_kolom_label', + 'enum_opsi', ]; protected $casts = [ 'validasi' => 'array', + 'enum_opsi' => 'array', ]; protected static function booted() diff --git a/app/Models/Ekosistem/PetaniCPM.php b/app/Models/Ekosistem/PetaniCPM.php index f5a606f..6706f70 100644 --- a/app/Models/Ekosistem/PetaniCPM.php +++ b/app/Models/Ekosistem/PetaniCPM.php @@ -44,6 +44,7 @@ class PetaniCPM extends Model 'created_by', 'updated_by', 'deleted_by', + 'program_id', ]; protected $casts = [ diff --git a/app/Models/Ekosistem/ValueBasisData.php b/app/Models/Ekosistem/ValueBasisData.php index 56ff78c..a5685fc 100644 --- a/app/Models/Ekosistem/ValueBasisData.php +++ b/app/Models/Ekosistem/ValueBasisData.php @@ -31,6 +31,7 @@ class ValueBasisData extends Model 'updated_by', 'deleted_by', 'value_relasi', + 'value_enum', ]; public function tabel(): BelongsTo diff --git a/database/migrations/2026_05_05_103739_update_basis_data_table.php b/database/migrations/2026_05_05_103739_update_basis_data_table.php index d5048db..cee687b 100644 --- a/database/migrations/2026_05_05_103739_update_basis_data_table.php +++ b/database/migrations/2026_05_05_103739_update_basis_data_table.php @@ -16,6 +16,8 @@ return new class extends Migration $table->string('relasi_tabel')->nullable(); $table->string('relasi_kolom_id')->nullable(); $table->string('relasi_kolom_label')->nullable(); + + $table->jsonb('enum_opsi')->nullable(); }); DB::statement("alter table public.ekosistem_basis_data_kolom drop constraint ekosistem_basis_data_kolom_tipe_check;"); @@ -29,12 +31,18 @@ return new class extends Migration 'date'::character varying, 'datetime'::character varying, 'text'::character varying, - 'foreign_key'::character varying + 'foreign_key'::character varying, + 'enum'::character varying ])::text[]))) "); Schema::table('ekosistem_basis_data_value', function (Blueprint $table) { $table->integer('value_relasi')->nullable(); + $table->string('value_enum')->nullable(); + }); + + Schema::table('ekosistem_petani_cpm', function (Blueprint $table) { + $table->foreignId('program_id')->nullable()->constrained('core_program')->nullOnDelete(); }); } diff --git a/resources/views/ekosistem/kolom-basis-data/add.blade.php b/resources/views/ekosistem/kolom-basis-data/add.blade.php index 235ff25..523edd2 100644 --- a/resources/views/ekosistem/kolom-basis-data/add.blade.php +++ b/resources/views/ekosistem/kolom-basis-data/add.blade.php @@ -35,6 +35,7 @@ +
+