From c4ff20facdc756306f347e4ffa462a495df65770 Mon Sep 17 00:00:00 2001 From: Irwan Cahyono Date: Wed, 1 Jul 2026 15:38:15 +0700 Subject: [PATCH] petani lahan tanaman update --- app/Enums/KeparahanSerangan.php | 10 ++ app/Enums/KondisiTanaman.php | 9 +- app/Enums/PenyakitTanaman.php | 11 ++ app/Enums/SeranganHama.php | 10 ++ .../Produktivitas/PetaniLahanController.php | 85 ++++++++- .../PetaniLahanTanamanController.php | 108 +++++++++++ app/Models/Pertanian/Lahan.php | 6 + app/Models/Pertanian/Tanaman.php | 17 ++ .../2026_06_28_095941_update_lahan_table.php | 6 +- ...2026_07_01_150041_update_tanaman_table.php | 32 ++++ .../produktivitas/petani/lahan/add.blade.php | 79 ++++++++- .../produktivitas/petani/lahan/edit.blade.php | 167 +++++++++++++++--- .../petani/lahan/tanaman/edit.blade.php | 158 +++++++++++++++++ routes/web.php | 2 + 14 files changed, 656 insertions(+), 44 deletions(-) create mode 100644 app/Enums/KeparahanSerangan.php create mode 100644 app/Enums/PenyakitTanaman.php create mode 100644 app/Enums/SeranganHama.php create mode 100644 app/Http/Controllers/Web/Produktivitas/PetaniLahanTanamanController.php create mode 100644 database/migrations/2026_07_01_150041_update_tanaman_table.php create mode 100644 resources/views/produktivitas/petani/lahan/tanaman/edit.blade.php diff --git a/app/Enums/KeparahanSerangan.php b/app/Enums/KeparahanSerangan.php new file mode 100644 index 0000000..f6ad0b2 --- /dev/null +++ b/app/Enums/KeparahanSerangan.php @@ -0,0 +1,10 @@ + ['required', 'exists:jenis_komoditas,id'], 'varietas_id' => ['nullable', 'exists:master_varietas,id'], 'jumlah_tanaman' => ['required', 'numeric'], + 'umur_lahan' => ['required', 'numeric'], + 'umur_tanaman' => ['required', 'numeric'], + 'kondisi_tanaman' => ['required', 'string', new Enum(KondisiTanaman::class)], + 'serangan_hama' => ['nullable', 'string', new Enum(SeranganHama::class)], + 'penyakit_tanaman' => ['nullable', 'string', new Enum(PenyakitTanaman::class)], + 'keparahan_serangan' => ['nullable', 'string', new Enum(KeparahanSerangan::class)], ]); $komoditas = Komoditas::where('id', $request->komoditas_id)->first(); @@ -103,6 +117,11 @@ class PetaniLahanController extends Controller 'varietas_id' => $lahan->varietas_id, 'petani_id' => $lahan->petani_id, 'nama' => 'Tanaman ' . $komoditas->nama . ' #' . $i, + 'umur_tanaman' => $lahan->umur_tanaman, + 'kondisi_tanaman' => $lahan->kondisi_tanaman, + 'serangan_hama' => $lahan->serangan_hama, + 'penyakit_tanaman' => $lahan->penyakit_tanaman, + 'keparahan_serangan' => $lahan->keparahan_serangan ]; }); @@ -122,7 +141,7 @@ class PetaniLahanController extends Controller $petani = Petani::findOrFail($petaniId); $lahan = Lahan::where('petani_id', $petaniId) - ->orderBy('created_at', 'desc') + ->orderBy('id', 'asc') ->get(); $lahanSelected = Lahan::where('petani_id', $petaniId)->findOrFail($id); @@ -140,7 +159,7 @@ class PetaniLahanController extends Controller $petani = Petani::findOrFail($petaniId); $lahan = Lahan::where('petani_id', $petaniId) - ->orderBy('created_at', 'desc') + ->orderBy('id', 'asc') ->get(); $lahanSelected = Lahan::where('petani_id', $petaniId)->findOrFail($id); @@ -155,9 +174,67 @@ class PetaniLahanController extends Controller /** * Update the specified resource in storage. */ - public function update(Request $request, string $id) + public function update(Request $request, string $petaniId, string $id) { - // + if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) { + abort(403); + } + + $petani = Petani::findOrFail($petaniId); + $lahan = Lahan::where('petani_id', $petaniId)->findOrFail($id); + + $validated = $request->validate([ + 'nama' => ['nullable', 'string', 'max:255'], + 'status_kepemilikan' => ['nullable', 'string', 'max:255'], + 'profile_id' => ['nullable'], + 'petani_id' => ['nullable'], + 'keluarga_pengelola_id' => ['nullable'], + 'adat_pemilik_id' => ['nullable'], + 'desa_kelurahan_id' => ['nullable'], + 'luas_lahan' => ['required', 'numeric'], + 'path' => ['nullable', 'string'], + 'komoditas_id' => ['required', 'exists:master_komoditas,id'], + 'jenis_komoditas_id' => ['required', 'exists:jenis_komoditas,id'], + 'varietas_id' => ['nullable', 'exists:master_varietas,id'], + 'jumlah_tanaman' => ['required', 'numeric'], + 'umur_lahan' => ['required', 'numeric'], + 'umur_tanaman' => ['required', 'numeric'], + 'kondisi_tanaman' => ['required', 'string', new Enum(KondisiTanaman::class)], + 'serangan_hama' => ['nullable', 'string', new Enum(SeranganHama::class)], + 'penyakit_tanaman' => ['nullable', 'string', new Enum(PenyakitTanaman::class)], + 'keparahan_serangan' => ['nullable', 'string', new Enum(KeparahanSerangan::class)], + ]); + + $komoditas = Komoditas::where('id', $request->komoditas_id)->first(); + + $lahanCount = Lahan::where('petani_id', $petaniId) + ->count(); + + $lahan->update([...$validated, + 'nama' => 'Lahan ' . $komoditas->nama . ' #' . ($lahanCount + 1), + 'uid' => 'LHN-' . $petani->uid . '-' . strtoupper(Str::random(10)), + 'petani_id' => $petaniId, + 'updated_by' => auth()->id()] + ); + + if ($lahan) { + $data = collect(range($lahanCount, $lahan->jumlah_tanaman))->map(function ($i) use ($lahan, $komoditas) { + return [ + 'lahan_id' => $lahan->id, + 'komoditas_id' => $lahan->komoditas_id, + 'jenis_komoditas_id' => $lahan->jenis_komoditas_id, + 'varietas_id' => $lahan->varietas_id, + 'petani_id' => $lahan->petani_id, + 'nama' => 'Tanaman ' . $komoditas->nama . ' #' . $i, + ]; + }); + + $data->chunk(500)->each(function ($chunk) { + Tanaman::insert($chunk->toArray()); + }); + + return redirect()->route('petani.lahan-tanaman.index', $petaniId)->with('success', 'Lahan berhasil ditambahkan.'); + } } /** diff --git a/app/Http/Controllers/Web/Produktivitas/PetaniLahanTanamanController.php b/app/Http/Controllers/Web/Produktivitas/PetaniLahanTanamanController.php new file mode 100644 index 0000000..54f2191 --- /dev/null +++ b/app/Http/Controllers/Web/Produktivitas/PetaniLahanTanamanController.php @@ -0,0 +1,108 @@ +findOrFail($lahanId); + $lahanTanaman = Tanaman::with(['komoditas', 'jenisKomoditas', 'varietas', 'profile'])->where('lahan_id', $lahanId)->findOrFail($id); + + return response()->json([ + 'status' => 'success', + 'data' => $lahanTanaman, + ]); + } + + public function edit(string $id) + { + // + } + + public function update(Request $request, string $petaniId, string $lahanId, string $id) + { + if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) { + abort(403); + } + + $petani = Petani::findOrFail($petaniId); + $lahan = Lahan::where('petani_id', $petaniId)->findOrFail($lahanId); + $lahanTanaman = Tanaman::where('lahan_id', $lahanId)->findOrFail($id); + + $validated = $request->validate([ + '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)], + ]); + + $lahanTanaman->update([...$validated, 'updated_by' => auth()->id()]); + + return response()->json([ + 'status' => 'success', + 'message' => 'Data tanaman berhasil diperbarui', + 'data' => $lahanTanaman, + ]); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(string $petaniId, string $lahanId, string $id) + { + if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) { + abort(403); + } + + $petani = Petani::findOrFail($petaniId); + $lahan = Lahan::where('petani_id', $petaniId)->findOrFail($lahanId); + $lahanTanaman = LahanTanaman::where('lahan_id', $lahanId)->findOrFail($id); + + $lahanTanaman->updated_by = auth()->id(); + $lahanTanaman->save(); + $lahanTanaman->delete(); + + return response()->json([ + 'status' => 'success', + 'message' => 'Data tanaman berhasil dihapus', + ]); + } +} diff --git a/app/Models/Pertanian/Lahan.php b/app/Models/Pertanian/Lahan.php index 512257b..131f457 100644 --- a/app/Models/Pertanian/Lahan.php +++ b/app/Models/Pertanian/Lahan.php @@ -36,6 +36,12 @@ class Lahan extends Model 'varietas_id', 'jumlah_tanaman', 'petani_id', + + 'kondisi_tanaman', + 'serangan_hama', + 'penyakit_tanaman', + 'keparahan_serangan', + 'created_by', 'updated_by', 'deleted_by', diff --git a/app/Models/Pertanian/Tanaman.php b/app/Models/Pertanian/Tanaman.php index 5b89bb2..e31a616 100644 --- a/app/Models/Pertanian/Tanaman.php +++ b/app/Models/Pertanian/Tanaman.php @@ -10,6 +10,11 @@ use App\Models\Pertanian\Komoditas; use App\Models\Master\JenisKomoditas; use App\Models\Master\Varietas; +use App\Enums\KondisiTanaman; +use App\Enums\SeranganHama; +use App\Enums\PenyakitTanaman; +use App\Enums\KeparahanSerangan; + class Tanaman extends Model { use SoftDeletes; @@ -32,6 +37,18 @@ class Tanaman extends Model 'created_by', 'updated_by', 'deleted_by', + + 'umur_tanaman', + 'serangan_hama', + 'penyakit_tanaman', + 'keparahan_serangan', + ]; + + protected $casts = [ + 'kondisi_tanaman' => KondisiTanaman::class, + 'serangan_hama' => SeranganHama::class, + 'penyakit_tanaman' => PenyakitTanaman::class, + 'keparahan_serangan' => KeparahanSerangan::class, ]; public function komoditas() diff --git a/database/migrations/2026_06_28_095941_update_lahan_table.php b/database/migrations/2026_06_28_095941_update_lahan_table.php index cb72450..10653e0 100644 --- a/database/migrations/2026_06_28_095941_update_lahan_table.php +++ b/database/migrations/2026_06_28_095941_update_lahan_table.php @@ -24,7 +24,7 @@ return new class extends Migration $table->integer('jumlah_tanaman')->nullable(); $table->string('kondisi_tanaman')->nullable(); - $table->string('hama_tanaman')->nullable(); + $table->string('serangan_hama')->nullable(); $table->string('penyakit_tanaman')->nullable(); $table->string('keparahan_serangan')->nullable(); @@ -35,10 +35,6 @@ return new class extends Migration Schema::table('petani', function (Blueprint $table) { $table->foreignId('profile_id')->nullable()->constrained('profiles')->onDelete('set null'); }); - - Schema::table('map_petani', function (Blueprint $table) { - $table->foreignId('petani_id')->nullable()->constrained('petani')->onDelete('set null'); - }); } /** diff --git a/database/migrations/2026_07_01_150041_update_tanaman_table.php b/database/migrations/2026_07_01_150041_update_tanaman_table.php new file mode 100644 index 0000000..b51bed8 --- /dev/null +++ b/database/migrations/2026_07_01_150041_update_tanaman_table.php @@ -0,0 +1,32 @@ +foreignId('petani_id')->nullable()->constrained('petani')->onDelete('set null'); + + $table->float('umur_tanaman', 8)->nullable(); + + $table->string('serangan_hama')->nullable(); + $table->string('penyakit_tanaman')->nullable(); + $table->string('keparahan_serangan')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + + } +}; diff --git a/resources/views/produktivitas/petani/lahan/add.blade.php b/resources/views/produktivitas/petani/lahan/add.blade.php index 4a7cc7a..7365af1 100644 --- a/resources/views/produktivitas/petani/lahan/add.blade.php +++ b/resources/views/produktivitas/petani/lahan/add.blade.php @@ -67,7 +67,7 @@
-
Data Lahan dan Komoditas
+
Data Lahan dan Tanaman
@@ -75,8 +75,18 @@ @error('luas_lahan')
{{ $message }}
@enderror
+
+ + + @error('umur_lahan')
{{ $message }}
@enderror +
+
+ + + @error('jumlah_tanaman')
{{ $message }}
@enderror +
@error('komoditas_id')
{{ $message }}
@enderror
+
+
@error('jenis_komoditas_id')
{{ $message }}
@enderror
-
-
@error('varietas_id')
{{ $message }}
@enderror
-
- - - @error('jumlah_tanaman')
{{ $message }}
@enderror +
+
+
+ + + @error('umur_tanaman')
{{ $message }}
@enderror +
+
+
+ +
+ + + @error('kondisi_tanaman')
{{ $message }}
@enderror +
+
+ + +
+
+
+
+ + +
+
+ + + @error('keparahan_serangan')
{{ $message }}
@enderror

-
Lokasi Wilayah
+
Lokasi
@@ -162,7 +218,7 @@
-
Gambar Area Lahan
+
Peta Lahan
Gunakan tool ⬟ di kiri peta
@@ -194,6 +250,11 @@ 'use strict'; $(document).ready(function () { + $('#kondisi_tanaman').select2(); + $('#serangan_hama').select2(); + $('#penyakit_tanaman').select2(); + $('#keparahan_serangan').select2(); + $('#provinsi_id').select2().change(function(e) { e.preventDefault(); var provinsiId = $(this).val(); diff --git a/resources/views/produktivitas/petani/lahan/edit.blade.php b/resources/views/produktivitas/petani/lahan/edit.blade.php index bce11b5..2e083cb 100644 --- a/resources/views/produktivitas/petani/lahan/edit.blade.php +++ b/resources/views/produktivitas/petani/lahan/edit.blade.php @@ -62,8 +62,9 @@
-
+ @csrf + @method('PUT')
@@ -110,13 +111,14 @@
- + @error('jumlah_tanaman')
{{ $message }}
@enderror

-
Lokasi Wilayah
+
Lokasi
@@ -161,8 +163,9 @@
- - Pastikan menggambar polygon di peta dengan menyambungkan titik akhir ke titik awal. + + Gunakan tombol edit (pensil) atau hapus (tong sampah) di peta untuk mengubah bentuk lahan. @error('path')
{{ $message }}
@enderror
@@ -170,8 +173,8 @@
-
Gambar Area Lahan
- Gunakan tool ⬟ di kiri peta +
Peta Lahan
+ Gunakan tool edit di kiri peta
@@ -194,14 +197,16 @@
- +
- - - + + + + + @@ -209,14 +214,62 @@ @forelse($lahanSelected->tanaman as $index => $item) - - - - - + + + + + +
No NamaKomoditasJenisVarietasLokasiKondisiHamaPenyakitKeparahan Aksi
{{ $loop->iteration }}{{ $item->nama }}{{ $item->komoditas->nama }}{{ $item->jenisKomoditas->nama }}{{ $item->varietas->nama }} +
+ {{ $item->nama }} + {{ $item->komoditas->nama }} / {{ $item->jenisKomoditas->nama }} / {{ $item->varietas->nama }} ({{ $item->umur_tanaman }} tahun) +
+
+ + @if($item->latitude && $item->longitude) + {{ $item->latitude }}, {{ $item->longitude }} + @endif + + + @if($item->kondisi_tanaman == \App\Enums\KondisiTanaman::BAIK) + Baik + @elseif($item->kondisi_tanaman == \App\Enums\KondisiTanaman::SEDANG) + Sedang + @elseif($item->kondisi_tanaman == \App\Enums\KondisiTanaman::BURUK) + Buruk + @elseif($item->kondisi_tanaman == \App\Enums\KondisiTanaman::MATI) + Mati + @endif + + @if($item->serangan_hama == \App\Enums\SeranganHama::ULAT) + Ulat + @elseif($item->serangan_hama == \App\Enums\SeranganHama::BELALANG) + Belalang + @elseif($item->serangan_hama == \App\Enums\SeranganHama::KUTU) + Kutu + @endif + + @if($item->penyakit_tanaman == \App\Enums\PenyakitTanaman::BUSUK_BUAH) + Busuk Buah + @elseif($item->penyakit_tanaman == \App\Enums\PenyakitTanaman::DAUN_MENGUNING) + Daun Menguning + @elseif($item->penyakit_tanaman == \App\Enums\PenyakitTanaman::DAUN_BERCAK) + Daun Bercak + @elseif($item->penyakit_tanaman == \App\Enums\PenyakitTanaman::TANAMAN_LAYU) + Tanaman Layu + @endif + + @if($item->keparahan_serangan == \App\Enums\KeparahanSerangan::RINGAN) + Ringan + @elseif($item->keparahan_serangan == \App\Enums\KeparahanSerangan::SEDANG) + Sedang + @elseif($item->keparahan_serangan == \App\Enums\KeparahanSerangan::BERAT) + Berat + @endif +
- +
@@ -235,6 +288,8 @@ +@include('produktivitas.petani.lahan.tanaman.edit') + @endsection @push('scripts') @@ -245,6 +300,25 @@ 'use strict'; $(document).ready(function () { + const selectedProvinsi = "{{ optional($lahanSelected->desaKelurahan->kecamatan->kabupatenKota->provinsi)->id }}"; + const selectedKabupaten = "{{ optional($lahanSelected->desaKelurahan->kecamatan->kabupatenKota)->id }}"; + const selectedKecamatan = "{{ optional($lahanSelected->desaKelurahan->kecamatan)->id }}"; + const selectedDesa = "{{ optional($lahanSelected->desaKelurahan)->id }}"; + + const selectedKomoditas = "{{ optional($lahanSelected->komoditas)->id }}"; + const selectedJenisKomoditas = "{{ optional($lahanSelected->jenisKomoditas)->id }}"; + const selectedVarietas = "{{ optional($lahanSelected->varietas)->id }}"; + + $('#table-tanaman').DataTable({ + "paging": true, + "lengthChange": true, + "searching": true, + "ordering": false, + "info": true, + "autoWidth": false, + "responsive": true, + }); + $('#provinsi_id').select2().change(function(e) { e.preventDefault(); var provinsiId = $(this).val(); @@ -267,6 +341,10 @@ } $('#kabupatenkota_id').append(''); }); + + if(selectedKabupaten){ + $('#kabupatenkota_id').val(selectedKabupaten).trigger('change'); + } } }); } @@ -291,6 +369,9 @@ } $('#kecamatan_id').append(''); }); + if (selectedKecamatan) { + $('#kecamatan_id').val(selectedKecamatan).trigger('change'); + } } }); } @@ -314,6 +395,9 @@ } $('#desa_kelurahan_id').append(''); }); + if (selectedDesa) { + $('#desa_kelurahan_id').val(selectedDesa).trigger('change'); + } } }); } @@ -323,6 +407,11 @@ focusToRegionBoundary(this); }); + async function initWilayah() { + if (!selectedProvinsi) return; + $('#provinsi_id').val(selectedProvinsi).trigger('change'); + } + $('#komoditas_id').select2().change(function(e) { e.preventDefault(); var komoditasId = $(this).val(); @@ -338,6 +427,9 @@ data.data.forEach(function(jenis) { $('#jenis_komoditas_id').append(''); }); + if (selectedJenisKomoditas) { + $('#jenis_komoditas_id').val(selectedJenisKomoditas).trigger('change'); + } } }); } @@ -356,12 +448,20 @@ data.data.forEach(function(jenis) { $('#varietas_id').append(''); }); + if (selectedVarietas) { + $('#varietas_id').val(selectedVarietas).trigger('change'); + } } }); } }); $('#varietas_id').select2(); + async function initKomoditas() { + if (!selectedKomoditas) return; + $('#komoditas_id').val(selectedKomoditas).trigger('change'); + } + // MAP let map = L.map('map').setView([-0.789275, 113.921327], 5); // Default: Tengah Indonesia @@ -373,7 +473,7 @@ let regionBoundaryLayer = L.featureGroup().addTo(map); - function focusToRegionBoundary(selectElement) { + function focusToRegionBoundary(selectElement, shouldZoom = true) { regionBoundaryLayer.clearLayers(); // Bersihkan garis wilayah sebelumnya let selectedOption = selectElement.options[selectElement.selectedIndex]; @@ -406,7 +506,7 @@ }); regionBoundaryLayer.addLayer(polygon); - map.fitBounds(polygon.getBounds(), { padding: [20, 20] }); + if (shouldZoom) map.fitBounds(polygon.getBounds(), { padding: [20, 20] }); } } catch (error) { console.error("Format JSON path wilayah tidak valid:", error); @@ -441,6 +541,28 @@ }); map.addControl(drawControl); + let rawLahanPath = document.getElementById('path').value; + if (rawLahanPath) { + try { + let parsedPath = JSON.parse(rawLahanPath); + if (Array.isArray(parsedPath) && parsedPath.length > 0) { + let existingLatLngs = parsedPath.map(function(coord) { + return [coord[1], coord[0]]; + }); + + let existingPolygon = L.polygon(existingLatLngs, { + color: '#28c76f', fillColor: '#28c76f', fillOpacity: 0.4, weight: 3 + }); + + drawnItems.addLayer(existingPolygon); + + setTimeout(() => { map.fitBounds(existingPolygon.getBounds(), { padding: [30, 30] }); }, 500); + } + } catch (e) { + console.error("Gagal merender polygon lahan eksisting: ", e); + } + } + map.on(L.Draw.Event.CREATED, function (e) { let layer = e.layer; @@ -483,7 +605,7 @@ jenis_komoditas_id: { required: true }, varietas_id: { required: true }, desa_kelurahan_id: { required: true }, - jumlah_tanaman: { required: true }, + jumlah_tanaman: { required: true, min: @json($lahanSelected->jumlah_tanaman) }, }, messages: { luas_lahan: { required: "Luas lahan wajib diisi" }, @@ -491,7 +613,7 @@ jenis_komoditas_id: { required: "Jenis komoditas wajib diisi" }, varietas_id: { required: "Varietas wajib diisi" }, desa_kelurahan_id: { required: "Desa/Kelurahan wajib diisi" }, - jumlah_tanaman: { required: "Jumlah tanaman wajib diisi" }, + jumlah_tanaman: { required: "Jumlah tanaman wajib diisi", min: "Jumlah tanaman tidak boleh kurang dari @json($lahanSelected->jumlah_tanaman), hapus pada tanaman yang dimaksud" }, }, errorElement: 'div', errorPlacement: function (error, element) { @@ -505,6 +627,9 @@ $(element).removeClass('is-invalid'); } }); + + initWilayah(); + initKomoditas(); }); @endpush \ No newline at end of file diff --git a/resources/views/produktivitas/petani/lahan/tanaman/edit.blade.php b/resources/views/produktivitas/petani/lahan/tanaman/edit.blade.php new file mode 100644 index 0000000..ede3343 --- /dev/null +++ b/resources/views/produktivitas/petani/lahan/tanaman/edit.blade.php @@ -0,0 +1,158 @@ + + + +@push('scripts') + +@endpush \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 317a9e1..12c0b77 100644 --- a/routes/web.php +++ b/routes/web.php @@ -188,4 +188,6 @@ Route::middleware('auth') // Petani Route::resource('petani', App\Http\Controllers\Web\Produktivitas\PetaniController::class); Route::resource('petani.lahan-tanaman', App\Http\Controllers\Web\Produktivitas\PetaniLahanController::class); + Route::resource('petani.lahan-tanaman.tanaman', App\Http\Controllers\Web\Produktivitas\PetaniLahanTanamanController::class)->only(['show', 'update', 'destroy']); + });