Merge branch 'main' of https://git.probindo.com/Probindo/database-pertani-web
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
enum LayoutForm: string
|
||||
{
|
||||
case ROW = 'form-row';
|
||||
case COLUMN = 'form-column';
|
||||
case VALUE = 'form-value';
|
||||
case SECTION = 'form-section';
|
||||
case HR_LINE = 'form-hr-line';
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return match($this) {
|
||||
self::ROW => 'Row',
|
||||
self::COLUMN => 'Column',
|
||||
self::VALUE => 'Value',
|
||||
self::SECTION => 'Section',
|
||||
self::HR_LINE => 'HR Line',
|
||||
};
|
||||
}
|
||||
|
||||
public static function options(): array
|
||||
{
|
||||
return collect(self::cases())->map(fn ($case) => [
|
||||
'value' => $case->value,
|
||||
'label' => $case->label(),
|
||||
])->toArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Core;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use App\Models\Core\Program;
|
||||
use App\Http\Resources\Core\ProgramResource;
|
||||
|
||||
class ProgramController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
$perPage = $request->query('per_page', 10);
|
||||
$search = $request->query('search', '');
|
||||
|
||||
$program = Program::where('nama', 'like', "%$search%")
|
||||
->paginate($perPage);
|
||||
|
||||
return ProgramResource::collection($program);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id): ProgramResource
|
||||
{
|
||||
$program = Program::findOrFail($id);
|
||||
return new ProgramResource($program);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Ekosistem;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
use App\Models\Ekosistem\TabelBasisData;
|
||||
use App\Models\Ekosistem\KolomBasisData;
|
||||
use App\Models\Core\Program;
|
||||
|
||||
|
||||
class FormBasisDataController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request, string $tabelId): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::with('kolom')
|
||||
->whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})->find($tabelId);
|
||||
if (!$tabel) {
|
||||
abort(404, 'Data tabel tidak ditemukan.');
|
||||
}
|
||||
$kolom = KolomBasisData::where('tabel_id', $tabelId)
|
||||
->where('is_active', true)->get();
|
||||
if ($kolom->isEmpty()) {
|
||||
abort(404, 'Data kolom tidak ditemukan untuk tabel ini.');
|
||||
}
|
||||
|
||||
$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.');
|
||||
}
|
||||
|
||||
$method = $request->query('method', 'add');
|
||||
|
||||
$list_relasi = null;
|
||||
if ($method == 'add' || $method == 'edit') {
|
||||
$list_relasi = [];
|
||||
foreach ($kolom as $k) {
|
||||
if ($k->tipe == 'foreign_key') {
|
||||
$relasi['kolom_id'] = $k->id;
|
||||
try {
|
||||
$options_kolom = DB::table($k->relasi_tabel)->selectRaw($k->relasi_kolom_label . ' as label, ' . $k->relasi_kolom_id . ' as value')->whereNull('deleted_at');
|
||||
$relasi['options'] = $options_kolom->get();
|
||||
$relasi['sql'] = $options_kolom->toSql();
|
||||
} catch (\Throwable $th) {
|
||||
$relasi['options'] = [];
|
||||
}
|
||||
$list_relasi[] = $relasi;
|
||||
}
|
||||
}
|
||||
$list_relasi = collect($list_relasi);
|
||||
} elseif ($method == 'view') {
|
||||
$id = $request->query('value_id');
|
||||
if (!$id) {
|
||||
abort(400, 'value_id query parameter diperlukan untuk view method.');
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
|
||||
$errors = $request->query('errors', null);
|
||||
|
||||
return response()->json($tabel->renderHtml($method, $errors, $list_relasi));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Ekosistem;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
use App\Models\Ekosistem\TabelBasisData;
|
||||
|
||||
use App\Http\Resources\Ekosistem\TabelBasisDataResource;
|
||||
|
||||
class TabelBasisDataController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$perPage = $request->query('per_page', 10);
|
||||
$search = strtolower($request->query('search', ''));
|
||||
|
||||
$tabel = TabelBasisData::with('kolom')
|
||||
->whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})
|
||||
->whereRaw('lower(tabel) LIKE ?', ["%$search%"])
|
||||
->paginate($perPage);
|
||||
|
||||
return TabelBasisDataResource::collection($tabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(Request $request, string $id): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::with('kolom', 'form', 'form.form', 'form.form.form', 'form.form.form.kolom')->findOrFail($id);
|
||||
|
||||
return (new TabelBasisDataResource($tabel))
|
||||
->response();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Ekosistem;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
use App\Models\Ekosistem\TabelBasisData;
|
||||
use App\Models\Ekosistem\KolomBasisData;
|
||||
use App\Models\Ekosistem\ValueBasisData;
|
||||
use App\Models\Core\Program;
|
||||
|
||||
class ValueBasisDataController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request, string $tabelId): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$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.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::with('kolom')
|
||||
->whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})
|
||||
->find($tabelId);
|
||||
if (!$tabel) {
|
||||
abort(404, 'Data tabel tidak ditemukan.');
|
||||
}
|
||||
$kolom = KolomBasisData::where('tabel_id', $tabelId)
|
||||
->where('is_active', true)
|
||||
->when('is_browse', function ($q) {
|
||||
$q->where('is_browse', true);
|
||||
})
|
||||
->orderBy('urutan', 'asc')
|
||||
->get();
|
||||
if ($kolom->isEmpty()) {
|
||||
abort(404, 'Data kolom tidak ditemukan untuk tabel ini.');
|
||||
}
|
||||
|
||||
$selects = [];
|
||||
foreach ($kolom as $k) {
|
||||
if ($k->tipe == 'boolean') {
|
||||
$selects[] = "
|
||||
MAX(
|
||||
CASE
|
||||
WHEN kolom_id = {$k->id}
|
||||
THEN CASE
|
||||
WHEN value_boolean = true THEN 'Ya'
|
||||
WHEN value_boolean = false THEN 'Tidak'
|
||||
ELSE NULL
|
||||
END
|
||||
ELSE NULL
|
||||
END
|
||||
) AS \"{$k->kolom}\"
|
||||
";
|
||||
} elseif ($k->tipe == 'foreign_key') {
|
||||
$selects[] = "
|
||||
MAX(
|
||||
CASE
|
||||
WHEN kolom_id = {$k->id}
|
||||
THEN (select {$k->relasi_kolom_label} from {$k->relasi_tabel} where {$k->relasi_kolom_id} = value_relasi)
|
||||
ELSE NULL
|
||||
END
|
||||
) AS \"{$k->kolom}\"
|
||||
";
|
||||
} elseif ($k->tipe == 'enum') {
|
||||
$selects[] = "
|
||||
MAX(
|
||||
CASE
|
||||
WHEN kolom_id = {$k->id}
|
||||
AND value_enum IS NOT NULL
|
||||
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(
|
||||
CASE
|
||||
WHEN kolom_id = {$k->id}
|
||||
THEN value_{$k->tipe}
|
||||
ELSE NULL
|
||||
END
|
||||
) AS \"{$k->kolom}\"
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
$base = ValueBasisData::query()
|
||||
->join('core_program', 'core_program.id', '=', 'ekosistem_basis_data_value.program_id')
|
||||
->where('tabel_id', $tabelId)
|
||||
->when($program, function ($query) use ($program) {
|
||||
$query->where('program_id', $program->id);
|
||||
})
|
||||
->selectRaw("
|
||||
core_program.id AS program_id,
|
||||
core_program.nama AS program_nama,
|
||||
tabel_id,
|
||||
value_id,
|
||||
" . implode(",\n", $selects) . "
|
||||
")
|
||||
->groupBy('core_program.id', 'core_program.nama', 'tabel_id', 'value_id')
|
||||
->orderBy('value_id', 'asc');
|
||||
|
||||
$values = DB::query()->fromSub($base, 'pivot')
|
||||
->when($search, function ($query) use ($search, $kolom) {
|
||||
$query->where(function ($q) use ($search, $kolom) {
|
||||
foreach ($kolom as $k) {
|
||||
if ($k->tipe == 'text' || $k->tipe == 'varchar') {
|
||||
$q->orWhereRaw("lower({$k->kolom}) LIKE ?", ["%$search%"]);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
->paginate($perPage);
|
||||
|
||||
return response()->json($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request, string $tabelId): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})->find($tabelId);
|
||||
if (!$tabel) {
|
||||
abort(404, 'Data tabel tidak ditemukan.');
|
||||
}
|
||||
$kolom = KolomBasisData::where('tabel_id', $tabelId)
|
||||
->where('is_active', true)->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.');
|
||||
}
|
||||
}
|
||||
|
||||
$validationRules = [];
|
||||
foreach ($kolom as $k) {
|
||||
if ($k->validasi && is_array($k->validasi)) {
|
||||
$validationRules[$k->kolom] = $k->validasi;
|
||||
} else {
|
||||
$validationRules[$k->kolom] = ['nullable'];
|
||||
}
|
||||
}
|
||||
$validated = $request->validate($validationRules);
|
||||
|
||||
DB::transaction(function () use ($program, $tabelId, $validated, $kolom) {
|
||||
$maxId = ValueBasisData::where('tabel_id', $tabelId)
|
||||
->where('program_id', $program->id)
|
||||
->whereNotNull('value_id')
|
||||
->max('value_id');
|
||||
foreach ($kolom as $k) {
|
||||
$values = [
|
||||
'program_id' => $program->id,
|
||||
'tabel_id' => (int)$tabelId,
|
||||
'kolom_id' => $k->id,
|
||||
'value_id' => ($maxId ?? 0) + 1,
|
||||
'created_by' => auth()->id(),
|
||||
'updated_by' => auth()->id(),
|
||||
];
|
||||
if ($k->tipe == 'foreign_key') {
|
||||
$values['value_relasi'] = $validated[$k->kolom] ?? null;
|
||||
} else {
|
||||
$values['value_' . $k->tipe] = $validated[$k->kolom] ?? null;
|
||||
}
|
||||
|
||||
ValueBasisData::create($values);
|
||||
}
|
||||
});
|
||||
|
||||
return response()->json(['message' => 'Data berhasil disimpan.']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $tabelId, string $id): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})->find($tabelId);
|
||||
if (!$tabel) {
|
||||
abort(404, 'Data tabel tidak ditemukan.');
|
||||
}
|
||||
$kolom = KolomBasisData::where('tabel_id', $tabelId)
|
||||
->where('is_active', true)->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.');
|
||||
}
|
||||
|
||||
$validationRules = [];
|
||||
foreach ($kolom as $k) {
|
||||
if ($k->validasi && is_array($k->validasi)) {
|
||||
$validationRules[$k->kolom] = $k->validasi;
|
||||
} else {
|
||||
$validationRules[$k->kolom] = ['nullable'];
|
||||
}
|
||||
}
|
||||
$validated = $request->validate($validationRules);
|
||||
|
||||
DB::transaction(function () use ($program, $tabelId, $validated, $kolom, $id, $values) {
|
||||
foreach ($validated as $kol => $val) {
|
||||
$k = $kolom->where('kolom', $kol)->first();
|
||||
if (!$k) {
|
||||
continue;
|
||||
}
|
||||
$v = $values->where('kolom_id', $k->id)->first();
|
||||
if (!$v) {
|
||||
$vals = [
|
||||
'program_id' => $program->id,
|
||||
'tabel_id' => (int)$tabelId,
|
||||
'kolom_id' => $k->id,
|
||||
'value_id' => $id,
|
||||
'created_by' => auth()->id(),
|
||||
'updated_by' => auth()->id(),
|
||||
];
|
||||
if ($k->tipe == 'foreign_key') {
|
||||
$vals['value_relasi'] = $validated[$k->kolom] ?? null;
|
||||
} else {
|
||||
$vals['value_' . $k->tipe] = $validated[$k->kolom] ?? null;
|
||||
}
|
||||
ValueBasisData::create($vals);
|
||||
} else {
|
||||
$v->update([
|
||||
'value_' . ($k->tipe == 'foreign_key' ? 'relasi' : $k->tipe) => $val,
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return response()->json(['message' => 'Data berhasil diperbarui.']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(Request $request, string $tabelId, string $id): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})->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.');
|
||||
}
|
||||
|
||||
ValueBasisData::query()
|
||||
->where('tabel_id', $tabelId)
|
||||
->where('value_id', $id)
|
||||
->where('program_id', $program->id)
|
||||
->delete();
|
||||
|
||||
return response()->json(['message' => 'Data berhasil dihapus.']);
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -1,16 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Konfigurasi;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Profile;
|
||||
|
||||
use App\Http\Resources\UserResource;
|
||||
|
||||
class AuthController extends Controller
|
||||
@@ -45,20 +43,25 @@ class AuthController extends Controller
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'email', 'max:255', 'unique:users'],
|
||||
'password' => ['required', 'string', 'min:8', 'confirmed'],
|
||||
'username' => ['required', 'string', 'max:255'],
|
||||
'role' => ['string'],
|
||||
'uid' => ['required','string', 'unique:users'],
|
||||
]);
|
||||
|
||||
$user = User::create([
|
||||
'name' => $credentials['name'],
|
||||
'email' => $credentials['email'],
|
||||
'password' => Hash::make($credentials['password']),
|
||||
'username' => $credentials['username'],
|
||||
'role' => $credentials['role'],
|
||||
'uid' => $credentials['uid'],
|
||||
]);
|
||||
|
||||
$profile = Profile::create([
|
||||
'nama' => $credentials['name'],
|
||||
'email' => $credentials['email'],
|
||||
'role' => $credentials['role'],
|
||||
'user_uid' => $credentials['uid'],
|
||||
'user_id' => $user->id,
|
||||
'created_by' => $user->id,
|
||||
'updated_by' => $user->id,
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Master;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Master;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Master;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\Http\Resources\Pertanian\JenisKomoditasResource;
|
||||
use App\Models\Pertanian\JenisKomoditas;
|
||||
|
||||
class JenisKomoditasController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
if (!Gate::any(['petani', 'fasilitator', 'super_admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$size = $request->integer('size') ?: 10;
|
||||
|
||||
$jenisKomoditasList = JenisKomoditas::when($request->search, function ($q, $search) {
|
||||
$search = strtolower($search);
|
||||
$q->whereRaw('lower(nama) like ?', ["%{$search}%"]);
|
||||
})
|
||||
->when($request->kode, fn($q, $v) => $q->where('kode', $v));
|
||||
|
||||
if ($request->filled('sort')) {
|
||||
$dir = str_starts_with($request->sort, '-') ? 'desc' : 'asc';
|
||||
$column = ltrim($request->sort, '-');
|
||||
|
||||
$allowed = ['id', 'nama', 'kode'];
|
||||
|
||||
if (in_array($column, $allowed)) {
|
||||
$jenisKomoditasList->orderBy($column, $dir);
|
||||
}
|
||||
} else {
|
||||
$jenisKomoditasList->orderBy('nama', 'asc');
|
||||
}
|
||||
|
||||
$jenisKomoditasList = $jenisKomoditasList->paginate($size);
|
||||
|
||||
return JenisKomoditasResource::collection($jenisKomoditasList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['petani', 'fasilitator', 'super_admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'nama' => ['required', 'string', 'max:255'],
|
||||
'kode' => ['required', 'string', 'max:50', 'unique:jenis_komoditas,kode'],
|
||||
'keterangan' => ['nullable', 'string'],
|
||||
]);
|
||||
|
||||
$jenisKomoditas = JenisKomoditas::create($validated);
|
||||
|
||||
return (new JenisKomoditasResource($jenisKomoditas))
|
||||
->response()
|
||||
->setStatusCode(201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['petani', 'fasilitator', 'super_admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$jenisKomoditas = JenisKomoditas::findOrFail($id);
|
||||
|
||||
return (new JenisKomoditasResource($jenisKomoditas))->response();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['petani', 'fasilitator', 'super_admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$jenisKomoditas = JenisKomoditas::findOrFail($id);
|
||||
|
||||
$validated = $request->validate([
|
||||
'nama' => ['required', 'string', 'max:255'],
|
||||
'kode' => ['required', 'string', 'max:50', Rule::unique('jenis_komoditas', 'kode')->ignore($jenisKomoditas->id)],
|
||||
'keterangan' => ['nullable', 'string'],
|
||||
]);
|
||||
|
||||
$jenisKomoditas->update($validated);
|
||||
|
||||
return (new JenisKomoditasResource($jenisKomoditas))->response();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['petani', 'fasilitator', 'super_admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$jenisKomoditas = JenisKomoditas::findOrFail($id);
|
||||
$jenisKomoditas->delete();
|
||||
|
||||
return response()->json(null, 204);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Master;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Master;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Master;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Master;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Produktivitas;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Produktivitas;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Map\InsLahan;
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Produktivitas;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Map\Inspeksi;
|
||||
+6
-2
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Produktivitas;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -87,7 +87,10 @@ class LahanController extends Controller
|
||||
if (!$profile) {
|
||||
abort(404, 'Profile tidak ditemukan');
|
||||
}
|
||||
|
||||
if ($request->has('profile_id')) {
|
||||
$request->merge(['profile_id' => (int) $request->profile_id]);
|
||||
}
|
||||
|
||||
$profileRule = $user->role === 'fasilitator' ? ['required', 'numeric', 'exists:profiles,id'] : ['nullable'];
|
||||
|
||||
$validated = $request->validate([
|
||||
@@ -97,6 +100,7 @@ class LahanController extends Controller
|
||||
'path' => ['nullable', 'array'],
|
||||
'path.*' => ['array'],
|
||||
'luas_lahan' => ['nullable', 'numeric'],
|
||||
'uid' => ['required', 'string'],
|
||||
'profile_id' => $profileRule,
|
||||
]);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Produktivitas;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Produktivitas;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
namespace App\Http\Controllers\Api\Produktivitas;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Produktivitas;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\Http\Resources\Pertanian\TanamanResource;
|
||||
use App\Models\Pertanian\Tanaman;
|
||||
use App\Enums\KondisiTanaman;
|
||||
|
||||
class TanamanController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
$user = Auth::user();
|
||||
$profile = $user->profile;
|
||||
$profileId = $user->role === 'petani' ? $profile->id : $request->profile_id;
|
||||
|
||||
$size = $request->integer('size') ?: 10;
|
||||
|
||||
$tanamanList = Tanaman::when($request->search, function ($q, $search) {
|
||||
$search = strtolower($search);
|
||||
$q->whereRaw('lower(nama) like ?', ["%{$search}%"]);
|
||||
})
|
||||
->when($profileId, fn($q,$v) => $q->where('profile_id',$v))
|
||||
->when($request->status_kepemilikan, fn($q,$v) => $q->where('status_kepemilikan',$v))
|
||||
->when($request->lahan_id, fn($q,$v) => $q->where('lahan_id',$v))
|
||||
->when($request->komoditas_id, fn($q,$v) => $q->where('komoditas_id',$v))
|
||||
->when($request->desa_kelurahan_id, fn($q,$v) =>
|
||||
$q->whereHas('lahan', fn($k)
|
||||
=> $k->where('desa_kelurahan_id',$v)
|
||||
)
|
||||
)
|
||||
->when($request->kecamatan_id, fn ($q, $v) =>
|
||||
$q->whereHas('lahan.desaKelurahan', fn ($k) =>
|
||||
$k->where('kecamatan_id', $v)
|
||||
)
|
||||
)
|
||||
->when($request->kabupaten_kota_id, fn ($q, $v) =>
|
||||
$q->whereHas('lahan.desaKelurahan.kecamatan', fn ($k) =>
|
||||
$k->where('kabupaten_kota_id', $v)
|
||||
)
|
||||
)
|
||||
->when($request->provinsi_id, fn ($q, $v) =>
|
||||
$q->whereHas('lahan.desaKelurahan.kecamatan.kabupatenkota', fn ($k) =>
|
||||
$k->where('provinsi_id', $v)
|
||||
)
|
||||
);
|
||||
|
||||
if ($request->filled('sort')) {
|
||||
$dir = str_starts_with($request->sort, '-') ? 'desc' : 'asc';
|
||||
$column = ltrim($request->sort, '-');
|
||||
|
||||
$allowed = ['id', 'nama'];
|
||||
|
||||
if (in_array($column, $allowed)) {
|
||||
$tanamanList->orderBy($column, $dir);
|
||||
}
|
||||
} else {
|
||||
$tanamanList->orderBy('nama', 'asc');
|
||||
}
|
||||
|
||||
$tanamanList = $tanamanList->paginate($size);
|
||||
|
||||
return TanamanResource::collection($tanamanList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$profile = $user->profile;
|
||||
$profileId = $user->role === 'petani' ? $profile->id : $request->profile_id;
|
||||
|
||||
$request->merge([
|
||||
'komoditas_id' => $request->input('komoditas.id') ?? $request->input('komoditas_id'),
|
||||
'lahan_id' => $request->input('lahan.id') ?? $request->input('lahan_id'),
|
||||
'profile_id' => $profileId,
|
||||
]);
|
||||
|
||||
$validated = $request->validate([
|
||||
'nama' => ['required', 'string', 'max:255'],
|
||||
'komoditas_id' => ['required', 'exists:master_komoditas,id'],
|
||||
'lahan_id' => [
|
||||
'required',
|
||||
Rule::exists('map_lahan', 'id')->where(function ($query) use ($profileId) {
|
||||
$query->where('profile_id', $profileId)
|
||||
->whereNull('deleted_at');
|
||||
}),
|
||||
],
|
||||
'latitude' => ['nullable', 'numeric', 'between:-90,90', 'required_with:longitude'],
|
||||
'longitude' => ['nullable', 'numeric', 'between:-180,180', 'required_with:latitude'],
|
||||
'kondisi_tanaman' => ['nullable', 'string', new Enum(KondisiTanaman::class)],
|
||||
]);
|
||||
|
||||
$tanaman = Tanaman::create([
|
||||
...$validated,
|
||||
'profile_id' => $profile->id,
|
||||
]);
|
||||
|
||||
return (new TanamanResource($tanaman))
|
||||
->response()
|
||||
->setStatusCode(201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$tanaman = Tanaman::findOrFail($id);
|
||||
if ($tanaman->profile_id !== Auth::user()->profile->id) {
|
||||
return response()->json(['message' => 'Unauthorized'], 403);
|
||||
}
|
||||
|
||||
return (new TanamanResource($tanaman))->response();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
$tanaman = Tanaman::findOrFail($id);
|
||||
if ($tanaman->profile_id !== Auth::user()->profile->id) {
|
||||
return response()->json(['message' => 'Unauthorized'], 403);
|
||||
}
|
||||
|
||||
$profile = Auth::user()->profile;
|
||||
|
||||
$validated = $request->validate([
|
||||
'nama' => ['required', 'string', 'max:255'],
|
||||
'komoditas_id' => ['required', 'exists:master_komoditas,id'],
|
||||
'lahan_id' => [
|
||||
'required',
|
||||
Rule::exists('map_lahan', 'id')->where(function ($query) use ($profile) {
|
||||
$query->where('profile_id', $profile->id)
|
||||
->whereNull('deleted_at');
|
||||
}),
|
||||
],
|
||||
'latitude' => ['nullable', 'numeric', 'between:-90,90', 'required_with:longitude'],
|
||||
'longitude' => ['nullable', 'numeric', 'between:-180,180', 'required_with:latitude'],
|
||||
'kondisi_tanaman' => ['nullable', 'string', new Enum(KondisiTanaman::class)],
|
||||
]);
|
||||
|
||||
$tanaman->update($validated);
|
||||
|
||||
return (new TanamanResource($tanaman))->response();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
$tanaman = Tanaman::findOrFail($id);
|
||||
if ($tanaman->profile_id !== Auth::user()->profile->id) {
|
||||
return response()->json(['message' => 'Unauthorized'], 403);
|
||||
}
|
||||
|
||||
$tanaman->delete();
|
||||
|
||||
return response()->json(null, 204);
|
||||
}
|
||||
}
|
||||
@@ -94,26 +94,41 @@ class TanamanController extends Controller
|
||||
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
$profile = Auth::user()->profile;
|
||||
|
||||
$user = Auth::user();
|
||||
$profile = $user->profile;
|
||||
$profileId = $user->role === 'petani' ? $profile->id : $request->profile_id;
|
||||
|
||||
$request->merge([
|
||||
'komoditas_id' => $request->input('komoditas.id') ?? $request->input('komoditas_id'),
|
||||
'lahan_id' => $request->input('lahan.id') ?? $request->input('lahan_id'),
|
||||
'profile_id' => $profileId,
|
||||
]);
|
||||
|
||||
$validated = $request->validate([
|
||||
'nama' => ['required', 'string', 'max:255'],
|
||||
'komoditas_id' => ['required', 'exists:master_komoditas,id'],
|
||||
'lahan_id' => [
|
||||
'required',
|
||||
Rule::exists('map_lahan', 'id')->where(function ($query) use ($profile) {
|
||||
$query->where('profile_id', $profile->id)
|
||||
Rule::exists('map_lahan', 'id')->where(function ($query) use ($profileId) {
|
||||
$query->where('profile_id', $profileId)
|
||||
->whereNull('deleted_at');
|
||||
}),
|
||||
],
|
||||
'latitude' => ['nullable', 'numeric', 'between:-90,90', 'required_with:longitude'],
|
||||
'longitude' => ['nullable', 'numeric', 'between:-180,180', 'required_with:latitude'],
|
||||
'longitude' => ['nullable ', 'numeric', 'between:-180,180', 'required_with:latitude'],
|
||||
'kondisi_tanaman' => ['nullable', 'string', new Enum(KondisiTanaman::class)],
|
||||
'uid' => ['required', 'string'],
|
||||
'jenis_komoditas_id' => ['nullable', 'exists:jenis_komoditas,id'],
|
||||
'komoditas_kode' => ['nullable', 'string', 'max:255'],
|
||||
]);
|
||||
|
||||
$tanaman = Tanaman::create([
|
||||
...$validated,
|
||||
'profile_id' => $profile->id,
|
||||
'uid' => $validated['uid'] ?? $request->input('uid'),
|
||||
'komoditas_kode' => $validated['komoditas_kode'] ?? $request->input('komoditas_kode'),
|
||||
'jenis_komoditas_id' => $validated['jenis_komoditas_id'] ?? $request->input('jenis_komoditas_id'),
|
||||
]);
|
||||
|
||||
return (new TanamanResource($tanaman))
|
||||
|
||||
@@ -4,13 +4,8 @@ namespace App\Http\Controllers\Web\Dashboard;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Profile;
|
||||
use App\Models\Wilayah\Provinsi;
|
||||
use App\Models\wilayah\KabupatenKota;
|
||||
use App\Models\Wilayah\Kecamatan;
|
||||
use App\Models\Wilayah\DesaKelurahan;
|
||||
use App\Models\Pertanian\Lahan;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
class SummaryController extends Controller
|
||||
{
|
||||
public function index()
|
||||
@@ -21,128 +16,4 @@ class SummaryController extends Controller
|
||||
$title = 'Summary Dashboard';
|
||||
return view('dashboard.summary', compact('title'));
|
||||
}
|
||||
|
||||
public function produktivitasBackup(Request $request)
|
||||
{
|
||||
if (!Gate::allows('super_admin') && !Gate::allows('admin')) {
|
||||
abort(403);
|
||||
}
|
||||
$title = 'Produktivitas Dashboard';
|
||||
$luasTotal = Lahan::whereNotNull('path')->sum('luas_lahan');
|
||||
$totalpetani = Profile::where('role', 'petani')->count();
|
||||
$totallahan = Lahan::whereNotNull('path')->count();
|
||||
|
||||
$petaniList = Profile::where('role', 'petani')
|
||||
->with(['lahan.tanaman.komoditas', 'desaKelurahan'])
|
||||
->paginate(20);
|
||||
|
||||
$allLahan = Lahan::whereNotNull('path')
|
||||
->with(['profile', 'tanaman.komoditas', 'desaKelurahan.kecamatan.kabupatenKota.provinsi'])
|
||||
->get()
|
||||
->map(function($lahan) {
|
||||
return [
|
||||
'id' => $lahan->id,
|
||||
'polygon' => $lahan->path,
|
||||
'nama_petani' => $lahan->profile->nama ?? 'N/A',
|
||||
'luas' => $lahan->luas_lahan,
|
||||
'tanaman' => $lahan->tanaman->map(fn($t) => $t->komoditas->nama ?? null)->filter()->unique()->values()
|
||||
];
|
||||
});
|
||||
|
||||
return view('dashboard.produktivitas', compact('title', 'petaniList', 'allLahan', 'totalpetani', 'totallahan', 'luasTotal'));
|
||||
}
|
||||
|
||||
public function produktivitas(Request $request)
|
||||
{
|
||||
if (!Gate::allows('super_admin') && !Gate::allows('admin')) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$title = 'Produktivitas Dashboard';
|
||||
$luasTotal = Lahan::whereNotNull('path')->sum('luas_lahan');
|
||||
$totalpetani = Profile::where('role', 'petani')->count();
|
||||
$totallahan = Lahan::whereNotNull('path')->count();
|
||||
|
||||
$petaniList = Profile::where('role', 'petani')
|
||||
->with(['lahan.tanaman.komoditas', 'desaKelurahan'])
|
||||
->paginate(20);
|
||||
|
||||
$allLahan = Lahan::whereNotNull('path')
|
||||
->with(['profile', 'tanaman.komoditas', 'desaKelurahan.kecamatan.kabupatenKota.provinsi'])
|
||||
->get();
|
||||
|
||||
// Penampung data per level (menggunakan ID sebagai key agar unique)
|
||||
$geoProvinsi = [];
|
||||
$geoKabupaten = [];
|
||||
$geoKecamatan = [];
|
||||
$geoDesa = [];
|
||||
$geoLahan = [];
|
||||
|
||||
foreach ($allLahan as $lahan) {
|
||||
$desa = $lahan->desaKelurahan;
|
||||
$kec = $desa ? $desa->kecamatan : null;
|
||||
$kab = $kec ? $kec->kabupatenKota : null;
|
||||
$prov = $kab ? $kab->provinsi : null;
|
||||
|
||||
// --- Akumulasi Provinsi ---
|
||||
if ($prov && $prov->path) {
|
||||
if (!isset($geoProvinsi[$prov->id])) {
|
||||
$geoProvinsi[$prov->id] = ['id' => $prov->id, 'nama' => $prov->nama, 'polygon' => $prov->path, 'total_lahan' => 0, 'total_luas' => 0];
|
||||
}
|
||||
$geoProvinsi[$prov->id]['total_lahan']++;
|
||||
$geoProvinsi[$prov->id]['total_luas'] += $lahan->luas_lahan;
|
||||
}
|
||||
|
||||
// --- Akumulasi Kabupaten ---
|
||||
if ($kab && $kab->path) {
|
||||
if (!isset($geoKabupaten[$kab->id])) {
|
||||
$geoKabupaten[$kab->id] = ['id' => $kab->id, 'parent_id' => $prov->id ?? null, 'nama' => $kab->nama, 'polygon' => $kab->path, 'total_lahan' => 0, 'total_luas' => 0];
|
||||
}
|
||||
$geoKabupaten[$kab->id]['total_lahan']++;
|
||||
$geoKabupaten[$kab->id]['total_luas'] += $lahan->luas_lahan;
|
||||
}
|
||||
|
||||
// --- Akumulasi Kecamatan ---
|
||||
if ($kec && $kec->path) {
|
||||
if (!isset($geoKecamatan[$kec->id])) {
|
||||
$geoKecamatan[$kec->id] = ['id' => $kec->id, 'parent_id' => $kab->id ?? null, 'nama' => $kec->nama, 'polygon' => $kec->path, 'total_lahan' => 0, 'total_luas' => 0];
|
||||
}
|
||||
$geoKecamatan[$kec->id]['total_lahan']++;
|
||||
$geoKecamatan[$kec->id]['total_luas'] += $lahan->luas_lahan;
|
||||
}
|
||||
|
||||
// --- Akumulasi Desa ---
|
||||
if ($desa && $desa->path) {
|
||||
if (!isset($geoDesa[$desa->id])) {
|
||||
$geoDesa[$desa->id] = ['id' => $desa->id, 'parent_id' => $kec->id ?? null, 'nama' => $desa->nama, 'polygon' => $desa->path, 'total_lahan' => 0, 'total_luas' => 0];
|
||||
}
|
||||
$geoDesa[$desa->id]['total_lahan']++;
|
||||
$geoDesa[$desa->id]['total_luas'] += $lahan->luas_lahan;
|
||||
}
|
||||
|
||||
// Data Lahan Tetap
|
||||
$geoLahan[] = [
|
||||
'id' => $lahan->id,
|
||||
'parent_id' => $desa->id ?? null,
|
||||
'polygon' => $lahan->path,
|
||||
'nama_petani' => $lahan->profile->nama ?? 'N/A',
|
||||
'luas' => $lahan->luas_lahan,
|
||||
'tanaman' => $lahan->tanaman->map(fn($t) => $t->komoditas->nama ?? null)->filter()->unique()->values()
|
||||
];
|
||||
}
|
||||
|
||||
return view('dashboard.produktivitas', [
|
||||
'title' => $title,
|
||||
'petaniList' => $petaniList,
|
||||
'totalpetani' => $totalpetani,
|
||||
'totallahan' => $totallahan,
|
||||
'luasTotal' => $luasTotal,
|
||||
// Reset key array agar menjadi format list normal untuk JSON
|
||||
'geoProvinsi' => array_values($geoProvinsi),
|
||||
'geoKabupaten' => array_values($geoKabupaten),
|
||||
'geoKecamatan' => array_values($geoKecamatan),
|
||||
'geoDesa' => array_values($geoDesa),
|
||||
'geoLahan' => $geoLahan
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Ekosistem;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
use App\Models\Ekosistem\TabelBasisData;
|
||||
use App\Models\Ekosistem\FormBasisData;
|
||||
use App\Enums\LayoutForm;
|
||||
|
||||
class FormBasisDataController extends Controller
|
||||
{
|
||||
public function index(Request $request, string $tabelId): View
|
||||
{
|
||||
Gate::authorize('super_admin');
|
||||
|
||||
$tabel = TabelBasisData::find($tabelId);
|
||||
if (!$tabel) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data tabel tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$listEnum = LayoutForm::options();
|
||||
|
||||
$tab = $request->tab ?? 'form';
|
||||
$tabel->state = 'preview';
|
||||
|
||||
return view('ekosistem.form-basis-data.index', compact('tabel', 'listEnum', 'tab'));
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function store(Request $request, string $tabelId): JsonResponse
|
||||
{
|
||||
Gate::authorize('super_admin');
|
||||
|
||||
$tabel = TabelBasisData::find($tabelId);
|
||||
if (!$tabel) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data tabel tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'parent_id' => ['nullable', 'exists:ekosistem_basis_data_form,id'],
|
||||
'tipe' => ['required', Rule::enum(LayoutForm::class)],
|
||||
'column_width' => [
|
||||
Rule::requiredIf($request->tipe === LayoutForm::COLUMN->value),
|
||||
'nullable', 'integer', 'min:1', 'max:12'],
|
||||
'kolom_id' => [
|
||||
Rule::requiredIf($request->tipe === LayoutForm::VALUE->value),
|
||||
'nullable', 'exists:ekosistem_basis_data_kolom,id'],
|
||||
'section_label' => [
|
||||
Rule::requiredIf($request->tipe === LayoutForm::SECTION->value),
|
||||
'nullable', 'string'],
|
||||
]);
|
||||
|
||||
FormBasisData::create([...$validated,
|
||||
'tabel_id' => $tabelId,
|
||||
'created_by' => auth()->user()->id,
|
||||
'updated_by' => auth()->user()->id
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Form basis data berhasil ditambahkan.'
|
||||
], 201);
|
||||
}
|
||||
|
||||
public function show(string $tabelId, string $id): JsonResponse
|
||||
{
|
||||
Gate::authorize('super_admin');
|
||||
|
||||
$form = FormBasisData::where('tabel_id', $tabelId)->find($id);
|
||||
if (!$form) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data formulir basis data tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $form
|
||||
], 200);
|
||||
}
|
||||
|
||||
public function edit(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function update(Request $request, string $tabelId, string $id)
|
||||
{
|
||||
Gate::authorize('super_admin');
|
||||
|
||||
$form = FormBasisData::where('tabel_id', $tabelId)->find($id);
|
||||
if (!$form) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data formulir basis data tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'parent_id' => ['nullable', 'exists:ekosistem_basis_data_form,id'],
|
||||
'tipe' => ['required', Rule::enum(LayoutForm::class)],
|
||||
'column_width' => [
|
||||
Rule::requiredIf($request->tipe === LayoutForm::COLUMN->value),
|
||||
'nullable', 'integer', 'min:1', 'max:12'],
|
||||
'kolom_id' => [
|
||||
Rule::requiredIf($request->tipe === LayoutForm::VALUE->value),
|
||||
'nullable', 'exists:ekosistem_basis_data_kolom,id'],
|
||||
'section_label' => [
|
||||
Rule::requiredIf($request->tipe === LayoutForm::SECTION->value),
|
||||
'nullable', 'string'],
|
||||
]);
|
||||
|
||||
$form->update([...$validated,
|
||||
'updated_by' => auth()->user()->id
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Form basis data berhasil diubah.'
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(string $tabelId, string $id): JsonResponse
|
||||
{
|
||||
Gate::authorize('super_admin');
|
||||
|
||||
$form = FormBasisData::where('tabel_id', $tabelId)->find($id);
|
||||
if (!$form) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data form basis data tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
if ($form->form->count() > 0) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Tidak dapat menghapus formulir basis data yang memiliki formulir.'
|
||||
], 400);
|
||||
}
|
||||
$form->update([
|
||||
'deleted_by' => auth()->user()->id
|
||||
]);
|
||||
$form->delete();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Form basis data berhasil dihapus.'
|
||||
], 200);
|
||||
}
|
||||
|
||||
public function generate(Request $request, string $tabelId): RedirectResponse
|
||||
{
|
||||
Gate::authorize('super_admin');
|
||||
|
||||
$tabel = TabelBasisData::find($tabelId);
|
||||
if (!$tabel) {
|
||||
return redirect()->route('tabel.formulir.index', $tabelId)->with('error', 'Tabel basis data tidak ditemukan.');
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($tabel) {
|
||||
|
||||
FormBasisData::where('tabel_id', $tabel->id)->delete();
|
||||
|
||||
FormBasisData::create([
|
||||
'tabel_id' => $tabel->id,
|
||||
'tipe' => LayoutForm::SECTION,
|
||||
'section_label' => $tabel->label,
|
||||
'created_by' => auth()->user()->id,
|
||||
'updated_by' => auth()->user()->id
|
||||
]);
|
||||
|
||||
FormBasisData::create([
|
||||
'tabel_id' => $tabel->id,
|
||||
'tipe' => LayoutForm::HR_LINE,
|
||||
'created_by' => auth()->user()->id,
|
||||
'updated_by' => auth()->user()->id
|
||||
]);
|
||||
|
||||
$chunks = $tabel->kolom->chunk(4);
|
||||
|
||||
foreach ($chunks as $chunk) {
|
||||
|
||||
$row = FormBasisData::create([
|
||||
'tabel_id' => $tabel->id,
|
||||
'tipe' => LayoutForm::ROW,
|
||||
'created_by' => auth()->user()->id,
|
||||
'updated_by' => auth()->user()->id
|
||||
]);
|
||||
|
||||
foreach ($chunk as $kolom) {
|
||||
$column = FormBasisData::create([
|
||||
'tabel_id' => $tabel->id,
|
||||
'tipe' => LayoutForm::COLUMN,
|
||||
'column_width' => 3,
|
||||
'parent_id' => $row->id,
|
||||
'created_by' => auth()->user()->id,
|
||||
'updated_by' => auth()->user()->id
|
||||
]);
|
||||
|
||||
FormBasisData::create([
|
||||
'tabel_id' => $tabel->id,
|
||||
'tipe' => LayoutForm::VALUE,
|
||||
'parent_id' => $column->id,
|
||||
'kolom_id' => $kolom->id,
|
||||
'created_by' => auth()->user()->id,
|
||||
'updated_by' => auth()->user()->id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return redirect()->route('tabel.formulir.index', $tabelId)->with('success', 'Formulir berhasil dibuat.');
|
||||
}
|
||||
|
||||
public function moveUp(Request $request, string $tabelId, string $id): JsonResponse
|
||||
{
|
||||
Gate::authorize('super_admin');
|
||||
|
||||
$current = FormBasisData::where('tabel_id', $tabelId)->find($id);
|
||||
if (!$current) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data formulir tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$prev = FormBasisData::where('tabel_id', $tabelId)
|
||||
->where('urutan', '<', $current->urutan)
|
||||
->where('parent_id', $current->parent_id)
|
||||
->orderBy('urutan', 'desc')
|
||||
->first();
|
||||
|
||||
if ($prev) {
|
||||
// swap
|
||||
[$current->urutan, $prev->urutan] = [$prev->urutan, $current->urutan];
|
||||
$current->save();
|
||||
$prev->save();
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Formulir basis data berhasil diperbarui.'
|
||||
], 200);
|
||||
}
|
||||
|
||||
public function moveDown(Request $request, string $tabelId, string $id): JsonResponse
|
||||
{
|
||||
Gate::authorize('super_admin');
|
||||
|
||||
$current = FormBasisData::where('tabel_id', $tabelId)->find($id);
|
||||
if (!$current) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data formulir tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$next = FormBasisData::where('tabel_id', $tabelId)
|
||||
->where('urutan', '>', $current->urutan)
|
||||
->where('parent_id', $current->parent_id)
|
||||
->orderBy('urutan', 'asc')
|
||||
->first();
|
||||
|
||||
if ($next) {
|
||||
// swap
|
||||
[$current->urutan, $next->urutan] = [$next->urutan, $current->urutan];
|
||||
$current->save();
|
||||
$next->save();
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Formulir basis data berhasil diperbarui.'
|
||||
], 200);
|
||||
}
|
||||
}
|
||||
@@ -145,6 +145,13 @@ class KolomBasisDataController extends Controller
|
||||
'is_browse' => ['nullable', 'boolean'],
|
||||
]);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
$kolom->update([...$validated,
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
@@ -188,7 +195,7 @@ class KolomBasisDataController extends Controller
|
||||
], 404);
|
||||
}
|
||||
|
||||
$prev = KolomBasisData::where('tabel_id', $current->tabel_id)
|
||||
$prev = KolomBasisData::where('tabel_id', $tabelId)
|
||||
->where('urutan', '<', $current->urutan)
|
||||
->orderBy('urutan', 'desc')
|
||||
->first();
|
||||
@@ -218,7 +225,7 @@ class KolomBasisDataController extends Controller
|
||||
], 404);
|
||||
}
|
||||
|
||||
$next = KolomBasisData::where('tabel_id', $current->tabel_id)
|
||||
$next = KolomBasisData::where('tabel_id', $tabelId)
|
||||
->where('urutan', '>', $current->urutan)
|
||||
->orderBy('urutan', 'asc')
|
||||
->first();
|
||||
|
||||
@@ -8,6 +8,13 @@ use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\Models\Ekosistem\TabelBasisData;
|
||||
use App\Models\Ekosistem\KolomBasisData;
|
||||
@@ -17,9 +24,16 @@ use App\Models\Core\Program;
|
||||
|
||||
class ValueBasisDataController extends Controller
|
||||
{
|
||||
private $tableModelClassMap = [
|
||||
'master_provinsi' => \App\Models\Wilayah\Provinsi::class,
|
||||
'master_kabupaten_kota' => \App\Models\Wilayah\KabupatenKota::class,
|
||||
'master_kecamatan' => \App\Models\Wilayah\Kecamatan::class,
|
||||
'master_desa_kelurahan' => \App\Models\Wilayah\DesaKelurahan::class,
|
||||
];
|
||||
|
||||
public function index(Request $request, string $tabelId): View
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
@@ -40,13 +54,15 @@ class ValueBasisDataController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::find($tabelId);
|
||||
$tabel = TabelBasisData::with('kolom')
|
||||
->whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})->find($tabelId);
|
||||
if (!$tabel) {
|
||||
abort(404, 'Data tabel tidak ditemukan.');
|
||||
}
|
||||
$kolom = KolomBasisData::where('tabel_id', $tabelId)
|
||||
$kolom = KolomBasisData::where('tabel_id', $tabel->id)
|
||||
->where('is_active', true)
|
||||
->where('is_browse', true)
|
||||
->get();
|
||||
if ($kolom->isEmpty()) {
|
||||
abort(404, 'Data kolom tidak ditemukan untuk tabel ini.');
|
||||
@@ -83,6 +99,7 @@ class ValueBasisDataController extends Controller
|
||||
MAX(
|
||||
CASE
|
||||
WHEN kolom_id = {$k->id}
|
||||
AND value_enum IS NOT NULL
|
||||
THEN (
|
||||
SELECT elem->>'label'
|
||||
FROM ekosistem_basis_data_kolom k,
|
||||
@@ -160,8 +177,11 @@ class ValueBasisDataController extends Controller
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::find($tabelId);
|
||||
|
||||
$tabel = TabelBasisData::with('kolom')
|
||||
->whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})->find($tabelId);
|
||||
if (!$tabel) {
|
||||
abort(404, 'Data tabel tidak ditemukan.');
|
||||
}
|
||||
@@ -189,7 +209,12 @@ class ValueBasisDataController extends Controller
|
||||
if ($k->tipe == 'foreign_key') {
|
||||
$relasi['kolom_id'] = $k->id;
|
||||
try {
|
||||
$options_kolom = DB::table($k->relasi_tabel)->selectRaw($k->relasi_kolom_label . ' as label, ' . $k->relasi_kolom_id . ' as value')->whereNull('deleted_at');
|
||||
$modelClass = Arr::get($this->tableModelClassMap, $k->relasi_tabel);
|
||||
if ($modelClass) {
|
||||
$options_kolom = $modelClass::select($k->relasi_kolom_label . ' as label', $k->relasi_kolom_id . ' as value')->limit(10000);
|
||||
} else {
|
||||
$options_kolom = DB::table($k->relasi_tabel)->selectRaw($k->relasi_kolom_label . ' as label, ' . $k->relasi_kolom_id . ' as value')->whereNull('deleted_at')->limit(10000);
|
||||
}
|
||||
$relasi['options'] = $options_kolom->get();
|
||||
$relasi['sql'] = $options_kolom->toSql();
|
||||
} catch (\Throwable $th) {
|
||||
@@ -199,18 +224,84 @@ 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'));
|
||||
}
|
||||
|
||||
private function prepareValidationRules($kolom)
|
||||
{
|
||||
$rules = [];
|
||||
foreach ($kolom as $k) {
|
||||
if ($k->validasi && is_array($k->validasi)) {
|
||||
$rules[$k->kolom] = $k->validasi;
|
||||
|
||||
if (!in_array('required', $k->validasi) && !in_array('nullable', $k->validasi)) {
|
||||
$rules[$k->kolom][] = 'nullable';
|
||||
}
|
||||
|
||||
if (!in_array('string', $k->validasi) && ($k->tipe == 'varchar' || $k->tipe == 'text')) {
|
||||
$rules[$k->kolom][] = 'string';
|
||||
}
|
||||
if (!in_array('size', $k->validasi) && ($k->tipe == 'varchar')) {
|
||||
$rules[$k->kolom][] = 'size:255';
|
||||
}
|
||||
if (!in_array('integer', $k->validasi) && $k->tipe == 'integer') {
|
||||
$rules[$k->kolom][] = 'integer';
|
||||
}
|
||||
if (!in_array('boolean', $k->validasi) && $k->tipe == 'boolean') {
|
||||
$rules[$k->kolom][] = 'boolean';
|
||||
}
|
||||
if (!in_array('date', $k->validasi) && ($k->tipe == 'date' || $k->tipe == 'datetime')) {
|
||||
$rules[$k->kolom][] = 'date';
|
||||
}
|
||||
if ($k->tipe == 'foreign_key') {
|
||||
$rules[$k->kolom][] = 'exists:' . $k->relasi_tabel . ',' . $k->relasi_kolom_id;
|
||||
}
|
||||
if ($k->tipe == 'enum') {
|
||||
$enumValues = collect($k->enum_opsi)->pluck('value')->toArray();
|
||||
$rules[$k->kolom][] = Rule::in($enumValues);
|
||||
}
|
||||
|
||||
} else {
|
||||
$rules[$k->kolom] = ['nullable'];
|
||||
|
||||
if ($k->tipe == 'varchar' || $k->tipe == 'text') {
|
||||
$rules[$k->kolom][] = 'string';
|
||||
}
|
||||
if ($k->tipe == 'varchar') {
|
||||
$rules[$k->kolom][] = 'size:255';
|
||||
}
|
||||
if ($k->tipe == 'integer') {
|
||||
$rules[$k->kolom][] = 'integer';
|
||||
}
|
||||
if ($k->tipe == 'boolean') {
|
||||
$rules[$k->kolom][] = 'boolean';
|
||||
}
|
||||
if ($k->tipe == 'date' || $k->tipe == 'datetime') {
|
||||
$rules[$k->kolom][] = 'date';
|
||||
}
|
||||
if ($k->tipe == 'foreign_key') {
|
||||
$rules[$k->kolom][] = 'exists:' . $k->relasi_tabel . ',' . $k->relasi_kolom_id;
|
||||
}
|
||||
if ($k->tipe == 'enum') {
|
||||
$enumValues = collect($k->enum_opsi)->pluck('value')->toArray();
|
||||
$rules[$k->kolom][] = Rule::in($enumValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public function store(Request $request, string $tabelId): RedirectResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::find($tabelId);
|
||||
$tabel = TabelBasisData::with('kolom')
|
||||
->whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})->find($tabelId);
|
||||
if (!$tabel) {
|
||||
abort(404, 'Data tabel tidak ditemukan.');
|
||||
}
|
||||
@@ -233,15 +324,7 @@ class ValueBasisDataController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$validationRules = [];
|
||||
foreach ($kolom as $k) {
|
||||
if ($k->validasi && is_array($k->validasi)) {
|
||||
$validationRules[$k->kolom] = $k->validasi;
|
||||
} else {
|
||||
$validationRules[$k->kolom] = ['nullable'];
|
||||
}
|
||||
}
|
||||
$validated = $request->validate($validationRules);
|
||||
$validated = $request->validate($this->prepareValidationRules($kolom));
|
||||
|
||||
DB::transaction(function () use ($program, $tabelId, $validated, $kolom) {
|
||||
$maxId = ValueBasisData::where('tabel_id', $tabelId)
|
||||
@@ -270,16 +353,16 @@ class ValueBasisDataController extends Controller
|
||||
return redirect()->route('tabel.data.index', [$tabelId, 'program_id' => $program->id])->with('success', 'Data berhasil ditambahkan.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(Request $request, string $tabelId, string $id): View
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::find($tabelId);
|
||||
$tabel = TabelBasisData::with('kolom')
|
||||
->whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})->find($tabelId);
|
||||
if (!$tabel) {
|
||||
abort(404, 'Data tabel tidak ditemukan.');
|
||||
}
|
||||
@@ -315,7 +398,9 @@ class ValueBasisDataController extends Controller
|
||||
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);
|
||||
$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) {
|
||||
@@ -336,7 +421,10 @@ class ValueBasisDataController extends Controller
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::find($tabelId);
|
||||
$tabel = TabelBasisData::with('kolom')
|
||||
->whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})->find($tabelId);
|
||||
if (!$tabel) {
|
||||
abort(404, 'Data tabel tidak ditemukan.');
|
||||
}
|
||||
@@ -376,7 +464,12 @@ class ValueBasisDataController extends Controller
|
||||
if ($k->tipe == 'foreign_key') {
|
||||
$relasi['kolom_id'] = $k->id;
|
||||
try {
|
||||
$options_kolom = DB::table($k->relasi_tabel)->selectRaw($k->relasi_kolom_label . ' as label, ' . $k->relasi_kolom_id . ' as value')->whereNull('deleted_at');
|
||||
$modelClass = Arr::get($this->tableModelClassMap, 'master_desa_kelurahan');
|
||||
if ($modelClass) {
|
||||
$options_kolom = $modelClass::select($k->relasi_kolom_label . ' as label', $k->relasi_kolom_id . ' as value')->limit(10000);
|
||||
} else {
|
||||
$options_kolom = DB::table($k->relasi_tabel)->selectRaw($k->relasi_kolom_label . ' as label, ' . $k->relasi_kolom_id . ' as value')->whereNull('deleted_at')->limit(10000);
|
||||
}
|
||||
$relasi['options'] = $options_kolom->get();
|
||||
$relasi['sql'] = $options_kolom->toSql();
|
||||
} catch (\Throwable $th) {
|
||||
@@ -390,16 +483,16 @@ class ValueBasisDataController extends Controller
|
||||
return view('ekosistem.value-basis-data.edit', compact('tabel', 'kolom', 'program', 'values', 'value_id', 'list_relasi'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $tabelId, string $id): RedirectResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$tabel = TabelBasisData::find($tabelId);
|
||||
$tabel = TabelBasisData::with('kolom')
|
||||
->whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})->find($tabelId);
|
||||
if (!$tabel) {
|
||||
abort(404, 'Data tabel tidak ditemukan.');
|
||||
}
|
||||
@@ -431,15 +524,7 @@ class ValueBasisDataController extends Controller
|
||||
abort(404, 'Data tidak ditemukan.');
|
||||
}
|
||||
|
||||
$validationRules = [];
|
||||
foreach ($kolom as $k) {
|
||||
if ($k->validasi && is_array($k->validasi)) {
|
||||
$validationRules[$k->kolom] = $k->validasi;
|
||||
} else {
|
||||
$validationRules[$k->kolom] = ['nullable'];
|
||||
}
|
||||
}
|
||||
$validated = $request->validate($validationRules);
|
||||
$validated = $request->validate($this->prepareValidationRules($kolom));
|
||||
|
||||
DB::transaction(function () use ($program, $tabelId, $validated, $kolom, $id, $values) {
|
||||
foreach ($validated as $kol => $val) {
|
||||
|
||||
@@ -15,13 +15,13 @@ class AuthController extends Controller
|
||||
public function login()
|
||||
{
|
||||
$title = 'Login';
|
||||
return view('konfigurasi.auth.login', compact('title'));
|
||||
return view('auth.login', compact('title'));
|
||||
}
|
||||
|
||||
public function register()
|
||||
{
|
||||
$title = 'Register';
|
||||
return view('konfigurasi.auth.register', compact('title'));
|
||||
return view('auth.register', compact('title'));
|
||||
}
|
||||
|
||||
public function createAccount(Request $request)
|
||||
@@ -42,7 +42,7 @@ class AuthController extends Controller
|
||||
'deleted_by' => null,
|
||||
]);
|
||||
|
||||
return redirect()->route('konfigurasi.auth.login')->with('success', 'Account created successfully. Please login.');
|
||||
return redirect()->route('auth.login')->with('success', 'Account created successfully. Please login.');
|
||||
}
|
||||
|
||||
public function verify(User $user)
|
||||
|
||||
@@ -10,6 +10,7 @@ use App\Enums\Role;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
@@ -70,6 +71,7 @@ class UserController extends Controller
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'username' => ['required', 'string', 'max:255', 'unique:users,name'],
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
||||
'password' => ['required', 'string', 'min:8', 'confirmed'],
|
||||
@@ -90,14 +92,17 @@ class UserController extends Controller
|
||||
|
||||
$user = User::create([
|
||||
'name' => $request->name,
|
||||
'username' => $request->username,
|
||||
'email' => $request->email,
|
||||
'password' => Hash::make($request->password),
|
||||
'role' => $request->role,
|
||||
'uid' => Str::random(10),
|
||||
'created_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
Profile::create([
|
||||
'user_id' => $user->id,
|
||||
'user_uid' => $user->uid,
|
||||
'role' => $request->role,
|
||||
'nama' => $request->name,
|
||||
'email' => $request->email,
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Master;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Master\JenisKomoditas;
|
||||
use App\Models\Pertanian\Komoditas;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class JenisKomoditasController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$perPage = $request->get('per_page', 10);
|
||||
$search = $request->get('search');
|
||||
|
||||
$jenisKomoditas = JenisKomoditas::with('komoditas')
|
||||
->when($search, function ($query) use ($search) {
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nama', 'ILIKE', "%{$search}%")
|
||||
->orWhere('path', 'ILIKE', "%{$search}%")
|
||||
->orWhereHas('komoditas', function ($komoditasQuery) use ($search) {
|
||||
$komoditasQuery->where('nama', 'ILIKE', "%{$search}%");
|
||||
});
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->paginate($perPage);
|
||||
|
||||
$komoditas = Komoditas::orderBy('nama', 'asc')->get();
|
||||
|
||||
return view('master.jeniskomoditas.index', compact(
|
||||
'jenisKomoditas',
|
||||
'komoditas'
|
||||
));
|
||||
}
|
||||
|
||||
public function getByKomoditas($komoditas_id)
|
||||
{
|
||||
$jenisKomoditas = JenisKomoditas::where('komoditas_id', $komoditas_id)
|
||||
->orderBy('nama', 'asc')
|
||||
->get(['id', 'nama']);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $jenisKomoditas,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'komoditas_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
'exists:master_komoditas,id',
|
||||
],
|
||||
'nama' => [
|
||||
'required',
|
||||
'string',
|
||||
'max:255',
|
||||
Rule::unique('jenis_komoditas', 'nama')
|
||||
->where('komoditas_id', $request->komoditas_id),
|
||||
],
|
||||
], [
|
||||
'komoditas_id.required' => 'Komoditas wajib dipilih.',
|
||||
'komoditas_id.exists' => 'Komoditas yang dipilih tidak valid.',
|
||||
'nama.required' => 'Nama jenis komoditas wajib diisi.',
|
||||
'nama.unique' => 'Nama jenis komoditas sudah tersedia pada komoditas ini.',
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$jenisKomoditas = JenisKomoditas::create([
|
||||
'komoditas_id' => $validated['komoditas_id'],
|
||||
'nama' => $validated['nama'],
|
||||
'created_by' => auth()->id(),
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Data jenis komoditas berhasil disimpan.',
|
||||
'data' => $jenisKomoditas,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('Gagal menyimpan jenis komoditas', [
|
||||
'error' => $e->getMessage(),
|
||||
'request' => $request->all(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal menyimpan data: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id)
|
||||
{
|
||||
try {
|
||||
$jenisKomoditas = JenisKomoditas::with('komoditas')->findOrFail($id);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $jenisKomoditas,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data jenis komoditas tidak ditemukan.',
|
||||
], 404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
$jenisKomoditas = JenisKomoditas::findOrFail($id);
|
||||
|
||||
$validated = $request->validate([
|
||||
'komoditas_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
'exists:master_komoditas,id',
|
||||
],
|
||||
'nama' => [
|
||||
'required',
|
||||
'string',
|
||||
'max:255',
|
||||
Rule::unique('jenis_komoditas', 'nama')
|
||||
->where('komoditas_id', $request->komoditas_id)
|
||||
->ignore($jenisKomoditas->id),
|
||||
],
|
||||
'path' => [
|
||||
'nullable',
|
||||
'string',
|
||||
],
|
||||
], [
|
||||
'komoditas_id.required' => 'Komoditas wajib dipilih.',
|
||||
'komoditas_id.exists' => 'Komoditas yang dipilih tidak valid.',
|
||||
'nama.required' => 'Nama jenis komoditas wajib diisi.',
|
||||
'nama.unique' => 'Nama jenis komoditas sudah tersedia pada komoditas ini.',
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$jenisKomoditas->update([
|
||||
'komoditas_id' => $validated['komoditas_id'],
|
||||
'nama' => $validated['nama'],
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Data jenis komoditas berhasil diperbarui.',
|
||||
'data' => $jenisKomoditas->fresh('komoditas'),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('Gagal update jenis komoditas', [
|
||||
'error' => $e->getMessage(),
|
||||
'id' => $id,
|
||||
'request' => $request->all(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal mengupdate data: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$jenisKomoditas = JenisKomoditas::findOrFail($id);
|
||||
$jenisKomoditas->update(['deleted_by' => auth()->id()]);
|
||||
$jenisKomoditas->delete();
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Data jenis komoditas berhasil dihapus.',
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('Gagal hapus jenis komoditas', [
|
||||
'error' => $e->getMessage(),
|
||||
'id' => $id,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal menghapus data: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,12 @@ class ProvinsiController extends Controller
|
||||
$perPage = $request->query('per_page', 10);
|
||||
$search = $request->query('search', '');
|
||||
|
||||
$provinsi = Provinsi::where('nama', 'like', "%$search%")
|
||||
->orWhere('kode', 'like', "%$search%")
|
||||
->orWhere('iso', 'like', "%$search%")
|
||||
$provinsi = Provinsi::withCount('kabupatenKota')
|
||||
->where(function($query) use ($search) {
|
||||
$query->where('nama', 'like', "%$search%")
|
||||
->orWhere('kode', 'like', "%$search%")
|
||||
->orWhere('iso', 'like', "%$search%");
|
||||
})
|
||||
->paginate($perPage);
|
||||
|
||||
return view('master.provinsi.index', compact('title', 'provinsi'));
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Master;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Master\Varietas;
|
||||
use App\Models\Pertanian\Komoditas;
|
||||
use App\Models\Master\JenisKomoditas;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class VarietasController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$perPage = $request->get('per_page', 10);
|
||||
$search = $request->get('search');
|
||||
|
||||
$varietas = Varietas::with(['komoditas', 'jenisKomoditas'])
|
||||
->when($search, function ($query) use ($search) {
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nama', 'ILIKE', "%{$search}%")
|
||||
->orWhere('path', 'ILIKE', "%{$search}%")
|
||||
->orWhereHas('komoditas', function ($komoditasQuery) use ($search) {
|
||||
$komoditasQuery->where('nama', 'ILIKE', "%{$search}%");
|
||||
})
|
||||
->orWhereHas('jenisKomoditas', function ($jenisQuery) use ($search) {
|
||||
$jenisQuery->where('nama', 'ILIKE', "%{$search}%");
|
||||
});
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->paginate($perPage);
|
||||
|
||||
$komoditas = Komoditas::orderBy('nama', 'asc')->get();
|
||||
|
||||
return view('master.varietas.index', compact(
|
||||
'varietas',
|
||||
'komoditas'
|
||||
));
|
||||
}
|
||||
|
||||
public function getByJenisKomoditas($jenisKomoditasId)
|
||||
{
|
||||
$varietas = Varietas::where('jenis_komoditas_id', $jenisKomoditasId)->get();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $varietas,
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$komoditasTable = (new Komoditas)->getTable();
|
||||
$jenisKomoditasTable = (new JenisKomoditas)->getTable();
|
||||
$varietasTable = (new Varietas)->getTable();
|
||||
|
||||
$validated = $request->validate([
|
||||
'komoditas_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::exists($komoditasTable, 'id'),
|
||||
],
|
||||
'jenis_komoditas_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::exists($jenisKomoditasTable, 'id')
|
||||
->where('komoditas_id', $request->komoditas_id),
|
||||
],
|
||||
'nama' => [
|
||||
'required',
|
||||
'string',
|
||||
'max:255',
|
||||
Rule::unique($varietasTable, 'nama')
|
||||
->where('komoditas_id', $request->komoditas_id)
|
||||
->where('jenis_komoditas_id', $request->jenis_komoditas_id),
|
||||
],
|
||||
'deskripsi' => [
|
||||
'nullable',
|
||||
'string',
|
||||
],
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$varietas = Varietas::create([
|
||||
'komoditas_id' => $validated['komoditas_id'],
|
||||
'jenis_komoditas_id' => $validated['jenis_komoditas_id'],
|
||||
'nama' => $validated['nama'],
|
||||
'deskripsi' => $validated['deskripsi'] ?? null,
|
||||
'created_by' => auth()->id(),
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Data varietas berhasil disimpan.',
|
||||
'data' => $varietas,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('Gagal menyimpan varietas', [
|
||||
'error' => $e->getMessage(),
|
||||
'request' => $request->all(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal menyimpan data: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function show(string $id)
|
||||
{
|
||||
try {
|
||||
$varietas = Varietas::with(['komoditas', 'jenisKomoditas'])->findOrFail($id);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $varietas,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data varietas tidak ditemukan.',
|
||||
], 404);
|
||||
}
|
||||
}
|
||||
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
$komoditasTable = (new Komoditas)->getTable();
|
||||
$jenisKomoditasTable = (new JenisKomoditas)->getTable();
|
||||
$varietasTable = (new Varietas)->getTable();
|
||||
|
||||
$validated = $request->validate([
|
||||
'komoditas_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::exists($komoditasTable, 'id'),
|
||||
],
|
||||
'jenis_komoditas_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::exists($jenisKomoditasTable, 'id')
|
||||
->where('komoditas_id', $request->komoditas_id),
|
||||
],
|
||||
'nama' => [
|
||||
'required',
|
||||
'string',
|
||||
'max:255',
|
||||
Rule::unique($varietasTable, 'nama')
|
||||
->where('komoditas_id', $request->komoditas_id)
|
||||
->where('jenis_komoditas_id', $request->jenis_komoditas_id),
|
||||
],
|
||||
'deskripsi' => [
|
||||
'nullable',
|
||||
'string',
|
||||
],
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$varietas = Varietas::findOrFail($id);
|
||||
$varietas->update([
|
||||
'komoditas_id' => $validated['komoditas_id'],
|
||||
'jenis_komoditas_id' => $validated['jenis_komoditas_id'],
|
||||
'nama' => $validated['nama'],
|
||||
'deskripsi' => $validated['deskripsi'] ?? null,
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Data varietas berhasil diperbarui.',
|
||||
'data' => $varietas->fresh(['komoditas', 'jenisKomoditas']),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('Gagal update varietas', [
|
||||
'error' => $e->getMessage(),
|
||||
'id' => $id,
|
||||
'request' => $request->all(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal mengupdate data: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy(string $id)
|
||||
{
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$varietas = Varietas::findOrFail($id);
|
||||
$varietas->update(['deleted_by' => auth()->id()]);
|
||||
$varietas->delete();
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Data varietas berhasil dihapus.',
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('Gagal hapus varietas', [
|
||||
'error' => $e->getMessage(),
|
||||
'id' => $id,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal menghapus data: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use App\Models\Pertanian\Adat;
|
||||
use App\Models\Wilayah\Provinsi;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class LahanController extends Controller
|
||||
{
|
||||
@@ -76,6 +77,25 @@ class LahanController extends Controller
|
||||
return view('produktivitas.lahan.index', compact('lahan', 'provinsi', 'profiles', 'adat', 'kabupaten', 'kecamatan', 'desa'));
|
||||
}
|
||||
|
||||
public function getByProfile(Request $request, $profileId)
|
||||
{
|
||||
$desaKelurahanId = $request->get('desa_kelurahan_id');
|
||||
|
||||
$lahan = Lahan::with('profile')
|
||||
->where('profile_id', $profileId)
|
||||
->when($desaKelurahanId, function ($query) use ($desaKelurahanId) {
|
||||
$query->where('desa_kelurahan_id', $desaKelurahanId);
|
||||
})
|
||||
->orderBy('created_at', 'desc')
|
||||
->get(['id', 'nama', 'path', 'profile_id', 'desa_kelurahan_id']);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $lahan,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function create()
|
||||
{
|
||||
$provinsi = Provinsi::orderBy('nama', 'asc')->get();
|
||||
@@ -112,8 +132,12 @@ class LahanController extends Controller
|
||||
return response()->json(['status' => 'error', 'message' => 'Format koordinat (path) bukan JSON array yang valid.'], 422);
|
||||
}
|
||||
}
|
||||
|
||||
$userUID = Profile::where('id', $request->profile_id)->value('user_uid');
|
||||
$userUID = substr($userUID, 2);
|
||||
|
||||
Lahan::create([
|
||||
'uid' => 'LH' . $userUID . '-' . strtoupper(Str::random(10)),
|
||||
'nama' => $request->nama,
|
||||
'status_kepemilikan' => $request->status_kepemilikan,
|
||||
'profile_id' => $request->profile_id,
|
||||
|
||||
@@ -0,0 +1,421 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Produktivitas;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Pertanian\Tanaman;
|
||||
use App\Models\Profile;
|
||||
use App\Models\Pertanian\Komoditas;
|
||||
use App\Models\Master\JenisKomoditas;
|
||||
use App\Models\Master\Varietas;
|
||||
use App\Models\Pertanian\Lahan;
|
||||
use App\Models\Wilayah\Provinsi;
|
||||
use App\Models\Wilayah\KabupatenKota;
|
||||
use App\Models\Wilayah\Kecamatan;
|
||||
use App\Models\Wilayah\DesaKelurahan;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class MapTanamanController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$perPage = $request->get('per_page', 10);
|
||||
$search = $request->get('search');
|
||||
|
||||
$tanaman = Tanaman::query()
|
||||
->select([
|
||||
DB::raw('MIN(id) as id'),
|
||||
'profile_id',
|
||||
'lahan_id',
|
||||
'komoditas_id',
|
||||
'jenis_komoditas_id',
|
||||
'varietas_id',
|
||||
DB::raw('COUNT(*) as total_tanaman'),
|
||||
DB::raw("SUM(CASE WHEN kondisi_tanaman = 'sehat' THEN 1 ELSE 0 END) as total_sehat"),
|
||||
DB::raw("SUM(CASE WHEN kondisi_tanaman = 'sakit' THEN 1 ELSE 0 END) as total_sakit"),
|
||||
DB::raw("SUM(CASE WHEN kondisi_tanaman = 'mati' THEN 1 ELSE 0 END) as total_mati"),
|
||||
DB::raw('MAX(created_at) as max_created_at'),
|
||||
])
|
||||
->with([
|
||||
'profile',
|
||||
'lahan.desaKelurahan.kecamatan.kabupatenkota.provinsi',
|
||||
'komoditas',
|
||||
'jenisKomoditas',
|
||||
'varietas',
|
||||
])
|
||||
->when($search, function ($query) use ($search) {
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->whereHas('profile', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
|
||||
->orWhereHas('lahan', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
|
||||
->orWhereHas('komoditas', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
|
||||
->orWhereHas('jenisKomoditas', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
|
||||
->orWhereHas('varietas', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
|
||||
->orWhereHas('lahan.desaKelurahan', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
|
||||
->orWhereHas('lahan.desaKelurahan.kecamatan', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
|
||||
->orWhereHas('lahan.desaKelurahan.kecamatan.kabupatenkota', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
|
||||
->orWhereHas('lahan.desaKelurahan.kecamatan.kabupatenkota.provinsi', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"));
|
||||
});
|
||||
})
|
||||
->groupBy([
|
||||
'profile_id',
|
||||
'lahan_id',
|
||||
'komoditas_id',
|
||||
'jenis_komoditas_id',
|
||||
'varietas_id',
|
||||
])
|
||||
->orderByDesc('max_created_at')
|
||||
->paginate($perPage);
|
||||
|
||||
return view('produktivitas.mapTanaman.index', compact('tanaman'));
|
||||
}
|
||||
|
||||
private function getTanamanGroupByRepresentativeId($id)
|
||||
{
|
||||
$representative = Tanaman::findOrFail($id);
|
||||
|
||||
$points = Tanaman::with([
|
||||
'profile',
|
||||
'lahan.desaKelurahan.kecamatan.kabupatenkota.provinsi',
|
||||
'komoditas',
|
||||
'jenisKomoditas',
|
||||
'varietas',
|
||||
])
|
||||
->where('profile_id', $representative->profile_id)
|
||||
->where('lahan_id', $representative->lahan_id)
|
||||
->where('komoditas_id', $representative->komoditas_id)
|
||||
->where('jenis_komoditas_id', $representative->jenis_komoditas_id)
|
||||
->where('varietas_id', $representative->varietas_id)
|
||||
->orderBy('id')
|
||||
->get();
|
||||
|
||||
return [
|
||||
'representative' => $representative,
|
||||
'points' => $points,
|
||||
];
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$provinsi = Provinsi::select('id', 'nama', 'path')
|
||||
->orderBy('nama')
|
||||
->get();
|
||||
|
||||
$komoditas = Komoditas::orderBy('nama')->get();
|
||||
$profiles = Profile::orderBy('nama')->get();
|
||||
|
||||
return view('produktivitas.mapTanaman.add', compact(
|
||||
'provinsi',
|
||||
'komoditas',
|
||||
'profiles'
|
||||
));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$desaKelurahanTable = (new DesaKelurahan)->getTable();
|
||||
$profileTable = (new Profile)->getTable();
|
||||
$lahanTable = (new Lahan)->getTable();
|
||||
$komoditasTable = (new Komoditas)->getTable();
|
||||
$jenisKomoditasTable = (new JenisKomoditas)->getTable();
|
||||
$varietasTable = (new Varietas)->getTable();
|
||||
|
||||
$validated = $request->validate([
|
||||
'desa_kelurahan_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::exists($desaKelurahanTable, 'id'),
|
||||
],
|
||||
|
||||
'profile_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::exists($profileTable, 'id'),
|
||||
],
|
||||
|
||||
'lahan_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::exists($lahanTable, 'id')
|
||||
->where('profile_id', $request->profile_id)
|
||||
->where('desa_kelurahan_id', $request->desa_kelurahan_id),
|
||||
],
|
||||
|
||||
'komoditas_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::exists($komoditasTable, 'id'),
|
||||
],
|
||||
|
||||
'jenis_komoditas_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::exists($jenisKomoditasTable, 'id')
|
||||
->where('komoditas_id', $request->komoditas_id),
|
||||
],
|
||||
|
||||
'varietas_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::exists($varietasTable, 'id')
|
||||
->where('jenis_komoditas_id', $request->jenis_komoditas_id),
|
||||
],
|
||||
|
||||
'points' => [
|
||||
'required',
|
||||
'array',
|
||||
'min:1',
|
||||
],
|
||||
|
||||
'points.*.latitude' => [
|
||||
'required',
|
||||
'numeric',
|
||||
],
|
||||
|
||||
'points.*.longitude' => [
|
||||
'required',
|
||||
'numeric',
|
||||
],
|
||||
|
||||
'points.*.kondisi_tanaman' => [
|
||||
'required',
|
||||
Rule::in(['sehat', 'sakit', 'mati']),
|
||||
],
|
||||
|
||||
'metode_pengumpulan' => [
|
||||
'nullable',
|
||||
'string',
|
||||
'max:50',
|
||||
],
|
||||
|
||||
'deskripsi' => [
|
||||
'nullable',
|
||||
'string',
|
||||
],
|
||||
], [
|
||||
'points.required' => 'Minimal tambahkan satu titik tanaman pada peta.',
|
||||
'points.min' => 'Minimal tambahkan satu titik tanaman pada peta.',
|
||||
'points.*.latitude.required' => 'Latitude titik tanaman wajib ada.',
|
||||
'points.*.longitude.required' => 'Longitude titik tanaman wajib ada.',
|
||||
'points.*.kondisi_tanaman.required' => 'Kondisi tanaman wajib dipilih.',
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$lahan = Lahan::findOrFail($validated['lahan_id']);
|
||||
$komoditas = Komoditas::findOrFail($validated['komoditas_id']);
|
||||
$profile = Profile::findOrFail($validated['profile_id']);
|
||||
|
||||
if (!$lahan->uid) {
|
||||
throw new \Exception('UID lahan tidak ditemukan.');
|
||||
}
|
||||
|
||||
$profileName = str_replace(' ', '', $profile->nama);
|
||||
$lahanUidPart = substr($lahan->uid, 2);
|
||||
|
||||
$existingCount = Tanaman::where('lahan_id', $validated['lahan_id'])
|
||||
->where('komoditas_id', $validated['komoditas_id'])
|
||||
->where('jenis_komoditas_id', $validated['jenis_komoditas_id'])
|
||||
->where('varietas_id', $validated['varietas_id'])
|
||||
->count();
|
||||
|
||||
$createdTanaman = [];
|
||||
|
||||
foreach ($validated['points'] as $index => $point) {
|
||||
$number = $existingCount + $index + 1;
|
||||
|
||||
$createdTanaman[] = Tanaman::create([
|
||||
'uid' => 'TM' . $lahanUidPart . '-' . strtoupper(Str::random(10)),
|
||||
'nama' => $komoditas->nama . ' - ' . $profileName . ' - ' . $number,
|
||||
'desa_kelurahan_id' => $validated['desa_kelurahan_id'],
|
||||
|
||||
'profile_id' => $validated['profile_id'],
|
||||
'lahan_id' => $validated['lahan_id'],
|
||||
|
||||
'komoditas_id' => $validated['komoditas_id'],
|
||||
'jenis_komoditas_id' => $validated['jenis_komoditas_id'],
|
||||
'varietas_id' => $validated['varietas_id'],
|
||||
|
||||
'latitude' => $point['latitude'],
|
||||
'longitude' => $point['longitude'],
|
||||
'kondisi_tanaman' => $point['kondisi_tanaman'],
|
||||
'metode_pengumpulan' => $validated['metode_pengumpulan'] ?? 'manual',
|
||||
'deskripsi' => $validated['deskripsi'] ?? null,
|
||||
'created_by' => auth()->id(),
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => count($createdTanaman) . ' data tanaman berhasil disimpan.',
|
||||
'redirect' => route('map-tanaman.index'),
|
||||
'data' => $createdTanaman,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('Gagal menyimpan tanaman bulk', [
|
||||
'error' => $e->getMessage(),
|
||||
'request' => $request->all(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal menyimpan data: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function show(string $id)
|
||||
{
|
||||
$group = $this->getTanamanGroupByRepresentativeId($id);
|
||||
|
||||
$tanaman = $group['representative']->load([
|
||||
'profile',
|
||||
'lahan.desaKelurahan.kecamatan.kabupatenkota.provinsi',
|
||||
'komoditas',
|
||||
'jenisKomoditas',
|
||||
'varietas',
|
||||
]);
|
||||
|
||||
$points = $group['points'];
|
||||
|
||||
return view('produktivitas.mapTanaman.view', compact(
|
||||
'tanaman',
|
||||
'points'
|
||||
));
|
||||
}
|
||||
public function edit(string $id)
|
||||
{
|
||||
$group = $this->getTanamanGroupByRepresentativeId($id);
|
||||
|
||||
$tanaman = $group['representative']->load([
|
||||
'profile',
|
||||
'lahan.desaKelurahan.kecamatan.kabupatenkota.provinsi',
|
||||
'komoditas',
|
||||
'jenisKomoditas',
|
||||
'varietas',
|
||||
]);
|
||||
|
||||
$points = $group['points'];
|
||||
|
||||
return view('produktivitas.mapTanaman.edit', compact(
|
||||
'tanaman',
|
||||
'points'
|
||||
));
|
||||
}
|
||||
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
$group = $this->getTanamanGroupByRepresentativeId($id);
|
||||
|
||||
$representative = $group['representative'];
|
||||
|
||||
$validated = $request->validate([
|
||||
'points' => ['required', 'array', 'min:1'],
|
||||
'points.*.id' => ['nullable', 'integer', 'exists:map_tanaman,id'],
|
||||
'points.*.latitude' => ['required', 'numeric'],
|
||||
'points.*.longitude' => ['required', 'numeric'],
|
||||
'points.*.kondisi_tanaman' => [
|
||||
'required',
|
||||
Rule::in(['sehat', 'sakit', 'mati']),
|
||||
],
|
||||
'points.*._delete' => ['nullable'],
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
foreach ($validated['points'] as $point) {
|
||||
if (!empty($point['_delete']) && !empty($point['id'])) {
|
||||
$tanaman = Tanaman::where('id', $point['id'])
|
||||
->where('profile_id', $representative->profile_id)
|
||||
->where('lahan_id', $representative->lahan_id)
|
||||
->where('komoditas_id', $representative->komoditas_id)
|
||||
->where('jenis_komoditas_id', $representative->jenis_komoditas_id)
|
||||
->where('varietas_id', $representative->varietas_id)
|
||||
->first();
|
||||
|
||||
if ($tanaman) {
|
||||
$tanaman->deleted_by = auth()->id();
|
||||
$tanaman->save();
|
||||
$tanaman->delete();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!empty($point['id'])) {
|
||||
$tanaman = Tanaman::where('id', $point['id'])
|
||||
->where('profile_id', $representative->profile_id)
|
||||
->where('lahan_id', $representative->lahan_id)
|
||||
->where('komoditas_id', $representative->komoditas_id)
|
||||
->where('jenis_komoditas_id', $representative->jenis_komoditas_id)
|
||||
->where('varietas_id', $representative->varietas_id)
|
||||
->firstOrFail();
|
||||
|
||||
$tanaman->update([
|
||||
'latitude' => $point['latitude'],
|
||||
'longitude' => $point['longitude'],
|
||||
'kondisi_tanaman' => $point['kondisi_tanaman'],
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Data titik tanaman berhasil diperbarui.',
|
||||
'redirect' => route('map-tanaman.index'),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal memperbarui data: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy(string $id)
|
||||
{
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$group = $this->getTanamanGroupByRepresentativeId($id);
|
||||
$points = $group['points'];
|
||||
|
||||
foreach ($points as $point) {
|
||||
$point->update([
|
||||
'deleted_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
$point->delete();
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => $points->count() . ' titik tanaman berhasil dihapus.',
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal menghapus data: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,25 @@ class ProfileController extends Controller
|
||||
return view('master.profile.index', compact('profiles', 'provinsi'));
|
||||
}
|
||||
|
||||
public function getByDesaKelurahan($desaId)
|
||||
{
|
||||
try {
|
||||
$profiles = Profile::where('desa_kelurahan_id', $desaId)
|
||||
->orderBy('nama', 'asc')
|
||||
->get(['id', 'nama']);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $profiles,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$provinsi = Provinsi::orderBy('nama', 'asc')->get();
|
||||
|
||||
@@ -54,6 +54,9 @@ class AktivitasController extends Controller
|
||||
'jenis_aktivitas' => ['required','string','max:255', Rule::in(['tujuan', 'aktivitas']),],
|
||||
'indikator' => ['required','string'],
|
||||
'deskripsi' => ['required','string'],
|
||||
'parent_id' => [
|
||||
Rule::requiredIf($request->jenis_aktivitas === 'aktivitas'),
|
||||
'nullable','exists:program_aktivitas,id',],
|
||||
]);
|
||||
|
||||
Aktivitas::create([...$validated,
|
||||
@@ -125,6 +128,9 @@ class AktivitasController extends Controller
|
||||
'jenis_aktivitas' => ['required','string','max:255', Rule::in(['tujuan', 'aktivitas']),],
|
||||
'indikator' => ['required','string'],
|
||||
'deskripsi' => ['required','string'],
|
||||
'parent_id' => [
|
||||
Rule::requiredIf($request->jenis_aktivitas === 'aktivitas'),
|
||||
'nullable','exists:program_aktivitas,id'],
|
||||
]);
|
||||
|
||||
$aktivitas->update([...$validated,
|
||||
|
||||
@@ -102,7 +102,8 @@ class FrameworkController extends Controller
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$framework = Framework::findOrFail($id);
|
||||
$framework = Framework::with('transformasi')->with('transformasi.tujuan')
|
||||
->findOrFail($id);
|
||||
$program = Program::all();
|
||||
|
||||
return view('program.framework.edit', compact('framework', 'program'));
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Program;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
use App\Models\Program\Framework;
|
||||
use App\Models\Program\Realisasi;
|
||||
|
||||
class RealisasiController extends Controller
|
||||
{
|
||||
public function index(Request $request): View
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$framework = Framework::when($request->has('frameworkid'), function ($query) use ($request) {
|
||||
$query->where('id', $request->frameworkid);
|
||||
})->latest()->first();
|
||||
if ($framework == null) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$ringkasanIsiRealisasi = DB::select('select count(pt.id) count_target, sum(case when rl.id > 0 then 1 else 0 end) count_realisasi
|
||||
from program_target pt
|
||||
inner join program_aktivitas pa on pt.aktivitas_id = pa.id
|
||||
inner join program_transformasi ptr on pa.transformasi_id = ptr.id
|
||||
inner join program_framework pf on ptr.framework_id = pf.id
|
||||
left join
|
||||
(select target_id, max(id) id from program_realisasi pr
|
||||
group by target_id) rl on pt.id = rl.target_id
|
||||
where
|
||||
pt.deleted_at is null
|
||||
and pa.deleted_at is null
|
||||
and ptr.deleted_at is null
|
||||
and pf.id = ?
|
||||
', [$framework->id]);
|
||||
$ringkasanIsiRealisasi = collect($ringkasanIsiRealisasi)->map(function ($item) {
|
||||
$item->persentase = $item->count_target > 0 ? round(($item->count_realisasi / $item->count_target) * 100, 2) : 0;
|
||||
return $item;
|
||||
})->first();
|
||||
|
||||
$ringkasanCapaianRealisasi = DB::select("select round(avg(percent_realisasi)::numeric * 100, 2) persentase,
|
||||
sum(case when percent_realisasi >= 0.8 then 1 else 0 end) capaian_80,
|
||||
sum(case when percent_realisasi >= 0.5 and percent_realisasi < 0.8 then 1 else 0 end) capaian_50_80,
|
||||
sum(case when percent_realisasi < 0.5 then 1 else 0 end) capaian_50
|
||||
from
|
||||
(select pt.id target_id, pr.id realisasi_id,
|
||||
pt.tipe,
|
||||
case
|
||||
when pt.tipe = 'integer' then pt.target_integer
|
||||
when pt.tipe = 'float' then pt.target_float
|
||||
when pt.tipe = 'boolean' then pt.target_boolean::integer
|
||||
end target,
|
||||
case
|
||||
when pt.tipe = 'integer' then pr.realisasi_integer
|
||||
when pt.tipe = 'float' then pr.realisasi_float
|
||||
when pt.tipe = 'boolean' then pr.realisasi_boolean::integer
|
||||
end realisasi,
|
||||
case
|
||||
when pt.tipe = 'integer' then pr.realisasi_integer::float / pt.target_integer::float
|
||||
when pt.tipe = 'float' then pr.realisasi_float / pt.target_float
|
||||
when pt.tipe = 'boolean' then pr.realisasi_boolean::integer / pt.target_boolean::integer
|
||||
end percent_realisasi
|
||||
from program_target pt
|
||||
inner join program_aktivitas pa on pt.aktivitas_id = pa.id
|
||||
inner join program_transformasi ptr on pa.transformasi_id = ptr.id
|
||||
inner join program_framework pf on ptr.framework_id = pf.id
|
||||
left join
|
||||
(select target_id, max(id) id from program_realisasi pr
|
||||
group by target_id) rl on pt.id = rl.target_id
|
||||
left join program_realisasi pr on rl.id = pr.id and pr.target_id = pt.id
|
||||
where
|
||||
pt.deleted_at is null
|
||||
and pa.deleted_at is null
|
||||
and ptr.deleted_at is null
|
||||
and pf.id = ?) v",
|
||||
[$framework->id]);
|
||||
$ringkasanCapaianRealisasi = collect($ringkasanCapaianRealisasi)->first();
|
||||
|
||||
$ringkasanVerifikasi = DB::select("select count(pt.id) count_target,
|
||||
sum(case when count_verifikasi > 0 then 1 else 0 end) count_verifikasi,
|
||||
sum(case when count_verifikasi = 0 or count_verifikasi is null then 1 else 0 end) count_unverifikasi
|
||||
from program_target pt
|
||||
inner join program_aktivitas pa on pt.aktivitas_id = pa.id
|
||||
inner join program_transformasi ptr on pa.transformasi_id = ptr.id
|
||||
inner join program_framework pf on ptr.framework_id = pf.id
|
||||
left join
|
||||
(select target_id, max(id) id from program_realisasi pr
|
||||
group by target_id) rl on pt.id = rl.target_id
|
||||
left join
|
||||
(select realisasi_id, count(pv.id) count_verifikasi from program_verifikasi pv
|
||||
group by realisasi_id) rv
|
||||
on rv.realisasi_id = rl.id
|
||||
where
|
||||
pt.deleted_at is null
|
||||
and pa.deleted_at is null
|
||||
and ptr.deleted_at is null
|
||||
and pf.id = ?",
|
||||
[$framework->id]);
|
||||
$ringkasanVerifikasi = collect($ringkasanVerifikasi)->map(function ($item) {
|
||||
$item->persentase = $item->count_target > 0 ? round(($item->count_verifikasi / $item->count_target) * 100, 2) : 0;
|
||||
return $item;
|
||||
})->first();
|
||||
|
||||
return view('program.realisasi.index', compact('framework', 'ringkasanIsiRealisasi', 'ringkasanCapaianRealisasi', 'ringkasanVerifikasi'));
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'target_id' => ['required', 'integer', 'exists:program_target,id'],
|
||||
'realisasi_integer' => ['nullable', 'integer'],
|
||||
'realisasi_float' => ['nullable', 'numeric'],
|
||||
'realisasi_boolean' => ['nullable', 'boolean'],
|
||||
]);
|
||||
|
||||
$realisasi = Realisasi::create([...$validated,
|
||||
'created_by' => auth()->id(),
|
||||
'updated_by' => auth()->id()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Target berhasil ditambahkan.'
|
||||
], 201);
|
||||
}
|
||||
|
||||
public function show(string $id)
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$realisasi = Realisasi::with('target', 'target.aktivitas', 'target.aktivitas.transformasi', 'verifikasi')
|
||||
->find($id);
|
||||
if (!$realisasi) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data realisasi tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $realisasi
|
||||
]);
|
||||
}
|
||||
|
||||
public function edit(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function update(Request $request, string $id): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$realisasi = Realisasi::find($id);
|
||||
if (!$realisasi) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data realisasi tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'target_id' => ['required', 'integer', 'exists:program_target,id'],
|
||||
'realisasi_integer' => ['nullable', 'integer'],
|
||||
'realisasi_float' => ['nullable', 'numeric'],
|
||||
'realisasi_boolean' => ['nullable', 'boolean'],
|
||||
]);
|
||||
|
||||
$realisasi->update([...$validated,
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Target berhasil diperbarui.'
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,16 @@ class TargetController extends Controller
|
||||
'nullable',
|
||||
'boolean'
|
||||
],
|
||||
'tipe_realisasi' => [
|
||||
'nullable',
|
||||
'string',
|
||||
Rule::in(['manual', 'referensi'])
|
||||
],
|
||||
'value_query' => [
|
||||
Rule::requiredIf($request->tipe_realisasi === 'referensi'),
|
||||
'nullable',
|
||||
'string'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -77,9 +87,6 @@ class TargetController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request, string $frameworkId, string $transformasiId, string $aktivitasId): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
@@ -109,12 +116,32 @@ class TargetController extends Controller
|
||||
], 201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id)
|
||||
public function show(string $frameworkId, string $transformasiId, string $aktivitasId, string $id)
|
||||
{
|
||||
//
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$target = Target::with('realisasi', 'latestRealisasi')
|
||||
->whereHas('aktivitas.transformasi', function ($query) use ($frameworkId) {
|
||||
$query->where('framework_id', $frameworkId);
|
||||
})
|
||||
->whereHas('aktivitas', function ($query) use ($transformasiId) {
|
||||
$query->where('transformasi_id', $transformasiId);
|
||||
})
|
||||
->where('aktivitas_id', $aktivitasId)->find($id);
|
||||
|
||||
if (!$target) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data target tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $target
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,16 +155,67 @@ class TargetController extends Controller
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
public function update(Request $request, string $frameworkId, string $transformasiId, string $aktivitasId, string $id)
|
||||
{
|
||||
//
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$target = Target::whereHas('aktivitas.transformasi', function ($query) use ($frameworkId) {
|
||||
$query->where('framework_id', $frameworkId);
|
||||
})
|
||||
->whereHas('aktivitas', function ($query) use ($transformasiId) {
|
||||
$query->where('transformasi_id', $transformasiId);
|
||||
})
|
||||
->where('aktivitas_id', $aktivitasId)->find($id);
|
||||
|
||||
if (!$target) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data target tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$validated = $this->validated($request);
|
||||
$target->update([...$validated,
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Target berhasil diperbarui.'
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
public function destroy(string $frameworkId, string $transformasiId, string $aktivitasId, string $id)
|
||||
{
|
||||
//
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$target = Target::whereHas('aktivitas.transformasi', function ($query) use ($frameworkId) {
|
||||
$query->where('framework_id', $frameworkId);
|
||||
})
|
||||
->whereHas('aktivitas', function ($query) use ($transformasiId) {
|
||||
$query->where('transformasi_id', $transformasiId);
|
||||
})
|
||||
->where('aktivitas_id', $aktivitasId)->find($id);
|
||||
|
||||
if (!$target) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data target tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$target->update([
|
||||
'deleted_by' => auth()->id(),
|
||||
]);
|
||||
$target->delete();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Target berhasil dihapus.'
|
||||
], 200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Program;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
use App\Models\Program\Framework;
|
||||
use App\Models\Program\Realisasi;
|
||||
use App\Models\Program\Verifikasi;
|
||||
|
||||
class VerifikasiController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'realisasi_id' => ['required', 'integer', 'exists:program_realisasi,id'],
|
||||
'dokumen' => ['required', 'string'],
|
||||
'link_dokumen' => ['required', 'url'],
|
||||
]);
|
||||
|
||||
$verifikasi = Verifikasi::create([...$validated,
|
||||
'created_by' => auth()->id(),
|
||||
'updated_by' => auth()->id()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Dokumen bukti berhasil ditambahkan.'
|
||||
], 201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id): JsonResponse
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id): JsonResponse
|
||||
{
|
||||
if (!Gate::any(['super_admin', 'admin'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$verifikasi = Verifikasi::find($id);
|
||||
if (!$verifikasi) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data verifikasi tidak ditemukan.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$verifikasi->update(['updated_by' => auth()->id()]);
|
||||
$verifikasi->delete();
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Dokumen bukti berhasil dihapus.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@ class ProgramController extends Controller
|
||||
'sub_domain' => ['required', Rule::unique(Program::class, 'sub_domain')],
|
||||
'tahun' => ['required', 'integer'],
|
||||
'instansi' => ['nullable', 'string'],
|
||||
'nama_singkat' => ['required', 'string'],
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
@@ -94,6 +95,9 @@ class ProgramController extends Controller
|
||||
$validator = Validator::make($request->all(), [
|
||||
'nama' => ['required'],
|
||||
'sub_domain' => ['required', Rule::unique(Program::class, 'sub_domain')->ignore($id)],
|
||||
'tahun' => ['required', 'integer'],
|
||||
'instansi' => ['nullable', 'string'],
|
||||
'nama_singkat' => ['required', 'string'],
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
@@ -106,9 +110,7 @@ class ProgramController extends Controller
|
||||
return redirect()->route('program.index')->with('error', 'Data program tidak ditemukan!');
|
||||
}
|
||||
|
||||
$program->update([
|
||||
'nama' => $request->nama,
|
||||
'sub_domain' => $request->sub_domain,
|
||||
$program->update([...$validator->validated(),
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\Core;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
use App\Http\Resources\Pertanian\KomoditasResource;
|
||||
|
||||
class ProgramKomoditasResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'program_id' => $this->program_id,
|
||||
'komoditas_id' => $this->komoditas_id,
|
||||
'default' => $this->default,
|
||||
'komoditas' => $this->komoditas ? new KomoditasResource($this->komoditas) : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\Core;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
use App\Http\Resources\Wilayah\ProvinsiResource;
|
||||
use App\Http\Resources\Wilayah\KabupatenKotaResource;
|
||||
use App\Http\Resources\Wilayah\KecamatanResource;
|
||||
use App\Http\Resources\Wilayah\DesaKelurahanResource;
|
||||
|
||||
class ProgramLokasiResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'program_id' => $this->program_id,
|
||||
'provinsi_id' => $this->provinsi_id,
|
||||
'kabupaten_kota_id' => $this->kabupaten_kota_id,
|
||||
'kecamatan_id' => $this->kecamatan_id,
|
||||
'desa_kelurahan_id' => $this->desa_kelurahan_id,
|
||||
'default' => $this->default,
|
||||
'provinsi' => $this->provinsi ? new ProvinsiResource($this->provinsi) : null,
|
||||
'kabupatenKota' => $this->kabupatenKota ? new KabupatenKotaResource($this->kabupatenKota) : null,
|
||||
'kecamatan' => $this->kecamatan ? new KecamatanResource($this->kecamatan) : null,
|
||||
'desaKelurahan' => $this->desaKelurahan ? new DesaKelurahanResource($this->desaKelurahan) : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\Core;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use App\Http\Resources\Core\ProgramKomoditasResource;
|
||||
use App\Http\Resources\Core\ProgramLokasiResource;
|
||||
|
||||
class ProgramResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'nama' => $this->nama,
|
||||
'sub_domain' => $this->sub_domain,
|
||||
'tahun' => $this->tahun,
|
||||
'instansi' => $this->instansi,
|
||||
'nama_singkat' => $this->nama_singkat,
|
||||
'komoditas' => $this->komoditas()->with('komoditas')->get()->map(function ($item) {
|
||||
return new ProgramKomoditasResource($item);
|
||||
}),
|
||||
'lokasi' => $this->lokasi()->with(['provinsi', 'kabupatenKota', 'kecamatan', 'desaKelurahan'])->get()->map(function ($item) {
|
||||
return new ProgramLokasiResource($item);
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\Ekosistem;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
use App\Http\Resources\Ekosistem\KolomBasisDataResource;
|
||||
|
||||
class FormBasisDataResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'tabel_id' => $this->tabel_id,
|
||||
'parent_id' => $this->parent_id,
|
||||
'tipe' => $this->tipe,
|
||||
'column_width' => $this->column_width,
|
||||
'kolom_id' => $this->kolom_id,
|
||||
'section_label' => $this->section_label,
|
||||
'urutan' => $this->urutan,
|
||||
'kolom' => new KolomBasisDataResource($this->whenLoaded('kolom')),
|
||||
'form' => FormBasisDataResource::collection($this->whenLoaded('form')),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\Ekosistem;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class KolomBasisDataResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'label' => $this->label,
|
||||
'kolom' => $this->kolom,
|
||||
'tipe' => $this->tipe,
|
||||
'validasi' => $this->validasi,
|
||||
'urutan' => $this->urutan,
|
||||
'relasi_tabel' => $this->relasi_tabel,
|
||||
'relasi_kolom_id' => $this->relasi_kolom_id,
|
||||
'relasi_kolom_label' => $this->relasi_kolom_label,
|
||||
'enum_opsi' => $this->enum_opsi,
|
||||
'is_active' => $this->is_active,
|
||||
'is_browse' => $this->is_browse,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\Ekosistem;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
use App\Models\Ekosistem\TabelBasisData;
|
||||
use App\Models\Ekosistem\KolomBasisData;
|
||||
use App\Http\Resources\Ekosistem\KolomBasisDataResource;
|
||||
|
||||
class TabelBasisDataResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'tabel' => $this->tabel,
|
||||
'label' => $this->label,
|
||||
'menu' => $this->menu,
|
||||
'deskripsi' => $this->deskripsi,
|
||||
// 'group_id' => $this->group_id,
|
||||
'urutan' => $this->urutan,
|
||||
// 'group' => new GroupBasisDataResource($this->whenLoaded('group')),
|
||||
'kolom' => KolomBasisDataResource::collection($this->whenLoaded('kolom')),
|
||||
//'ringkasan' => RingkasanBasisDataResource::collection($this->whenLoaded('ringkasan')),
|
||||
'form' => FormBasisDataResource::collection($this->whenLoaded('form')),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\Ekosistem;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class ValueBasisDataResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'program_id' => $this->program_id,
|
||||
'tabel_id' => $this->tabel_id,
|
||||
'kolom_id' => $this->kolom_id,
|
||||
'value_id' => $this->value_id,
|
||||
'value_varchar' => $this->value_varchar,
|
||||
'value_integer' => $this->value_integer,
|
||||
'value_float' => $this->value_float,
|
||||
'value_boolean' => $this->value_boolean,
|
||||
'value_date' => $this->value_date,
|
||||
'value_datetime' => $this->value_datetime,
|
||||
'value_text' => $this->value_text,
|
||||
'value_relasi' => $this->value_relasi,
|
||||
'value_enum' => $this->value_enum,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\Pertanian;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class JenisKomoditasResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'nama' => $this->nama,
|
||||
'kode' => $this->kode,
|
||||
'keterangan' => $this->keterangan,
|
||||
'created_at' => $this->created_at?->toIso8601String(),
|
||||
'updated_at' => $this->updated_at?->toIso8601String(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ class LahanResource extends JsonResource
|
||||
'luas_lahan' => $this->luas_lahan,
|
||||
'keluarga_pengelola_id' => $this->keluarga_pengelola_id,
|
||||
'adat_pemilik_id' => $this->adat_pemilik_id,
|
||||
'uid' => $this->uid,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ class TanamanResource extends JsonResource
|
||||
'latitude' => $this->latitude,
|
||||
'longitude' => $this->longitude,
|
||||
'kondisi_tanaman' => $this->kondisi_tanaman,
|
||||
'uid' => $this->uid,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
use App\Http\Resources\Wilayah\DesaKelurahanResource;
|
||||
use App\Http\Resources\UserResource;
|
||||
use phpDocumentor\Reflection\Types\This;
|
||||
|
||||
class ProfileResource extends JsonResource
|
||||
{
|
||||
@@ -31,6 +32,7 @@ class ProfileResource extends JsonResource
|
||||
'desa_kelurahan_id' => $this->desa_kelurahan_id,
|
||||
'desa_kelurahan' => $this->desaKelurahan ? new DesaKelurahanResource($this->desaKelurahan) : null,
|
||||
'user' => $this->user ? new UserResource($this->user) : null,
|
||||
'user_uid' => $this->user_uid,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ class UserResource extends JsonResource
|
||||
'email' => $this->email,
|
||||
'email_verified_at' => $this->email_verified_at,
|
||||
'role' => $this->role,
|
||||
'uid' => $this->uid,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ class Program extends Model
|
||||
"sub_domain",
|
||||
"tahun",
|
||||
"instansi",
|
||||
"nama_singkat",
|
||||
];
|
||||
|
||||
public function komoditas(): HasMany
|
||||
|
||||
@@ -0,0 +1,383 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Ekosistem;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use App\Models\Ekosistem\TabelBasisData;
|
||||
use App\Enums\LayoutForm;
|
||||
|
||||
class FormBasisData extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $table = 'ekosistem_basis_data_form';
|
||||
|
||||
protected $fillable = [
|
||||
'tabel_id',
|
||||
'parent_id',
|
||||
'tipe',
|
||||
'column_width',
|
||||
'kolom_id',
|
||||
'section_label',
|
||||
'urutan',
|
||||
'created_by',
|
||||
'updated_by',
|
||||
'deleted_by',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'tipe' => LayoutForm::class
|
||||
];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function ($model) {
|
||||
$max = self::where('tabel_id', $model->tabel_id)->max('urutan');
|
||||
$model->urutan = ($max ?? 0) + 1;
|
||||
});
|
||||
static::addGlobalScope('order', function (Builder $builder) {
|
||||
$builder->orderBy('urutan');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function tabel(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TabelBasisData::class, 'tabel_id');
|
||||
}
|
||||
|
||||
public function form(): HasMany
|
||||
{
|
||||
return $this->hasMany(FormBasisData::class, 'parent_id')
|
||||
->with('form')
|
||||
->orderBy('urutan');
|
||||
}
|
||||
|
||||
public function kolom(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(KolomBasisData::class, 'kolom_id');
|
||||
}
|
||||
|
||||
public function renderHtml(string $state, $errors = null, $optionsFK = null, $values = null, $framework = 'bootstrap'): string
|
||||
{
|
||||
if ($framework == 'tailwind') {
|
||||
return match ($this->tipe) {
|
||||
LayoutForm::COLUMN => '<div className="space-y-2 form-control-validation">'
|
||||
.$this->childHtml($state, $errors, $optionsFK, $values, $framework).'</div>',
|
||||
LayoutForm::VALUE => $this->value($state, $errors, $optionsFK, $values, $framework),
|
||||
LayoutForm::SECTION => '<h3 className="font-semibold text-lg text-slate-900">'.$this->section_label.'</h3>',
|
||||
LayoutForm::ROW => '<div className="grid grid-cols-1 gap-5">'.$this->childHtml($state, $errors, $optionsFK, $values, $framework).'</div>',
|
||||
LayoutForm::HR_LINE => '<hr/>',
|
||||
default => ''
|
||||
};
|
||||
} else {
|
||||
return match ($this->tipe) {
|
||||
LayoutForm::COLUMN => '<div class="col-'.($this->column_width ?? 3).' mb-4 form-control-validation">'
|
||||
.$this->childHtml($state, $errors, $optionsFK, $values, $framework).'</div>',
|
||||
LayoutForm::VALUE => $this->value($state, $errors, $optionsFK, $values, $framework),
|
||||
LayoutForm::SECTION => '<h6 class="mb-3">'.$this->section_label.'</h6>',
|
||||
LayoutForm::ROW => '<div class="row">'.$this->childHtml($state, $errors, $optionsFK, $values, $framework).'</div>',
|
||||
LayoutForm::HR_LINE => '<hr/>',
|
||||
default => ''
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function childHtml(string $state, $errors = null, $optionsFK = null, $values = null, $framework = 'bootstrap'): string
|
||||
{
|
||||
$html = '';
|
||||
foreach ($this->form as $form) {
|
||||
$html .= $form->renderHtml($state, $errors, $optionsFK, $values, $framework);
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function value(string $state, $errors = null, $optionsFK = null, $values = null, $framework = 'bootstrap'): string
|
||||
{
|
||||
$html = '';
|
||||
if ($this->kolom) {
|
||||
$k = $this->kolom;
|
||||
|
||||
$value = $values ? $values->where('kolom_id', $k->id)->first() : null;
|
||||
$oldValue = old($k->kolom);
|
||||
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Label htmlFor="label" className="text-sm font-medium text-slate-700">kolom_required'.$this->kolom->label;
|
||||
$html .= '</Label>';
|
||||
} else {
|
||||
$html .= '<label class="form-label" for="value-data-kolom_name">kolom_required'.$this->kolom->label;
|
||||
$html .= '</label>';
|
||||
}
|
||||
|
||||
if($k->tipe == 'varchar') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Input className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
} else {
|
||||
$html .= '<input type="text" class="form-control kolom_error" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
}
|
||||
}
|
||||
elseif($k->tipe == 'text') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Textarea className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
|
||||
name="kolom_name">kolom_value</Textarea>';
|
||||
} else {
|
||||
$html .= '<textarea class="form-control kolom_error" id="value-data-kolom_name" readonly
|
||||
name="kolom_name">kolom_value</textarea>';
|
||||
}
|
||||
}
|
||||
elseif($k->tipe == 'integer') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Input type="number" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" step="1" value="kolom_value" />';
|
||||
} else {
|
||||
$html .= '<input type="number" class="form-control" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" step="1" value="kolom_value" />';
|
||||
}
|
||||
}
|
||||
elseif($k->tipe == 'float') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Input className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" step="any" />';
|
||||
} else {
|
||||
$html .= '<input type="number" class="form-control kolom_error" id="add-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" step="any" />';
|
||||
}
|
||||
}
|
||||
elseif($k->tipe == 'date') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Input type="date" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
} else {
|
||||
$html .= '<input type="date" class="form-control kolom_error" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
}
|
||||
}
|
||||
elseif($k->tipe == 'datetime'){
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Input type="datetime-local" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
} else {
|
||||
$html .= '<input type="datetime-local" class="form-control kolom_error" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
}
|
||||
}
|
||||
elseif($k->tipe == 'boolean') {
|
||||
if ($state == 'preview' || $state == 'view') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Input type="text" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
} else {
|
||||
$html .= '<input type="text" class="form-control kolom_error" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
}
|
||||
} elseif ($state == 'add') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Select value="kolom_value">
|
||||
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="rounded-xl">
|
||||
<SelectItem value="1" className="rounded-lg">Ya</SelectItem>
|
||||
<SelectItem value="0" className="rounded-lg">Tidak</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>';
|
||||
} else {
|
||||
$html .= '<select class="form-select tipe-boolean kolom_error" id="value-data-kolom_name" name="kolom_name">
|
||||
<option value="1" '. (old($k->kolom) == 1 ? 'selected' : '') .'>Ya</option>
|
||||
<option value="0" '. (old($k->kolom) == 0 ? 'selected' : '') .'>Tidak</option>
|
||||
</select>';
|
||||
}
|
||||
} elseif ($state == 'edit') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Select value="kolom_value">
|
||||
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="rounded-xl">
|
||||
<SelectItem value="1" className="rounded-lg">Ya</SelectItem>
|
||||
<SelectItem value="0" className="rounded-lg">Tidak</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>';
|
||||
} else {
|
||||
$html .= '<select class="form-select tipe-boolean kolom_error" id="value-data-kolom_name" name="kolom_name">
|
||||
<option value="1" '. ((old($k->kolom) ?? (($value ? $value['value_'.$k->tipe] : null) ?? null) == 1) ? 'selected' : '') .'>Ya</option>
|
||||
<option value="0" '. ((old($k->kolom) ?? (($value ? $value['value_'.$k->tipe] : null) ?? null) == 0) ? 'selected' : '') .'>Tidak</option>
|
||||
</select>';
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($k->tipe == 'foreign_key') {
|
||||
if ($state == 'preview' || $state == 'view') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Input type="text" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
} else {
|
||||
$html .= '<input type="text" class="form-control kolom_error" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
}
|
||||
} elseif ($state == 'add') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Select value="kolom_value" id="value-data-kolom_name" name="kolom_name" className="form-select tipe-foreign_key kolom_error">
|
||||
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
|
||||
<SelectValue />
|
||||
</SelectTrigger>';
|
||||
if ($optionsFK && $optionsFK->where('kolom_id', $k->id)->first() != null) {
|
||||
foreach ($optionsFK->where('kolom_id', $k->id)->first()['options'] as $option) {
|
||||
$html .= '<SelectContent className="rounded-xl">
|
||||
<SelectItem value="'.$option->value.'" className="rounded-lg">'.$option->label.'</SelectItem>
|
||||
</SelectContent>';
|
||||
}
|
||||
}
|
||||
$html .= '</Select>';
|
||||
} else {
|
||||
$html .= '<select class="form-select tipe-foreign_key kolom_error" id="value-data-kolom_name" name="kolom_name">';
|
||||
if ($optionsFK && $optionsFK->where('kolom_id', $k->id)->first() != null) {
|
||||
foreach ($optionsFK->where('kolom_id', $k->id)->first()['options'] as $option) {
|
||||
$html .= '<option value="'.$option->value.'" '.(old($k->kolom) == $option->value ? 'selected' : '').'>'.$option->label.'</option>';
|
||||
}
|
||||
}
|
||||
$html .= '</select>';
|
||||
}
|
||||
} elseif ($state == 'edit') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Select value="kolom_value" id="value-data-kolom_name" name="kolom_name" className="form-select tipe-foreign_key kolom_error">
|
||||
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
|
||||
<SelectValue />
|
||||
</SelectTrigger>';
|
||||
if ($optionsFK && $optionsFK->where('kolom_id', $k->id)->first() != null) {
|
||||
foreach ($optionsFK->where('kolom_id', $k->id)->first()['options'] as $option) {
|
||||
$html .= '<SelectContent className="rounded-xl">
|
||||
<SelectItem value="'.$option->value.'" className="rounded-lg" '.(old($k->kolom) ?? ($value ? ($value['value_relasi'] == $option->value) : null) ? 'selected' : '') .'>'.$option->label.'</SelectItem>
|
||||
</SelectContent>';
|
||||
}
|
||||
}
|
||||
$html .= '</Select>';
|
||||
} else {
|
||||
$html .= '<select class="form-select tipe-foreign_key kolom_error" id="value-data-kolom_name" name="kolom_name">';
|
||||
if ($optionsFK && $optionsFK->where('kolom_id', $k->id)->first() != null) {
|
||||
foreach ($optionsFK->where('kolom_id', $k->id)->first()['options'] as $option) {
|
||||
$html .= '<option value="'.$option->value.'" '.(old($k->kolom) ?? ($value ? $value['value_relasi'] : null) == $option->value ? 'selected' : '').'>'.$option->label.'</option>';
|
||||
}
|
||||
}
|
||||
$html .= '</select>';
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($k->tipe == 'enum') {
|
||||
if ($state == 'preview' || $state == 'view') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Input type="text" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
} else {
|
||||
$html .= '<input type="text" class="form-control kolom_error" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
}
|
||||
} elseif ($state == 'add') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Select value="kolom_value" id="value-data-kolom_name" name="kolom_name" className="form-select tipe-enum kolom_error">
|
||||
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
|
||||
<SelectValue />
|
||||
</SelectTrigger>';
|
||||
foreach($k->enum_opsi as $opsi) {
|
||||
$html .= '<SelectContent className="rounded-xl">
|
||||
<SelectItem value="'.$opsi['value'].'" className="rounded-lg">'.$opsi['label'].'</SelectItem>
|
||||
</SelectContent>';
|
||||
}
|
||||
$html .= '</Select>';
|
||||
} else {
|
||||
$html .= '<select class="form-select tipe-enum kolom_error" id="value-data-kolom_name" name="kolom_name">';
|
||||
foreach($k->enum_opsi as $opsi) {
|
||||
$html .= '<option value="' .$opsi['value']. '" ' .(old($k->kolom) == $opsi['value'] ? 'selected' : ''). '>' .$opsi['label']. '</option>';
|
||||
}
|
||||
$html .= '</select>';
|
||||
}
|
||||
} elseif ($state == 'edit') {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Select value="kolom_value" id="value-data-kolom_name" name="kolom_name" className="form-select tipe-enum kolom_error">
|
||||
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
|
||||
<SelectValue />
|
||||
</SelectTrigger>';
|
||||
foreach($k->enum_opsi as $opsi) {
|
||||
$html .= '<SelectContent className="rounded-xl">
|
||||
<SelectItem value="'.$opsi['value'].'" className="rounded-lg">'.$opsi['label'].'</SelectItem>
|
||||
</SelectContent>';
|
||||
}
|
||||
$html .= '</Select>';
|
||||
} else {
|
||||
$html .= '<select class="form-select tipe-enum kolom_error" id="value-data-kolom_name" name="kolom_name">';
|
||||
foreach($k->enum_opsi as $opsi) {
|
||||
$html .= '<option value="' .$opsi['value']. '" ' .(old($k->kolom) ?? ($value ? $value['value_'.$k->tipe] : null) == $opsi['value'] ? 'selected' : ''). '>' .$opsi['label']. '</option>';
|
||||
}
|
||||
$html .= '</select>';
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($framework == 'tailwind') {
|
||||
$html .= '<Input type="text" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
} else {
|
||||
$html .= '<input type="text" class="form-control kolom_error" id="value-data-kolom_name" readonly
|
||||
name="kolom_name" value="kolom_value" />';
|
||||
}
|
||||
}
|
||||
|
||||
$errorClass = $errors && $errors->has($k->kolom)
|
||||
? 'is-invalid'
|
||||
: '';
|
||||
|
||||
if ($state == 'preview') {
|
||||
$html = Str::of($html)
|
||||
->replace('kolom_value', '')
|
||||
->replace('kolom_name', $k->kolom)
|
||||
->replace('kolom_error', '')
|
||||
->replace('kolom_required', '');
|
||||
} elseif ($state == 'add') {
|
||||
$html = Str::of($html)
|
||||
->replace('kolom_value', e($oldValue))
|
||||
->replace('kolom_name', $k->kolom)
|
||||
->replace('kolom_error', $errorClass)
|
||||
->replace('kolom_required', '')
|
||||
->replace('readonly', '');
|
||||
} elseif ($state == 'edit') {
|
||||
$html = Str::of($html)
|
||||
->replace('kolom_value', e($oldValue ?? ($value ? ($value['value_'.$k->tipe]) : null)))
|
||||
->replace('kolom_name', $k->kolom)
|
||||
->replace('kolom_error', $errorClass)
|
||||
->replace('kolom_required', '')
|
||||
->replace('readonly', '');
|
||||
} elseif ($state == 'view') {
|
||||
$html = Str::of($html)
|
||||
->replace('kolom_name', $k->kolom)
|
||||
->replace('kolom_error', '')
|
||||
->replace('kolom_required', '');
|
||||
|
||||
if ($k->tipe == 'boolean') {
|
||||
$html = Str::of($html)
|
||||
->replace('kolom_value', e($value ? ($value['value_'.$k->tipe] == 1 ? 'Ya' : 'Tidak') : null));
|
||||
} elseif($k->tipe == 'foreign_key') {
|
||||
$html = Str::of($html)
|
||||
->replace('kolom_value', e($value ? $value['value_relasi_label'] : null));
|
||||
} elseif($k->tipe == 'enum') {
|
||||
$html = Str::of($html)
|
||||
->replace('kolom_value', e($value ? $value['value_enum_label'] : null));
|
||||
} else {
|
||||
$html = Str::of($html)
|
||||
->replace('kolom_value', e($value ? $value['value_'.$k->tipe] : null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,14 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
|
||||
use App\Models\Ekosistem\KolomBasisData;
|
||||
use App\Models\Ekosistem\GroupBasisData;
|
||||
use App\Models\Ekosistem\RingkasanBasisData;
|
||||
use App\Models\Ekosistem\FormBasisData;
|
||||
|
||||
class TabelBasisData extends Model
|
||||
{
|
||||
@@ -53,4 +57,20 @@ class TabelBasisData extends Model
|
||||
{
|
||||
return $this->hasMany(RingkasanBasisData::class, 'tabel_id')->orderBy('urutan');
|
||||
}
|
||||
|
||||
public function form(): HasMany
|
||||
{
|
||||
return $this->hasMany(FormBasisData::class, 'tabel_id')
|
||||
->whereNull('parent_id')
|
||||
->orderBy('urutan');
|
||||
}
|
||||
|
||||
public function renderHtml(string $state, $errors = null, $optionsFK = null, $values = null): string
|
||||
{
|
||||
$html = '';
|
||||
foreach ($this->form as $form) {
|
||||
$html .= $form->renderHtml($state, $errors, $optionsFK, $values);
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ class Lahan extends Model
|
||||
'status_kepemilikan',
|
||||
'profile_id',
|
||||
'desa_kelurahan_id',
|
||||
'uid',
|
||||
'path',
|
||||
'luas_lahan',
|
||||
'created_by',
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Master;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use App\Models\Pertanian\Komoditas;
|
||||
|
||||
class JenisKomoditas extends Model
|
||||
{
|
||||
use HasFactory, SoftDeletes;
|
||||
|
||||
protected $table = 'jenis_komoditas';
|
||||
|
||||
protected $fillable = [
|
||||
'nama',
|
||||
'komoditas_id',
|
||||
'created_by',
|
||||
'updated_by',
|
||||
'deleted_by',
|
||||
];
|
||||
|
||||
public function komoditas()
|
||||
{
|
||||
return $this->belongsTo(Komoditas::class, 'komoditas_id');
|
||||
}
|
||||
|
||||
public function varietas()
|
||||
{
|
||||
return $this->hasMany(Varietas::class, 'jenis_komoditas_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Master;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use App\Models\Pertanian\Komoditas;
|
||||
use App\Models\Master\JenisKomoditas;
|
||||
|
||||
class Varietas extends Model
|
||||
{
|
||||
protected $table = 'master_varietas';
|
||||
|
||||
protected $fillable = [
|
||||
'komoditas_id',
|
||||
'jenis_komoditas_id',
|
||||
'nama',
|
||||
'deskripsi',
|
||||
'created_by',
|
||||
'updated_by',
|
||||
];
|
||||
|
||||
public function jenisKomoditas()
|
||||
{
|
||||
return $this->belongsTo(JenisKomoditas::class, 'jenis_komoditas_id');
|
||||
}
|
||||
|
||||
public function komoditas()
|
||||
{
|
||||
return $this->belongsTo(Komoditas::class, 'komoditas_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Pertanian;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class JenisKomoditas extends Model
|
||||
{
|
||||
use HasFactory, SoftDeletes;
|
||||
|
||||
/**
|
||||
* Nama tabel yang terkait dengan model ini.
|
||||
* Un-comment baris di bawah jika nama tabel di database tidak jamak (plural).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'jenis_komoditas';
|
||||
|
||||
/**
|
||||
* Atribut yang dapat diisi secara massal (mass assignable).
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'nama',
|
||||
'kode',
|
||||
'keterangan',
|
||||
];
|
||||
|
||||
/**
|
||||
* Atribut yang harus dikonversi ke tipe data lain (casting).
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* Relasi ke model Komoditas atau Tanaman (jika ada).
|
||||
* Contoh: Satu Jenis Komoditas memiliki banyak data Tanaman/Komoditas turunannya.
|
||||
*/
|
||||
public function tanaman(): HasMany
|
||||
{
|
||||
return $this->hasMany(Tanaman::class, 'jenis_komoditas_id', 'id');
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ namespace App\Models\Pertanian;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Models\Master\JenisKomoditas;
|
||||
use App\Models\Master\Varietas;
|
||||
|
||||
class Komoditas extends Model
|
||||
{
|
||||
@@ -30,4 +32,14 @@ class Komoditas extends Model
|
||||
$builder->whereIn('id', app('SystemProgram')->komoditas()->pluck('id'));
|
||||
});
|
||||
}
|
||||
|
||||
public function jenisKomoditas()
|
||||
{
|
||||
return $this->hasMany(JenisKomoditas::class, 'komoditas_id');
|
||||
}
|
||||
|
||||
public function varietas()
|
||||
{
|
||||
return $this->hasMany(Varietas::class, 'komoditas_id');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ class Lahan extends Model
|
||||
protected $table = 'map_lahan';
|
||||
|
||||
protected $fillable = [
|
||||
'uid',
|
||||
'nama',
|
||||
'status_kepemilikan',
|
||||
'profile_id',
|
||||
@@ -37,22 +38,22 @@ class Lahan extends Model
|
||||
'path' => 'array',
|
||||
];
|
||||
|
||||
public function profile()
|
||||
public function profile(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Profile::class, 'profile_id');
|
||||
}
|
||||
|
||||
public function desaKelurahan()
|
||||
public function desaKelurahan(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DesaKelurahan::class, 'desa_kelurahan_id');
|
||||
}
|
||||
|
||||
public function adat()
|
||||
public function adat(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Adat::class, 'adat_pemilik_id');
|
||||
}
|
||||
|
||||
public function tanaman()
|
||||
public function tanaman(): HasMany
|
||||
{
|
||||
return $this->hasMany(Tanaman::class, 'lahan_id');
|
||||
}
|
||||
|
||||
@@ -4,12 +4,11 @@ namespace App\Models\Pertanian;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use App\Models\Pertanian\Komoditas;
|
||||
use App\Models\Pertanian\Lahan;
|
||||
use App\Models\Profile;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
use App\Models\Pertanian\Lahan;
|
||||
use App\Models\Pertanian\Komoditas;
|
||||
use App\Models\Master\JenisKomoditas;
|
||||
use App\Models\Master\Varietas;
|
||||
|
||||
class Tanaman extends Model
|
||||
{
|
||||
@@ -18,13 +17,18 @@ class Tanaman extends Model
|
||||
protected $table = 'map_tanaman';
|
||||
|
||||
protected $fillable = [
|
||||
'uid',
|
||||
'nama',
|
||||
'jenis_komoditas_id',
|
||||
'varietas_id',
|
||||
'komoditas_id',
|
||||
'profile_id',
|
||||
'lahan_id',
|
||||
'latitude',
|
||||
'longitude',
|
||||
'kondisi_tanaman',
|
||||
'metode_pengumpulan',
|
||||
'deskripsi',
|
||||
'created_by',
|
||||
'updated_by',
|
||||
'deleted_by',
|
||||
@@ -35,6 +39,16 @@ class Tanaman extends Model
|
||||
return $this->belongsTo(Komoditas::class, 'komoditas_id');
|
||||
}
|
||||
|
||||
public function jenisKomoditas()
|
||||
{
|
||||
return $this->belongsTo(JenisKomoditas::class, 'jenis_komoditas_id');
|
||||
}
|
||||
|
||||
public function varietas()
|
||||
{
|
||||
return $this->belongsTo(Varietas::class, 'varietas_id');
|
||||
}
|
||||
|
||||
public function profile()
|
||||
{
|
||||
return $this->belongsTo(Profile::class, 'profile_id');
|
||||
|
||||
@@ -4,11 +4,9 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Pertanian\Lahan;
|
||||
use App\Models\Wilayah\DesaKelurahan;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Profile extends Model
|
||||
{
|
||||
@@ -17,13 +15,14 @@ class Profile extends Model
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'role',
|
||||
'user_uid',
|
||||
'nama',
|
||||
'email',
|
||||
'telepon',
|
||||
'alamat',
|
||||
'kk',
|
||||
'ktp',
|
||||
|
||||
'uid',
|
||||
'desa_kelurahan_id',
|
||||
'path_kk',
|
||||
'file_kk',
|
||||
@@ -44,9 +43,4 @@ class Profile extends Model
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
public function lahan(): HasMany
|
||||
{
|
||||
return $this->hasMany(Lahan::class, 'profile_id');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ class Aktivitas extends Model
|
||||
"indikator",
|
||||
"deskripsi",
|
||||
"transformasi_id",
|
||||
"parent_id",
|
||||
"created_by",
|
||||
"updated_by"
|
||||
];
|
||||
|
||||
public function transformasi(): BelongsTo
|
||||
@@ -32,6 +35,20 @@ class Aktivitas extends Model
|
||||
|
||||
public function target(): HasMany
|
||||
{
|
||||
return $this->hasMany(Target::class, 'aktivitas_id', 'id');
|
||||
return $this->hasMany(Target::class, 'aktivitas_id', 'id')
|
||||
->orderBy('id', 'asc');
|
||||
}
|
||||
|
||||
public function parent(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Aktivitas::class, 'parent_id', 'id');
|
||||
}
|
||||
|
||||
public function aktivitas(): HasMany
|
||||
{
|
||||
return $this->hasMany(Aktivitas::class, 'parent_id', 'id')
|
||||
->where('jenis_aktivitas', 'aktivitas')
|
||||
->orderBy('kode', 'asc')
|
||||
->orderBy('id', 'asc');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ class Framework extends Model
|
||||
"nama",
|
||||
"tahun",
|
||||
"program_id",
|
||||
"created_by",
|
||||
"updated_by",
|
||||
];
|
||||
|
||||
public function program(): BelongsTo
|
||||
@@ -29,6 +31,8 @@ class Framework extends Model
|
||||
|
||||
public function transformasi(): HasMany
|
||||
{
|
||||
return $this->hasMany(Transformasi::class, 'framework_id', 'id');
|
||||
return $this->hasMany(Transformasi::class, 'framework_id', 'id')
|
||||
->orderBy('kode', 'asc')
|
||||
->orderBy('id', 'asc');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Program;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
use App\Models\Program\Target;
|
||||
|
||||
class Realisasi extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $table = 'program_realisasi';
|
||||
|
||||
protected $fillable = [
|
||||
"target_id",
|
||||
"realisasi_integer",
|
||||
"realisasi_float",
|
||||
"realisasi_boolean",
|
||||
"created_by",
|
||||
"updated_by",
|
||||
"deleted_by",
|
||||
];
|
||||
|
||||
public function target(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Target::class, 'target_id', 'id');
|
||||
}
|
||||
|
||||
public function verifikasi(): HasMany
|
||||
{
|
||||
return $this->hasMany(Verifikasi::class, 'realisasi_id', 'id')->oldest();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ namespace App\Models\Program;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
|
||||
use App\Models\Program\Aktivitas;
|
||||
|
||||
@@ -27,10 +29,25 @@ class Target extends Model
|
||||
"realisasi_float",
|
||||
"realisasi_boolean",
|
||||
"aktivitas_id",
|
||||
"tipe_realisasi",
|
||||
"value_query",
|
||||
"created_by",
|
||||
"updated_by",
|
||||
"deleted_by",
|
||||
];
|
||||
|
||||
public function aktivitas(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Aktivitas::class, 'aktivitas_id', 'id');
|
||||
}
|
||||
|
||||
public function realisasi(): HasMany
|
||||
{
|
||||
return $this->hasMany(Realisasi::class, 'target_id', 'id')->latest();
|
||||
}
|
||||
|
||||
public function latestRealisasi(): HasOne
|
||||
{
|
||||
return $this->hasOne(Realisasi::class, 'target_id', 'id')->latest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,12 @@ class Transformasi extends Model
|
||||
return $this->belongsTo(Framework::class, 'framework_id', 'id');
|
||||
}
|
||||
|
||||
public function aktivitas(): HasMany
|
||||
public function tujuan(): HasMany
|
||||
{
|
||||
return $this->hasMany(Aktivitas::class, 'transformasi_id', 'id');
|
||||
return $this->hasMany(Aktivitas::class, 'transformasi_id', 'id')
|
||||
->whereNull('parent_id')
|
||||
->where('jenis_aktivitas', 'tujuan')
|
||||
->orderBy('kode', 'asc')
|
||||
->orderBy('id', 'asc');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Program;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
use App\Models\Program\Realisasi;
|
||||
|
||||
class Verifikasi extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $table = 'program_verifikasi';
|
||||
|
||||
protected $fillable = [
|
||||
"realisasi_id",
|
||||
"dokumen",
|
||||
"link_dokumen",
|
||||
"created_by",
|
||||
"updated_by",
|
||||
"deleted_by",
|
||||
];
|
||||
|
||||
public function realisasi(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Realisasi::class, 'realisasi_id', 'id');
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@ class User extends Authenticatable
|
||||
'password',
|
||||
'email_verified_at',
|
||||
'role',
|
||||
'username',
|
||||
'uid'
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\wilayah;
|
||||
namespace App\Models\Wilayah;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
@@ -67,7 +67,9 @@ class AppServiceProvider extends ServiceProvider
|
||||
});
|
||||
|
||||
View::composer('*', function ($view) {
|
||||
$tabel_menu = TabelBasisData::has('kolom')->get();
|
||||
$tabel_menu = TabelBasisData::whereHas('kolom', function ($query) {
|
||||
$query->where('is_active', true);
|
||||
})->get();
|
||||
|
||||
$view->with('tabel_menu', $tabel_menu);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
use App\Models\Wilayah\Provinsi;
|
||||
use App\Models\Wilayah\KabupatenKota;
|
||||
use App\Models\Wilayah\Kecamatan;
|
||||
use App\Models\Wilayah\DesaKelurahan;
|
||||
|
||||
class WilayahDashboard extends Component
|
||||
{
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
$kodeJawa = ['31', '32', '33', '34', '35', '36'];
|
||||
|
||||
$totalProvinsi = Provinsi::count();
|
||||
$totalKabKota = KabupatenKota::count();
|
||||
$totalKecamatan = Kecamatan::count();
|
||||
$totalDesaKelurahan = DesaKelurahan::count();
|
||||
|
||||
|
||||
$provinsiAktif = Provinsi::has('kabupatenKota')->count();
|
||||
|
||||
$provinsiKosong = $totalProvinsi - $provinsiAktif;
|
||||
|
||||
$totalKabupaten = KabupatenKota::whereRaw("SUBSTRING(kode, 3, 2) < '70'")->count();
|
||||
$totalKota = KabupatenKota::whereRaw("SUBSTRING(kode, 3, 2) >= '70'")->count();
|
||||
|
||||
if ($totalKabupaten == 0 && $totalKota == 0 && $totalKabKota > 0) {
|
||||
$totalKabupaten = $totalKabKota;
|
||||
}
|
||||
|
||||
$kecamatanPerdesaan = Kecamatan::whereHas('kabupatenKota', function($query) {
|
||||
$query->whereRaw("SUBSTRING(kode, 3, 2) < '70'");
|
||||
})->count();
|
||||
|
||||
$kecamatanPerkotaan = max(0, $totalKecamatan - $kecamatanPerdesaan);
|
||||
|
||||
$terpetakan = DesaKelurahan::whereNotNull('path')->count();
|
||||
$belumTerpetakan = max(0, $totalDesaKelurahan - $terpetakan);
|
||||
|
||||
$totalDesa = DesaKelurahan::where('nama', 'like', 'DESA%')->count() ?: $totalDesaKelurahan;
|
||||
$totalKelurahan = DesaKelurahan::where('nama', 'like', 'KEL%')->count();
|
||||
|
||||
$data = [
|
||||
'totalProvinsi' => $totalProvinsi,
|
||||
'provinsiAktif' => $provinsiAktif,
|
||||
'provinsiKosong' => $provinsiKosong,
|
||||
|
||||
'totalKabKota' => $totalKabKota,
|
||||
'totalKabupaten' => $totalKabupaten,
|
||||
'totalKota' => $totalKota,
|
||||
|
||||
'totalKecamatan' => $totalKecamatan,
|
||||
'kecamatanPerdesaan' => $kecamatanPerdesaan,
|
||||
'kecamatanPerkotaan' => $kecamatanPerkotaan,
|
||||
|
||||
'totalDesaKelurahan' => $totalDesaKelurahan,
|
||||
'totalDesa' => $totalDesa,
|
||||
'totalKelurahan' => $totalKelurahan,
|
||||
'terpetakan' => $terpetakan,
|
||||
'belumTerpetakan' => $belumTerpetakan,
|
||||
];
|
||||
|
||||
return view('components.wilayah-dashboard', $data);
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,10 @@ return new class extends Migration
|
||||
{
|
||||
Schema::create('users', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uid')->unique();
|
||||
$table->string('name');
|
||||
$table->string('email')->unique();
|
||||
$table->string('username')->unique();
|
||||
$table->string('email')->unique()->nullable();
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->string('password');
|
||||
$table->rememberToken();
|
||||
@@ -23,17 +25,6 @@ return new class extends Migration
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
// Schema::create('user_roles', function (Blueprint $table) {
|
||||
// $table->id();
|
||||
// $table->foreignId('user_id')->unique()->constrained('users')->onDelete('cascade');
|
||||
// $table->enum('role_name', ['Super Admin', 'Admin', 'Koordinator', 'Penyuluh', 'Pendamping', 'Petani'])->default('Petani');
|
||||
// $table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
// $table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
// $table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
// $table->timestamps();
|
||||
// $table->softDeletes();
|
||||
// });
|
||||
|
||||
Schema::create('password_reset_tokens', function (Blueprint $table) {
|
||||
$table->string('email')->primary();
|
||||
$table->string('token');
|
||||
@@ -53,7 +44,6 @@ return new class extends Migration
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('users');
|
||||
// Schema::dropIfExists('user_roles');
|
||||
Schema::dropIfExists('password_reset_tokens');
|
||||
Schema::dropIfExists('sessions');
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ return new class extends Migration
|
||||
$table->string('file_kk')->nullable();
|
||||
$table->string('path_ktp', 500)->nullable();
|
||||
$table->string('file_ktp')->nullable();
|
||||
$table->string('user_uid');
|
||||
|
||||
$table->foreignId('keluarga_id')->nullable()->constrained('keluarga')->onDelete('set null');
|
||||
|
||||
|
||||
@@ -22,13 +22,39 @@ return new class extends Migration
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
Schema::create('jenis_komoditas', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('komoditas_id')->constrained('master_komoditas')->onDelete('cascade');
|
||||
$table->string('nama');
|
||||
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Schema::create('master_varietas', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('komoditas_id')->constrained('master_komoditas')->onDelete('cascade');
|
||||
$table->foreignId('jenis_komoditas_id')->constrained('jenis_komoditas')->onDelete('cascade');
|
||||
$table->string('nama');
|
||||
$table->text('deskripsi')->unique();
|
||||
|
||||
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('master_varietas');
|
||||
Schema::dropIfExists('jenis_komoditas');
|
||||
Schema::dropIfExists('master_komoditas');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ return new class extends Migration
|
||||
{
|
||||
Schema::create('map_lahan', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uid')->unique();
|
||||
$table->string('nama');
|
||||
$table->string('status_kepemilikan');
|
||||
|
||||
@@ -21,7 +22,13 @@ return new class extends Migration
|
||||
$table->foreignId('adat_pemilik_id')->nullable()->constrained('adat')->onDelete('set null');
|
||||
|
||||
$table->foreignId('desa_kelurahan_id')->nullable()->constrained('master_desa_kelurahan');
|
||||
$table->text('path')->nullable();
|
||||
$table->string('lat')->nullable();
|
||||
$table->string('long')->nullable();
|
||||
$table->jsonb('path')->nullable();
|
||||
|
||||
$table->boolean('sertifikat')->default(false);
|
||||
$table->boolean('konflik')->default(false);
|
||||
$table->text('deskripsi')->nullable();
|
||||
|
||||
$table->float('luas_lahan', 8)->nullable();
|
||||
|
||||
@@ -33,11 +40,32 @@ return new class extends Migration
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Schema::create('sertifikat_lahan', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uid')->unique();
|
||||
$table->string('nomor_sertifikat');
|
||||
$table->date('tanggal_terbit');
|
||||
$table->date('tanggal_kadaluarsa')->nullable();
|
||||
$table->string('lembaga_penerbit')->nullable();
|
||||
|
||||
$table->foreignId('lahan_id')->constrained('map_lahan')->onDelete('cascade');
|
||||
|
||||
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Schema::create('map_tanaman', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uid')->unique();
|
||||
$table->string('nama');
|
||||
|
||||
$table->foreignId('komoditas_id')->constrained('master_komoditas')->onDelete('set null');
|
||||
$table->foreignId('jenis_komoditas_id')->constrained('jenis_komoditas')->onDelete('set null');
|
||||
$table->foreignId('varietas_id')->constrained('master_varietas')->onDelete('set null');
|
||||
$table->foreignId('profile_id')->constrained('profiles')->onDelete('set null');
|
||||
$table->foreignId('lahan_id')->constrained('map_lahan')->onDelete('set null');
|
||||
|
||||
@@ -45,6 +73,8 @@ return new class extends Migration
|
||||
$table->float('longitude')->nullable();
|
||||
|
||||
$table->string('kondisi_tanaman')->nullable();
|
||||
$table->string('metode_pengumpulan')->nullable();
|
||||
$table->text('deskripsi')->nullable();
|
||||
|
||||
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
@@ -61,6 +91,7 @@ return new class extends Migration
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('map_tanaman');
|
||||
Schema::dropIfExists('sertifikat_lahan');
|
||||
Schema::dropIfExists('map_lahan');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('map_lahan', function (Blueprint $table) {
|
||||
$table->jsonb('path')->nullable()->change();
|
||||
});
|
||||
|
||||
Schema::table('master_provinsi', function (Blueprint $table) {
|
||||
$table->jsonb('path')->nullable()->change();
|
||||
});
|
||||
|
||||
Schema::table('master_kabupaten_kota', function (Blueprint $table) {
|
||||
$table->jsonb('path')->nullable()->change();
|
||||
});
|
||||
|
||||
Schema::table('master_kecamatan', function (Blueprint $table) {
|
||||
$table->jsonb('path')->nullable()->change();
|
||||
});
|
||||
|
||||
Schema::table('master_desa_kelurahan', function (Blueprint $table) {
|
||||
$table->jsonb('path')->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
@@ -18,6 +18,7 @@ return new class extends Migration
|
||||
$table->string('sub_domain');
|
||||
$table->integer('tahun');
|
||||
$table->string('instansi')->nullable();
|
||||
$table->string('nama_singkat', length: 50);
|
||||
|
||||
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
|
||||
@@ -29,9 +29,15 @@ return new class extends Migration
|
||||
$table->foreignId('tabel_id')->constrained('ekosistem_basis_data_tabel')->restrictOnDelete();
|
||||
$table->string('kolom');
|
||||
$table->string('label');
|
||||
$table->enum('tipe', ['varchar', 'integer', 'float', 'boolean', 'date', 'datetime', 'text'])->default('varchar');
|
||||
$table->enum('tipe', ['varchar', 'integer', 'float', 'boolean', 'date', 'datetime', 'text', 'foreign_key', 'enum'])->default('varchar');
|
||||
$table->jsonb('validasi')->nullable();
|
||||
$table->integer('urutan')->default(1);
|
||||
$table->string('relasi_tabel')->nullable();
|
||||
$table->string('relasi_kolom_id')->nullable();
|
||||
$table->string('relasi_kolom_label')->nullable();
|
||||
$table->boolean('is_active')->default('true');
|
||||
$table->boolean('is_browse')->default('false');
|
||||
$table->jsonb('enum_opsi')->nullable();
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
@@ -60,6 +66,8 @@ return new class extends Migration
|
||||
$table->date('value_date')->nullable();
|
||||
$table->datetime('value_datetime')->nullable();
|
||||
$table->text('value_text')->nullable();
|
||||
$table->integer('value_relasi')->nullable();
|
||||
$table->string('value_enum')->nullable();
|
||||
|
||||
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('profiles', function (Blueprint $table) {
|
||||
$table->foreignId('adat_id')->nullable()->constrained('adat');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -13,9 +13,11 @@ return new class extends Migration
|
||||
{
|
||||
Schema::create('ekosistem_petani_cpm', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->string('uid')->unique();
|
||||
$table->foreignId('program_id')->nullable()->constrained('core_program')->nullOnDelete();
|
||||
$table->string('nama');
|
||||
$table->boolean('jenis_kelamin');
|
||||
$table->string('tempat_lahir')->nullable();
|
||||
$table->date('tanggal_lahir');
|
||||
|
||||
$table->string('pendidikan_terakhir')->nullable();
|
||||
@@ -28,11 +30,17 @@ return new class extends Migration
|
||||
$table->float('lama_bertani', 8)->nullable();
|
||||
$table->float('luas_lahan', 8)->nullable();
|
||||
|
||||
$table->string('dusun_rt_rw')->nullable();
|
||||
$table->string('nomor_telepon')->nullable();
|
||||
$table->string('foto')->nullable();
|
||||
|
||||
$table->string('pekerjaan_sampingan')->nullable();
|
||||
$table->foreignId('komoditas_sampingan_id')->nullable()->constrained('master_komoditas');
|
||||
$table->float('lama_bertani_sampingan', 8)->nullable();
|
||||
$table->float('luas_lahan_sampingan', 8)->nullable();
|
||||
|
||||
|
||||
|
||||
$table->string('status_perkawinan')->nullable();
|
||||
$table->string('status_keluarga')->nullable();
|
||||
$table->integer('jumlah_tanggungan')->nullable();
|
||||
@@ -48,9 +56,6 @@ return new class extends Migration
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('ekosistem_petani_cpm');
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('ekosistem_basis_data_kolom', function (Blueprint $table) {
|
||||
$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;");
|
||||
DB::statement("
|
||||
alter table public.ekosistem_basis_data_kolom add constraint ekosistem_basis_data_kolom_tipe_check check (((tipe)::text = any
|
||||
((array[
|
||||
'varchar'::character varying,
|
||||
'integer'::character varying,
|
||||
'float'::character varying,
|
||||
'boolean'::character varying,
|
||||
'date'::character varying,
|
||||
'datetime'::character varying,
|
||||
'text'::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();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -13,6 +13,7 @@ return new class extends Migration
|
||||
{
|
||||
Schema::create('ekosistem_lahan_cpcl', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uid')->unique();
|
||||
$table->string('nama');
|
||||
$table->string('status_kepemilikan');
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('ekosistem_basis_data_kolom', function (Blueprint $table) {
|
||||
$table->boolean('is_active')->default('true');
|
||||
$table->boolean('is_browse')->default('false');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('ekosistem_basis_data_form', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->foreignId('tabel_id')->constrained('ekosistem_basis_data_tabel')->restrictOnDelete();
|
||||
|
||||
$table->foreignId('parent_id')->nullable()->constrained('ekosistem_basis_data_form')->restrictOnDelete();
|
||||
|
||||
$table->enum('tipe', ['form-row', 'form-column', 'form-value', 'form-section', 'form-hr-line'])->default('form-value');
|
||||
|
||||
$table->integer('column_width')->nullable();
|
||||
|
||||
$table->foreignId('kolom_id')->nullable()->constrained('ekosistem_basis_data_kolom')->nullOnDelete();
|
||||
|
||||
$table->string('section_label')->nullable();
|
||||
|
||||
$table->integer('urutan')->default(1);
|
||||
|
||||
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('ekosistem_basis_data_form');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('program_aktivitas', function (Blueprint $table) {
|
||||
$table->foreignId('parent_id')->nullable()->constrained('program_aktivitas')->nullOnDelete();
|
||||
});
|
||||
|
||||
Schema::table('program_target', function (Blueprint $table) {
|
||||
$table->enum('tipe_realisasi', ['manual', 'referensi'])->default('manual');
|
||||
$table->text('value_query')->nullable();
|
||||
});
|
||||
|
||||
Schema::table('program_verifikasi', function (Blueprint $table) {
|
||||
$table->foreignId('realisasi_id')->nullable()->constrained('program_realisasi')->nullOnDelete();
|
||||
$table->dropColumn('aktivitas_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
@@ -15,7 +15,9 @@ class AdminUserSeeder extends Seeder
|
||||
public function run(): void
|
||||
{
|
||||
DB::table('users')->insert([
|
||||
'uid' => 'AD-1234567891',
|
||||
'name' => 'Admin',
|
||||
'username' => 'admin',
|
||||
'email' => 'admin@example.com',
|
||||
'email_verified_at' => now(),
|
||||
'password' => Hash::make('Asalada123'),
|
||||
@@ -24,7 +26,7 @@ class AdminUserSeeder extends Seeder
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
Db::table('profiles')->insert([
|
||||
DB::table('profiles')->insert([
|
||||
'user_id' => 1,
|
||||
'role' => 'super_admin',
|
||||
'nama' => 'Admin',
|
||||
@@ -43,7 +45,7 @@ class AdminUserSeeder extends Seeder
|
||||
'updated_by' => 1,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
'adat_id' => null,
|
||||
'user_uid' => 'AD-1234567891',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ class DatabaseSeeder extends Seeder
|
||||
User::factory()->create([
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
'uid' => 'AD-1234567890',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 203 KiB |
@@ -4,7 +4,7 @@
|
||||
<div class="card-body">
|
||||
<!-- Logo -->
|
||||
<div class="app-brand justify-content-center mb-6">
|
||||
<a href="{{ route('dashboard.produktivitas') }}" class="app-brand-link">
|
||||
<a href="{{ route('dashboard.summary') }}" class="app-brand-link">
|
||||
<span class="app-brand-logo demo">
|
||||
<span class="text-primary">
|
||||
<svg width="32" height="24" viewBox="0 0 32 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
@props(['title', 'mainCount', 'icon', 'color' => 'primary', 'subLabel1', 'subCount1', 'subLabel2', 'subCount2'])
|
||||
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body p-3">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<div>
|
||||
<p class="text-muted fw-medium mb-1 small text-uppercase">{{ $title }}</p>
|
||||
<h3 class="mb-0 fw-bold text-secondary">{{ number_format($mainCount, 0, ',', '.') }}</h3>
|
||||
</div>
|
||||
<div class="badge bg-label-{{ $color }} p-2 rounded">
|
||||
<i class="ti tabler-{{ $icon }}" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-lighter rounded p-2 mt-auto">
|
||||
<div class="row text-center gx-0">
|
||||
<div class="col-6 border-end">
|
||||
<span class="text-muted d-block" style="font-size: 0.75rem;">{{ $subLabel1 }}</span>
|
||||
<span class="fw-semibold text-dark small">{{ number_format($subCount1, 0, ',', '.') }}</span>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<span class="text-muted d-block" style="font-size: 0.75rem;">{{ $subLabel2 }}</span>
|
||||
<span class="fw-semibold text-dark small">{{ number_format($subCount2, 0, ',', '.') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,50 @@
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-12 col-sm-6 col-xl-3">
|
||||
<x-wilayah-card
|
||||
title="TOTAL PROVINSI"
|
||||
:mainCount="$totalProvinsi"
|
||||
icon="map-pin"
|
||||
color="primary"
|
||||
subLabel1="Data Aktif"
|
||||
:subCount1="$provinsiAktif"
|
||||
subLabel2="Data Kosong"
|
||||
:subCount2="$provinsiKosong"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 col-xl-3">
|
||||
<x-wilayah-card
|
||||
title="Kabupaten & Kota"
|
||||
mainCount="{{ $totalKabKota }}"
|
||||
icon="building-skyscraper"
|
||||
color="info"
|
||||
subLabel1="Kabupaten"
|
||||
subCount1="{{ $totalKabupaten }}"
|
||||
subLabel2="Kota"
|
||||
subCount2="{{ $totalKota }}"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 col-xl-3">
|
||||
<x-wilayah-card
|
||||
title="TOTAL KECAMATAN"
|
||||
:mainCount="$totalKecamatan"
|
||||
icon="map-pin"
|
||||
color="warning"
|
||||
subLabel1="Zona Perdesaan"
|
||||
:subCount1="$kecamatanPerdesaan"
|
||||
subLabel2="Zona Perkotaan"
|
||||
:subCount2="$kecamatanPerkotaan"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 col-xl-3">
|
||||
<x-wilayah-card
|
||||
title="DESA & KELURAHAN"
|
||||
:mainCount="$totalDesaKelurahan"
|
||||
icon="home-2"
|
||||
color="success"
|
||||
subLabel1="Terpetakan"
|
||||
:subCount1="$terpetakan"
|
||||
subLabel2="Blm Pemetaan"
|
||||
:subCount2="$belumTerpetakan"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -18,6 +18,12 @@
|
||||
<input type="text" class="form-control" id="add-program-nama" name="nama" placeholder="Cth: Program Pertanian" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-nama-singkat">Nama Singkat<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-program-nama-singkat" name="nama_singkat" placeholder="Cth: PP" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-subdomain">Sub Domain<span class="text-danger">*</span></label>
|
||||
@@ -51,12 +57,14 @@
|
||||
rules: {
|
||||
nama: { required: true },
|
||||
sub_domain: { required: true },
|
||||
tahun: { required: true }
|
||||
tahun: { required: true },
|
||||
nama_singkat: { required: true }
|
||||
},
|
||||
messages: {
|
||||
nama: { required: "Nama program wajib diisi" },
|
||||
sub_domain: { required: "Subdomain wajib diisi" },
|
||||
tahun: { required: "Tahun wajib diisi" }
|
||||
tahun: { required: "Tahun wajib diisi" },
|
||||
nama_singkat: { required: "Nama singkat wajib diisi" }
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
<input type="text" class="form-control" id="add-program-nama" name="nama" placeholder="Cth: Program Pertanian" value="{{ old('nama', $program->nama) }}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-nama-singkat">Nama Singkat<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-program-nama-singkat" name="nama_singkat" placeholder="Cth: PP" value="{{ old('nama_singkat', $program->nama_singkat) }}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-subdomain">Sub Domain<span class="text-danger">*</span></label>
|
||||
@@ -56,12 +62,14 @@
|
||||
rules: {
|
||||
nama: { required: true },
|
||||
sub_domain: { required: true },
|
||||
tahun: { required: true }
|
||||
tahun: { required: true },
|
||||
nama_singkat: { required: true }
|
||||
},
|
||||
messages: {
|
||||
nama: { required: "Nama program wajib diisi" },
|
||||
sub_domain: { required: "Subdomain wajib diisi" },
|
||||
tahun: { required: "Tahun wajib diisi" }
|
||||
tahun: { required: "Tahun wajib diisi" },
|
||||
nama_singkat: { required: "Nama singkat wajib diisi" }
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
<input type="text" class="form-control" id="add-program-nama" name="nama" placeholder="Cth: Program Pertanian" value="{{ old('nama', $program->nama) }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-nama-singkat">Nama Singkat<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-program-nama-singkat" name="nama_singkat" placeholder="Cth: PP" value="{{ old('nama_singkat', $program->nama_singkat) }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-subdomain">Sub Domain<span class="text-danger">*</span></label>
|
||||
|
||||
@@ -1,619 +0,0 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@push('style')
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||
<style>
|
||||
body { background-color: #f8faf9; font-family: 'Public Sans', sans-serif; }
|
||||
|
||||
.card { border: none; border-radius: 15px; box-shadow: 0 4px 20px rgba(0,0,0,0.05); }
|
||||
|
||||
/* Map Container */
|
||||
#map { height: 600px; width: 100%; border-radius: 15px; }
|
||||
|
||||
/* Sidebar Mini Stats */
|
||||
.stat-card-mini { transition: all 0.3s ease; border-left: 5px solid transparent; }
|
||||
.stat-card-mini:hover { transform: translateX(5px); border-left-color: var(--agri-green); }
|
||||
|
||||
/* Map Switcher Manual */
|
||||
.map-controls-custom {
|
||||
position: absolute; top: 20px; right: 20px; z-index: 1000;
|
||||
background: white; padding: 5px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
/* Table Styling */
|
||||
.table thead th { background-color: #f8f9fa; text-transform: uppercase; font-size: 11px; letter-spacing: 1px; }
|
||||
.avatar-label { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; border-radius: 10px; font-weight: bold; }
|
||||
|
||||
.leaflet-tooltip.leaflet-modern-tooltip {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
color: #333;
|
||||
font-family: 'Public Sans', sans-serif; /* Pastikan font dashboard Anda */
|
||||
}
|
||||
|
||||
/* Menghilangkan panah kecil di bawah tooltip */
|
||||
.leaflet-modern-tooltip:before {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
/* 2. Gaya untuk Modern Map Card kita */
|
||||
.modern-map-card {
|
||||
background: #ffffff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);
|
||||
padding: 16px;
|
||||
width: 190px; /* Lebar card */
|
||||
border: 1px solid rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
/* Bagian Header */
|
||||
.card-header-region {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.region-label {
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
color: #888;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.5px;
|
||||
display: block;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.region-name {
|
||||
font-weight: 700;
|
||||
font-size: 15px;
|
||||
margin: 0;
|
||||
color: #1e1e1e;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* Bagian Stats Row (Flexbox untuk menyusun ikon & teks) */
|
||||
.d-flex { display: flex; }
|
||||
.align-items-center { align-items: center; }
|
||||
.mb-2 { margin-bottom: 8px; }
|
||||
.me-2 { margin-right: 10px; }
|
||||
.fw-bold { font-weight: 700; }
|
||||
.small { font-size: 12px; }
|
||||
|
||||
/* Gaya Ikon Baris Statistik */
|
||||
.stat-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Warna Latar Belakang Ringan untuk Ikon (Bootstrap style) */
|
||||
.bg-success-light { background-color: rgba(40, 167, 69, 0.1); }
|
||||
.bg-primary-light { background-color: rgba(0, 123, 255, 0.1); }
|
||||
.text-success { color: #28a745; }
|
||||
.text-primary { color: #007bff; }
|
||||
|
||||
.stat-info {
|
||||
flex: 1;
|
||||
}
|
||||
.stat-value {
|
||||
font-size: 14px;
|
||||
color: #222;
|
||||
line-height: 1;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.text-muted { color: #6c757d; }
|
||||
|
||||
/* Bagian Footer Action */
|
||||
.action-prompt {
|
||||
font-size: 12px;
|
||||
}
|
||||
/* Sedikit animasi pada chevron saat di-hover */
|
||||
.action-prompt i {
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.leaflet-modern-tooltip:hover .action-prompt i {
|
||||
transform: translateX(3px);
|
||||
}
|
||||
|
||||
/* Gaya Bootstrap Helper Ringan (untuk jaga-jaga jika dashboard tidak memuatnya) */
|
||||
.border-top { border-top: 1px solid rgba(0,0,0,0.08) !important; }
|
||||
.border-bottom { border-bottom: 1px solid rgba(0,0,0,0.08) !important; }
|
||||
.py-2 { padding-top: 8px !important; padding-bottom: 8px !important; }
|
||||
.my-2 { margin-top: 8px !important; margin-bottom: 8px !important; }
|
||||
|
||||
.leaflet-popup-wrapper.leaflet-modern-popup-wrapper {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.leaflet-modern-popup-wrapper .leaflet-popup-content-wrapper {
|
||||
border-radius: 12px;
|
||||
padding: 0 !important; /* Hapus padding default Leaflet agar full width */
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
|
||||
border: 1px solid rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.leaflet-modern-popup-wrapper .leaflet-popup-content {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
/* Penyesuaian panah kecil di bawah */
|
||||
.leaflet-modern-popup-wrapper .leaflet-popup-tip {
|
||||
background: #f8f9fa; /* Sesuaikan dengan warna body footer popup (bg-light) */
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
/* 2. Gaya untuk Modern Lahan Popup kita */
|
||||
.modern-lahan-popup {
|
||||
font-family: 'Public Sans', sans-serif;
|
||||
min-width: 270px; /* Lebar card */
|
||||
}
|
||||
|
||||
/* Typography Hierarki */
|
||||
.modern-lahan-popup .h5 { font-size: 16px; margin: 0; }
|
||||
.modern-lahan-popup .fs-5 { font-size: 1.25rem; }
|
||||
.modern-lahan-popup small { font-size: 11px; }
|
||||
|
||||
/* Header Farmer */
|
||||
.rounded-top-12 { border-radius: 12px 12px 0 0; }
|
||||
.header-farmer {
|
||||
border-bottom: 1px solid rgba(0,0,0,0.06);
|
||||
}
|
||||
.label-header {
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.farmer-name {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* Body Details */
|
||||
.details-body {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.rounded-bottom-12 { border-radius: 0 0 12px 12px; }
|
||||
|
||||
.label-detail {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.value-detail {
|
||||
font-size: 14px;
|
||||
margin-top: 1px;
|
||||
line-height: 1.1;
|
||||
}
|
||||
.value-commodity {
|
||||
font-size: 13px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* Ikon Container (derived from stats card style) */
|
||||
.icon-stat-container {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Helper Colors (for icons & backgrounds) */
|
||||
.text-danger-light { color: #dc3545 !important; }
|
||||
.text-danger { color: #dc3545 !important; }
|
||||
.text-success { color: #28a745 !important; }
|
||||
|
||||
/* Background Ringan (Bootstrap Style) */
|
||||
.text-success-light { background-color: rgba(40, 167, 69, 0.1) !important; }
|
||||
.text-danger-light { background-color: rgba(220, 53, 69, 0.1) !important; }
|
||||
.bg-primary-light { background-color: rgba(0, 123, 255, 0.1) !important; }
|
||||
|
||||
/* Bootstrap-like Utilities (untuk berjaga-jaga jika dash belum memuatnya) */
|
||||
.me-2 { margin-right: 10px !important; }
|
||||
.mb-3 { margin-bottom: 16px !important; }
|
||||
.ps-2 { padding-left: 12px !important; }
|
||||
.col-6 { width: 50%; }
|
||||
.col-12 { width: 100%; }
|
||||
.border { border: 1px solid rgba(0,0,0,0.08) !important; }
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<div class="card mb-3 stat-card-mini">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="avatar bg-label-success rounded p-2"><i class="ti tabler-mountain fs-3"></i></div>
|
||||
<!-- <span class="badge bg-label-success">+2.4%</span> -->
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<small class="text-muted text-uppercase">Total Land Area</small>
|
||||
<h4 class="mb-0 fw-bold">{{ number_format($luasTotal, 1) }} <small class="text-muted">ha</small></h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3 stat-card-mini">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="avatar bg-label-success rounded p-2"><i class="ti tabler-map fs-3"></i></div>
|
||||
<!-- <span class="badge bg-label-success"></span> -->
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<small class="text-muted text-uppercase">Total Lahan</small>
|
||||
<h4 class="mb-0 fw-bold">{{ $totallahan }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3 stat-card-mini">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="avatar bg-label-primary rounded p-2"><i class="ti tabler-users fs-3"></i></div>
|
||||
<span class="badge bg-success text-white text-center">Active</span>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<small class="text-muted text-uppercase">Registered Farmers</small>
|
||||
<h4 class="mb-0 fw-bold">{{ $totalpetani }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header"><h6 class="mb-0 fw-bold">Distribusi Komoditas</h6></div>
|
||||
<div class="card-body">
|
||||
@foreach(['Vanilla' => 45, 'Candlenut' => 30, 'Cocoa' => 15, 'Coffee' => 10] as $name => $val)
|
||||
<div class="mb-3">
|
||||
<div class="d-flex justify-content-between mb-1">
|
||||
<small class="fw-bold">{{ $name }}</small>
|
||||
<small class="text-muted">{{ $val }}%</small>
|
||||
</div>
|
||||
<div class="progress" style="height: 6px;">
|
||||
<div class="progress-bar bg-success" style="width: {{ $val }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-9">
|
||||
<div class="card mb-4 overflow-hidden position-relative">
|
||||
<div class="card-header d-flex justify-content-between align-items-center bg-white py-3">
|
||||
<h6 class="mb-0 fw-bold"><i class="ti tabler-map-2 me-2"></i>Peta Sebaran Lahan</h6>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button class="btn btn-outline-secondary active" onclick="setMapLayer('satellite')">Satellite</button>
|
||||
<button class="btn btn-outline-secondary" onclick="setMapLayer('topo')">Topographic</button>
|
||||
<button class="btn btn-outline-secondary" onclick="setMapLayer('parcels')">Parcels</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="map">
|
||||
<button id="btnBackMap" class="btn btn-sm btn-dark shadow" style="display:none; position:absolute; top:20px; left:50px; z-index:1000;">
|
||||
<i class="ti tabler-arrow-left me-1"></i> Kembali ke Atas
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-0 fw-bold">Produktivitas Petani Regional</h6>
|
||||
<button class="btn btn-sm btn-success"><i class="ti tabler-plus me-1"></i> Bulk Action</button>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nama Petani</th>
|
||||
<th>ID Lahan</th>
|
||||
<th>Komoditas</th>
|
||||
<th>Luas (HA)</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($petaniList as $p)
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="avatar-label bg-label-secondary me-2">{{ substr($p->nama, 0, 1) }}</div>
|
||||
<span class="fw-bold">{{ $p->nama }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="text-muted small">TR-{{ $p->id }}</span></td>
|
||||
<td><span class="badge bg-label-info">Vanilla</span></td>
|
||||
<td class="fw-bold">{{ number_format($p->lahan->sum('luas_lahan'), 1) }}</td>
|
||||
<td><span class="badge bg-success">Verified</span></td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script>
|
||||
var satellite = L.tileLayer('https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', { maxZoom: 22 });
|
||||
var topo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png');
|
||||
var parcels = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png');
|
||||
|
||||
var map = L.map('map', { center: [-0.789, 113.921], zoom: 5, layers: [satellite], zoomControl: false });
|
||||
L.control.zoom({ position: 'topleft' }).addTo(map);
|
||||
|
||||
function setMapLayer(type) {
|
||||
map.removeLayer(satellite); map.removeLayer(topo); map.removeLayer(parcels);
|
||||
if(type === 'satellite') satellite.addTo(map);
|
||||
if(type === 'topo') topo.addTo(map);
|
||||
if(type === 'parcels') parcels.addTo(map);
|
||||
event.target.parentElement.querySelectorAll('.btn').forEach(b => b.classList.remove('active'));
|
||||
event.target.classList.add('active');
|
||||
}
|
||||
|
||||
// 2. Data dari Server
|
||||
var dataLevels = {
|
||||
'provinsi': @json($geoProvinsi),
|
||||
'kabupaten': @json($geoKabupaten),
|
||||
'kecamatan': @json($geoKecamatan),
|
||||
'desa': @json($geoDesa),
|
||||
'lahan': @json($geoLahan)
|
||||
};
|
||||
|
||||
var currentLayerGroup = L.featureGroup().addTo(map);
|
||||
var mapHistory = [];
|
||||
var btnBack = document.getElementById('btnBackMap');
|
||||
|
||||
function ensureLatLon(coords) {
|
||||
if (typeof coords[0] === 'number') {
|
||||
if (Math.abs(coords[0]) > 90) {
|
||||
return [coords[1], coords[0]];
|
||||
}
|
||||
return [coords[0], coords[1]];
|
||||
}
|
||||
return coords.map(ensureLatLon);
|
||||
}
|
||||
|
||||
function renderLevel(level, parentId = null, fallbackBounds = null) {
|
||||
var dataToRender = dataLevels[level];
|
||||
|
||||
if (parentId !== null) {
|
||||
dataToRender = dataToRender.filter(item => item.parent_id == parentId);
|
||||
}
|
||||
|
||||
if (dataToRender.length === 0) {
|
||||
alert(`Belum ada data pemetaan ${level} yang terdaftar di wilayah ini.`);
|
||||
if (mapHistory.length > 0) {
|
||||
mapHistory.pop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
currentLayerGroup.clearLayers();
|
||||
|
||||
if (level === 'lahan' && parentId !== null) {
|
||||
var parentDesa = dataLevels['desa'].find(d => d.id == parentId);
|
||||
|
||||
if (parentDesa && parentDesa.polygon) {
|
||||
try {
|
||||
var desaGeojson = typeof parentDesa.polygon === 'string' ? JSON.parse(parentDesa.polygon) : parentDesa.polygon;
|
||||
var desaLayer;
|
||||
|
||||
var desaStyle = {
|
||||
color: '#dc3545',
|
||||
weight: 2,
|
||||
dashArray: '5, 8',
|
||||
fillColor: 'none',
|
||||
interactive: false
|
||||
};
|
||||
|
||||
if (desaGeojson !== null && typeof desaGeojson === 'object' && desaGeojson.type) {
|
||||
desaLayer = L.geoJSON(desaGeojson, {
|
||||
style: desaStyle,
|
||||
coordsToLatLng: function (coords) {
|
||||
var a = coords[0], b = coords[1];
|
||||
if (Math.abs(a) > 90) return L.latLng(b, a);
|
||||
if (Math.abs(b) > 90) return L.latLng(a, b);
|
||||
return L.latLng(b, a);
|
||||
}
|
||||
});
|
||||
} else if (Array.isArray(desaGeojson)) {
|
||||
var safeCoordsDesa = ensureLatLon(desaGeojson);
|
||||
desaLayer = L.polygon(safeCoordsDesa, desaStyle);
|
||||
}
|
||||
|
||||
if (desaLayer) {
|
||||
currentLayerGroup.addLayer(desaLayer);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Gagal render batas desa:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dataToRender.forEach(function(item) {
|
||||
if (!item.polygon) return;
|
||||
try {
|
||||
var geojsonData = typeof item.polygon === 'string' ? JSON.parse(item.polygon) : item.polygon;
|
||||
var layer;
|
||||
|
||||
var styleOpts = level === 'lahan'
|
||||
? { color: '#28a745', weight: 2, fillColor: '#28a745', fillOpacity: 0.6 }
|
||||
: { color: '#f39c12', weight: 2, fillColor: '#f1c40f', fillOpacity: 0.3 };
|
||||
|
||||
if (geojsonData !== null && typeof geojsonData === 'object' && geojsonData.type) {
|
||||
layer = L.geoJSON(geojsonData, {
|
||||
style: styleOpts,
|
||||
coordsToLatLng: function (coords) {
|
||||
var a = coords[0], b = coords[1];
|
||||
if (Math.abs(a) > 90) return L.latLng(b, a);
|
||||
if (Math.abs(b) > 90) return L.latLng(a, b);
|
||||
return L.latLng(b, a);
|
||||
}
|
||||
});
|
||||
} else if (Array.isArray(geojsonData)) {
|
||||
var safeCoords = ensureLatLon(geojsonData);
|
||||
layer = L.polygon(safeCoords, styleOpts);
|
||||
}
|
||||
|
||||
if (layer) {
|
||||
if (level === 'lahan') {
|
||||
var listTanaman = item.tanaman && item.tanaman.length > 0 ? item.tanaman.join(', ') : null;
|
||||
|
||||
var komoditasText = listTanaman
|
||||
? listTanaman
|
||||
: '<span class="text-danger-light fw-medium small">Belum terdaftar</span>';
|
||||
|
||||
var cropIcon = listTanaman ? 'ti tabler-plant' : 'ti tabler-leaf-off';
|
||||
var cropIconColor = listTanaman ? 'text-success' : 'text-danger';
|
||||
|
||||
var popupContent = `
|
||||
<div class="modern-lahan-popup">
|
||||
<div class="p-3 bg-white rounded-top-12 header-farmer">
|
||||
<div class="d-flex align-items-center mb-1">
|
||||
<small class="label-header text-uppercase text-muted fw-semibold">Pemilik Lahan</small>
|
||||
</div>
|
||||
<h6 class="mb-0 fw-bold farmer-name h5">${item.nama_petani}</h6>
|
||||
</div>
|
||||
|
||||
<div class="p-3 bg-light rounded-bottom-12 details-body">
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-12 d-flex align-items-center">
|
||||
<div class="icon-stat-container rounded-circle bg-white text-muted border me-2">
|
||||
<i class="ti tabler-hash fs-5"></i>
|
||||
</div>
|
||||
<div>
|
||||
<small class="d-block text-muted text-uppercase fw-medium label-detail">ID Lahan</small>
|
||||
<span class="fw-bold text-dark value-detail">TR-${item.id}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-1">
|
||||
<div class="col-6 d-flex align-items-center">
|
||||
<div class="icon-stat-container rounded ${cropIconColor}-light me-2">
|
||||
<i class="${cropIcon} fs-5 ${cropIconColor}"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<small class="d-block text-muted text-uppercase fw-medium label-detail">Komoditas</small>
|
||||
<span class="fw-semibold text-dark value-commodity">${komoditasText}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6 d-flex align-items-center border-start ps-2">
|
||||
<div class="icon-stat-container rounded bg-primary-light me-2">
|
||||
<i class="ti tabler-dimensions fs-5 text-primary"></i>
|
||||
</div>
|
||||
<div>
|
||||
<small class="d-block text-muted text-uppercase fw-medium label-detail">Luas Lahan</small>
|
||||
<span class="fw-bold text-dark value-detail">${parseFloat(item.luas).toFixed(1)} Ha</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
layer.bindPopup(popupContent, {
|
||||
maxWidth: 300,
|
||||
closeButton: true,
|
||||
offset: [0, 0],
|
||||
className: 'leaflet-modern-popup-wrapper'
|
||||
});
|
||||
} else {
|
||||
var tooltipContent = `
|
||||
<div class="modern-map-card">
|
||||
<div class="card-header-region">
|
||||
<span class="region-label">Wilayah</span>
|
||||
<h6 class="region-name">${item.nama}</h6>
|
||||
</div>
|
||||
|
||||
<div class="card-body-stats border-top border-bottom py-2 my-2">
|
||||
<div class="stat-row d-flex align-items-center mb-2">
|
||||
<div class="stat-icon bg-success-light text-success me-2 rounded-p-2">
|
||||
<i class="ti tabler-map"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<small class="text-muted text-uppercase fw-medium" style="font-size: 10px;">Jumlah Lahan</small>
|
||||
<div class="stat-value fw-bold">${parseInt(item.total_lahan)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-row d-flex align-items-center">
|
||||
<div class="stat-icon bg-primary-light text-primary me-2 rounded-p-2">
|
||||
<i class="ti tabler-area"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<small class="text-muted text-uppercase fw-medium" style="font-size: 10px;">Total Luas</small>
|
||||
<div class="stat-value fw-bold">${parseFloat(item.total_luas).toFixed(2)} <small class="text-muted">Ha</small></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer-action text-center mt-2">
|
||||
<span class="action-prompt text-primary fw-medium small">
|
||||
Klik untuk detail <i class="ti tabler-chevron-right ms-1"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
layer.bindTooltip(tooltipContent, {
|
||||
sticky: true,
|
||||
direction: 'top',
|
||||
className: 'leaflet-modern-tooltip',
|
||||
offset: [0, -10]
|
||||
});
|
||||
|
||||
layer.on('click', function(e) {
|
||||
L.DomEvent.stopPropagation(e);
|
||||
var nextLevel = level === 'provinsi' ? 'kabupaten'
|
||||
: level === 'kabupaten' ? 'kecamatan'
|
||||
: level === 'kecamatan' ? 'desa' : 'lahan';
|
||||
|
||||
mapHistory.push({ level: level, parentId: parentId, bounds: currentLayerGroup.getBounds() });
|
||||
renderLevel(nextLevel, item.id, e.target.getBounds());
|
||||
});
|
||||
}
|
||||
currentLayerGroup.addLayer(layer);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Gagal memproses data level", level, "ID", item.id, e);
|
||||
}
|
||||
});
|
||||
|
||||
if (btnBack) btnBack.style.display = mapHistory.length > 0 ? 'block' : 'none';
|
||||
|
||||
if (currentLayerGroup.getLayers().length > 0) {
|
||||
var bounds = currentLayerGroup.getBounds();
|
||||
if (bounds.isValid()) {
|
||||
map.fitBounds(bounds, { padding: [30, 30], maxZoom: 18 });
|
||||
}
|
||||
} else if (fallbackBounds && fallbackBounds.isValid()) {
|
||||
map.fitBounds(fallbackBounds, { padding: [30, 30], maxZoom: 18 });
|
||||
}
|
||||
}
|
||||
|
||||
if (btnBack) {
|
||||
btnBack.addEventListener('click', function() {
|
||||
var prevState = mapHistory.pop();
|
||||
if (prevState) {
|
||||
renderLevel(prevState.level, prevState.parentId);
|
||||
if (prevState.bounds && prevState.bounds.isValid()) {
|
||||
map.fitBounds(prevState.bounds, { padding: [30, 30] });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
map.invalidateSize();
|
||||
// Render Awal: Provinsi
|
||||
renderLevel('provinsi', null);
|
||||
}, 300);
|
||||
|
||||
</script>
|
||||
@endpush
|
||||
@@ -33,14 +33,14 @@
|
||||
<!-- Header Section -->
|
||||
<div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 mb-6">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold teks-header-judul">
|
||||
Ringkasan M&E (Theory of Change)
|
||||
</h2>
|
||||
|
||||
<p class="text-sm mt-1 teks-header-sub">
|
||||
Capaian Utama Transformasi Bioekonomi Desa Ngada
|
||||
</p>
|
||||
</div>
|
||||
<h2 class="text-2xl font-bold teks-header-judul">
|
||||
Ringkasan M&E (Theory of Change)
|
||||
</h2>
|
||||
|
||||
<p class="text-sm mt-1 teks-header-sub">
|
||||
Capaian Utama Transformasi Bioekonomi Desa Ngada
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button class="bg-white border border-gray-200 text-gray-600 px-4 py-2 rounded-lg text-sm font-medium hover:bg-gray-50 flex items-center gap-2">
|
||||
<i data-lucide="download" class="w-4 h-4"></i> Export PDF
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasAddColumn"
|
||||
aria-labelledby="offcanvasAddColumnLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasAddColumnLabel" class="offcanvas-title">Tambah Kolom</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="add-new-column pt-0" id="addColumnForm" action="{{ route('tabel.formulir.store', $tabel->id) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" id="add-column-tipe" name="tipe" value="form-column" />
|
||||
<input type="hidden" id="add-column-parent" name="parent_id" value="" />
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-column-width">Lebar Kolom (1-12)</label>
|
||||
<input type="number" min="1" max="12" step="1" value="3"
|
||||
class="form-control" id="add-column-width" name="column_width" placeholder="Cth: 3" />
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
const offcanvasAddColumn = new bootstrap.Offcanvas(document.getElementById('offcanvasAddColumn'));
|
||||
$('#addColumnForm').validate({
|
||||
rules: {
|
||||
column_width: { required: true, number: true },
|
||||
},
|
||||
messages: {
|
||||
column_width: { required: "Lebar kolom wajib diisi" },
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action'),
|
||||
type: 'POST',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasAddColumn.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
|
||||
$('.add-column').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#add-column-parent').val($(this).data('parent'));
|
||||
offcanvasAddColumn.show();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,27 @@
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
function addForm(tipe) {
|
||||
$.ajax({
|
||||
url: '{{ route('tabel.formulir.store', [$tabel->id]) }}',
|
||||
type: 'POST',
|
||||
data: {
|
||||
tipe: tipe,
|
||||
_token: '{{ csrf_token() }}',
|
||||
},
|
||||
success: function () {
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
}
|
||||
$(".add-hr-line").click(function (e) {
|
||||
e.preventDefault();
|
||||
addForm('form-hr-line');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user