22 Commits
Author SHA1 Message Date
Althaf 712b10e405 Merge branches 'main' and 'main' of https://git.probindo.com/Probindo/database-pertani-web 2026-07-22 17:06:45 +07:00
Althaf 6cfcf46ba6 use assets avatars 2026-07-22 17:06:31 +07:00
Syaharani b1b9828514 update jumlah tanaman 2026-07-22 16:54:57 +07:00
Syaharani 7af7e1bdaf update jumlah lahan 2026-07-22 16:40:24 +07:00
Syaharani bd05fc7f0f update hama dan penyakit 2026-07-22 16:23:32 +07:00
Syaharani 17b5687db8 update user profile 2026-07-22 15:55:07 +07:00
Syaharani e7f48b6500 solve lahan & tanaman 2026-07-22 15:49:25 +07:00
Syaharani a5884d0f8c solve akses pasar 2026-07-22 15:22:56 +07:00
Syaharani 9576c6295e solve sosial ekonomi 2026-07-22 14:41:05 +07:00
irwan.l.cahyono 079e300d5d Merge branch 'main' of https://git.probindo.com/Probindo/database-pertani-web 2026-07-22 14:39:10 +07:00
irwan.l.cahyono 2c94316439 petani lahan hapus 2026-07-22 14:38:10 +07:00
Syaharani 690b53e5a2 Merge origin/main 2026-07-22 14:08:34 +07:00
irwan.l.cahyono 50c9adfdc7 Merge branch 'main' of https://git.probindo.com/Probindo/database-pertani-web 2026-07-22 13:56:56 +07:00
irwan.l.cahyono 696c7dede8 hama dan penyakit lahan 2026-07-22 13:56:55 +07:00
Syaharani 5967e7d6f3 solve pendidikan & pelatihan 2026-07-22 13:28:58 +07:00
Syaharani 4c66d72dc5 solve praktik budidaya 2026-07-22 13:27:35 +07:00
Althaf c43483a9f8 default profile-iconize & fixed overlapping tab 2026-07-22 13:24:39 +07:00
Syaharani e02a34a527 solve lahan & tanaman 2026-07-22 11:58:51 +07:00
Althaf 713355ce0a add text-heading to adjust icon color theme 2026-07-22 10:35:36 +07:00
Althaf 12f8d0bbda integrate image cropper for avatar upload/delete option/retouch 2026-07-22 10:10:06 +07:00
Althaf 8afe7f9b38 solve view-controller dropzone 2026-07-21 11:49:32 +07:00
Althaf fbf84eb4cb enhance UX alerts 2026-07-20 16:45:00 +07:00
30 changed files with 1375 additions and 178 deletions
+3 -3
View File
@@ -11,9 +11,9 @@ enum KeparahanSerangan: string
public function label(): string
{
return match($this) {
self::RINGAN => 'Ringan',
self::SEDANG => 'Sedang',
self::BERAT => 'Berat',
self::RINGAN => 'Ringan, hanya beberapa tanaman',
self::SEDANG => 'Sedang, sebagian tanaman terdampak',
self::BERAT => 'Parah, sebagian besar tanaman terdampak',
};
}
+4 -4
View File
@@ -13,10 +13,10 @@ enum KondisiTanaman: string
public function label(): string
{
return match($this) {
self::BAIK => 'Baik',
self::SEDANG => 'Sedang',
self::BURUK => 'Buruk',
self::MATI => 'Mati',
self::BAIK => 'Baik, tumbuh lebat, banyak buah',
self::SEDANG => 'Sedang, cukup tumbuh, ada masalah',
self::BURUK => 'Buruk, banyak tanaman tua dan lemah/tidak berbuah',
self::MATI => 'Mati, tanaman telah mati, tidak dapat tumbuh maupun berbuah',
};
}
@@ -11,6 +11,7 @@ use App\Models\User;
use App\Models\Pertanian\Petani;
use App\Models\Pertanian\Komoditas;
use App\Models\Pertanian\Lahan;
use App\Models\Pertanian\Tanaman;
use App\Models\Pertanian\SurveyPelatihan;
use App\Models\Pertanian\SurveySertifikasi;
@@ -143,24 +144,29 @@ class SurveyPetaniController extends Controller
// Ringkasan lahan
$totalLuasLahan = (float) Lahan::query()
->sum('luas_lahan');
$totalJumlahTanaman = (int) Lahan::query()
->sum('jumlah_tanaman');
$totalLuasLahan = ((float) Lahan::query()
->sum('luas_lahan')) / 10000;
// Jumlah tanaman berdasarkan komoditas petani
$tanamanPerKomoditasCollection = DB::table("{$lahanTable} as l")
$tanamanTable = (new Tanaman())->getTable();
$tanamanPerKomoditasCollection = DB::table("{$tanamanTable} as t")
->join("{$lahanTable} as l", 'l.id', '=', 't.lahan_id')
->join("{$petaniTable} as p", 'p.id', '=', 'l.petani_id')
->leftJoin("{$komoditasTable} as k", 'k.id', '=', 'p.komoditas_id')
->leftJoin("{$komoditasTable} as k", 'k.id', '=', 't.komoditas_id')
->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label")
->selectRaw('COALESCE(SUM(l.jumlah_tanaman), 0) as total')
->selectRaw('COUNT(t.id) as total')
->where('k.is_utama', true)
->whereNull('t.deleted_at')
->whereNull('l.deleted_at')
->whereNull('p.deleted_at')
->groupBy('k.id', 'k.nama')
->orderByDesc('total')
->get();
$totalJumlahTanaman = (int) $tanamanPerKomoditasCollection->sum('total');
$tanamanPerKomoditas = $tanamanPerKomoditasCollection
->map(function ($item, $index) use ($colors, $totalJumlahTanaman) {
$color = $colors[$index % count($colors)];
@@ -25,9 +25,25 @@ class AksesPasarController extends Controller
$aksesPasar = AksesPasar::where('petani_id', $petaniId)->first();
$hargaJualPanen = HargaJualPanen::where('petani_id', $petaniId)->get();
$hargaJualRows = collect([
'Buah segar hasil petik',
'Biji basah',
'Biji kering/Biji Kupas',
'Terfermentasi (Rp/kg)',
])->map(function (string $bentuk, int $index) use ($hargaJualPanen) {
$existingData = $hargaJualPanen->firstWhere('bentuk_produk', $bentuk);
return [
'index' => $index,
'bentuk' => $bentuk,
'harga_panen_terakhir' => $this->currencyForDisplay($existingData?->harga_panen_terakhir),
'harga_tahun_lalu' => $this->currencyForDisplay($existingData?->harga_tahun_lalu),
'harga_dua_tahun_lalu' => $this->currencyForDisplay($existingData?->harga_dua_tahun_lalu),
];
});
return view('produktivitas.petani.akses-pasar.index', array_merge(
compact('petani', 'aksesPasar', 'hargaJualPanen'),
compact('petani', 'aksesPasar', 'hargaJualPanen', 'hargaJualRows'),
$this->aksesPasarOptions()
));
}
@@ -251,4 +267,11 @@ class AksesPasarController extends Controller
$digits = preg_replace('/\D/', '', (string) $value);
return $digits === '' ? null : $digits;
}
private function currencyForDisplay(mixed $value): string
{
$digits = $this->currencyDigits($value);
return is_null($digits) ? '' : number_format((int) $digits, 0, ',', '.');
}
}
@@ -77,10 +77,11 @@ class PendidikanPelatihanController extends Controller
]);
}
return back()->with('success', 'Riwayat pelatihan berhasil disimpan.');
return $this->redirectBackToFragment($request, 'section-sertifikasi')
->with('success', 'Riwayat pelatihan berhasil disimpan.');
}
public function destroyPelatihan(Petani $petani, SurveyPelatihan $surveyPelatihan)
public function destroyPelatihan(Request $request, Petani $petani, SurveyPelatihan $surveyPelatihan)
{
$this->authorizeAccess();
@@ -92,7 +93,8 @@ class PendidikanPelatihanController extends Controller
$surveyPelatihan->delete();
return back()->with('success', 'Riwayat pelatihan berhasil dihapus.');
return $this->redirectBackToFragment($request, 'section-pelatihan')
->with('success', 'Riwayat pelatihan berhasil dihapus.');
}
public function storeSertifikasi(Request $request, Petani $petani)
@@ -155,10 +157,11 @@ class PendidikanPelatihanController extends Controller
]);
}
return back()->with('success', 'Sertifikasi berhasil disimpan.');
return $this->redirectBackToFragment($request, 'section-sertifikasi')
->with('success', 'Sertifikasi berhasil disimpan.');
}
public function destroySertifikasi(Petani $petani, SurveySertifikasi $surveySertifikasi)
public function destroySertifikasi(Request $request, Petani $petani, SurveySertifikasi $surveySertifikasi)
{
$this->authorizeAccess();
@@ -170,6 +173,18 @@ class PendidikanPelatihanController extends Controller
$surveySertifikasi->delete();
return back()->with('success', 'Sertifikasi berhasil dihapus.');
return $this->redirectBackToFragment($request, 'section-sertifikasi')
->with('success', 'Sertifikasi berhasil dihapus.');
}
private function redirectBackToFragment(Request $request, string $defaultFragment)
{
$fragment = $request->input('redirect_fragment', $defaultFragment);
if (!is_string($fragment) || !preg_match('/^[A-Za-z0-9_-]+$/', $fragment)) {
$fragment = $defaultFragment;
}
return redirect()->to(Str::before(url()->previous(), '#') . '#' . $fragment);
}
}
@@ -50,14 +50,14 @@ class PetaniController extends Controller
$query->where('created_by', auth()->user()->id);
}
$summaryPetaniIds = (clone $query)->pluck('id');
$petani = $query->paginate($request->per_page ?? 10);
$komoditas = Komoditas::where('is_utama', true)->get();
$lahan = Lahan::whereIn('petani_id', $petani->pluck('id'))
$lahan = Lahan::whereIn('petani_id', $summaryPetaniIds)
->whereIn('komoditas_id', $komoditas->pluck('id'))
->get();
$tanaman = Tanaman::whereIn('lahan_id', $lahan->pluck('id'))
->whereIn('lahan_id', $lahan->pluck('id'))
->get();
$case = "
@@ -70,7 +70,7 @@ class PetaniController extends Controller
END
";
$skor = SkorPetani::selectRaw("$case AS segmen, COUNT(*) AS total")
->whereIn('petani_id', $petani->pluck('id'))
->whereIn('petani_id', $summaryPetaniIds)
->groupByRaw($case)
->get();
@@ -178,7 +178,7 @@ class PetaniController extends Controller
'created_by' => auth()->id(),
'updated_by' => auth()->id()]);
return redirect()->route('petani.index')->with('success', 'Data petani berhasil ditambahkan.');
return redirect()->route('petani.edit', $petani->id)->with('success', 'Data petani berhasil ditambahkan.');
}
public function show(string $id)
@@ -224,6 +224,13 @@ class PetaniController extends Controller
$validatedData = $this->validatePetani($request);
if ($request->input('hapus_foto') == '1') {
if ($petani->foto && Storage::exists($petani->foto)) {
Storage::delete($petani->foto);
}
$validatedData['foto'] = null;
}
if ($request->hasFile('file_ktp')) {
$file_ktp = $request->file('file_ktp');
$validatedData['path_ktp'] = $file_ktp->store('petani/ktp');
@@ -235,6 +242,10 @@ class PetaniController extends Controller
$validatedData['file_kk'] = $file_kk->getClientOriginalName();
}
if ($request->hasFile('foto')) {
if ($petani->foto && Storage::exists($petani->foto)) {
Storage::delete($petani->foto);
}
$file_foto = $request->file('foto');
$validatedData['foto'] = $file_foto->store('petani/foto');
}
@@ -242,7 +253,7 @@ class PetaniController extends Controller
$petani->update([...$validatedData,
'updated_by' => auth()->id()]);
return redirect()->route('petani.index')->with('success', 'Data petani berhasil diupdate.');
return redirect()->route('petani.edit', $petani->id)->with('success', 'Data petani berhasil diupdate.');
}
/**
@@ -7,6 +7,7 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules\Enum;
@@ -17,6 +18,7 @@ use App\Models\Pertanian\Lahan;
use App\Models\Wilayah\DesaKelurahan;
use App\Models\Wilayah\Provinsi;
use App\Models\Pertanian\Komoditas;
use App\Models\Pertanian\PraktikBudidaya;
use App\Models\Pertanian\Tanaman;
use App\Models\Master\JenisTanaman;
@@ -64,8 +66,46 @@ class PetaniLahanController extends Controller
$komoditas = Komoditas::all();
$tanamanPenaung = JenisTanaman::all();
$autoPestDiseaseData = $this->autoPestDiseaseData($petaniId);
$jenisHamaOtomatis = $autoPestDiseaseData['jenis_hama'];
$jenisPenyakitOtomatis = $autoPestDiseaseData['jenis_penyakit'];
return view('produktivitas.petani.lahan.add', compact('petani', 'lahan', 'provinsi', 'komoditas', 'tanamanPenaung'));
return view('produktivitas.petani.lahan.add', compact('petani', 'lahan', 'provinsi', 'komoditas', 'tanamanPenaung', 'jenisHamaOtomatis', 'jenisPenyakitOtomatis'));
}
private function autoPestDiseaseData(string|int $petaniId): array
{
$praktikBudidaya = PraktikBudidaya::where('petani_id', $petaniId)->latest()->first();
return [
'jenis_hama' => $this->normalizeArrayValue($praktikBudidaya?->jenis_hama),
'jenis_penyakit' => $this->normalizeArrayValue($praktikBudidaya?->jenis_penyakit),
];
}
private function normalizeArrayValue(mixed $value): array
{
if (is_array($value)) {
return array_values(array_filter($value, fn ($item) => filled($item)));
}
if (is_string($value) && $value !== '') {
$decoded = json_decode($value, true);
if (is_array($decoded)) {
return array_values(array_filter($decoded, fn ($item) => filled($item)));
}
return [$value];
}
return [];
}
private function hasPestDiseaseColumns(string $table): bool
{
return Schema::hasColumn($table, 'jenis_hama')
&& Schema::hasColumn($table, 'jenis_penyakit');
}
private function validateLahan(Request $request)
@@ -167,6 +207,14 @@ class PetaniLahanController extends Controller
]);
$validated = $this->validateLahan($request);
$autoPestDiseaseData = $this->autoPestDiseaseData($petaniId);
$lahanHasPestDiseaseColumns = $this->hasPestDiseaseColumns((new Lahan)->getTable());
$tanamanHasPestDiseaseColumns = $this->hasPestDiseaseColumns((new Tanaman)->getTable());
if ($lahanHasPestDiseaseColumns) {
$validated = array_merge($validated, $autoPestDiseaseData);
}
$komoditas = Komoditas::where('id', $request->komoditas_id)->first();
$lahanCount = Lahan::where('petani_id', $petaniId)
->count();
@@ -196,8 +244,8 @@ class PetaniLahanController extends Controller
);
if ($lahan && $lahan->jumlah_tanaman > 0) {
$data = collect(range(1, $lahan->jumlah_tanaman))->map(function ($i) use ($lahan, $komoditas, $lahanUid) {
return [
$data = collect(range(1, $lahan->jumlah_tanaman))->map(function ($i) use ($lahan, $komoditas, $lahanUid, $autoPestDiseaseData, $tanamanHasPestDiseaseColumns) {
$row = [
'lahan_id' => $lahan->id,
'uid' => 'TNM-' . $lahanUid . '-' . strtoupper(Str::random(10)),
'komoditas_id' => $lahan->komoditas_id,
@@ -215,6 +263,13 @@ class PetaniLahanController extends Controller
'created_at' => now(),
'updated_at' => now(),
];
if ($tanamanHasPestDiseaseColumns) {
$row['jenis_hama'] = json_encode($autoPestDiseaseData['jenis_hama'] ?? []);
$row['jenis_penyakit'] = json_encode($autoPestDiseaseData['jenis_penyakit'] ?? []);
}
return $row;
});
$data->chunk(500)->each(function ($chunk) {
@@ -224,15 +279,15 @@ class PetaniLahanController extends Controller
if ($request->ajax()) {
return response()->json([
'success' => true,
'redirect' => route('petani.lahan-tanaman.index', $petaniId),
'redirect' => route('petani.lahan-tanaman.edit', [$petaniId, $lahan->id]),
'message' => 'Lahan berhasil ditambahkan.'
]);
}
return redirect()->route('petani.lahan-tanaman.index', $petaniId)->with('success', 'Lahan berhasil ditambahkan.');
return redirect()->route('petani.lahan-tanaman.edit', [$petaniId, $lahan->id])->with('success', 'Lahan berhasil ditambahkan.');
}
return redirect()->route('petani.lahan-tanaman.index', $petaniId)->with('success', 'Lahan berhasil ditambahkan.');
return redirect()->route('petani.lahan-tanaman.edit', [$petaniId, $lahan->id])->with('success', 'Lahan berhasil ditambahkan.');
}
public function show(string $petaniId, string $id)
@@ -269,10 +324,13 @@ class PetaniLahanController extends Controller
$komoditas = Komoditas::all();
$tanamanPenaung = JenisTanaman::all();
$autoPestDiseaseData = $this->autoPestDiseaseData($petaniId);
$jenisHamaOtomatis = $autoPestDiseaseData['jenis_hama'];
$jenisPenyakitOtomatis = $autoPestDiseaseData['jenis_penyakit'];
$provinsi = Provinsi::orderBy('kode', 'asc')->get();
return view('produktivitas.petani.lahan.edit', compact('lahan', 'lahanSelected', 'petani', 'komoditas', 'provinsi', 'tanamanPenaung'));
return view('produktivitas.petani.lahan.edit', compact('lahan', 'lahanSelected', 'petani', 'komoditas', 'provinsi', 'tanamanPenaung', 'jenisHamaOtomatis', 'jenisPenyakitOtomatis'));
}
public function update(Request $request, string $petaniId, string $id)
@@ -290,6 +348,14 @@ class PetaniLahanController extends Controller
->toArray()
]);
$validated = $this->validateLahan($request);
$autoPestDiseaseData = $this->autoPestDiseaseData($petaniId);
$lahanHasPestDiseaseColumns = $this->hasPestDiseaseColumns((new Lahan)->getTable());
$tanamanHasPestDiseaseColumns = $this->hasPestDiseaseColumns((new Tanaman)->getTable());
if ($lahanHasPestDiseaseColumns) {
$validated = array_merge($validated, $autoPestDiseaseData);
}
$komoditas = Komoditas::where('id', $request->komoditas_id)->first();
$tanamanCount = Tanaman::where('lahan_id', $lahan->id)->count();
$lahanCount = Lahan::where('petani_id', $petaniId)->count();
@@ -302,6 +368,22 @@ class PetaniLahanController extends Controller
$fotoLama = [];
}
if ($request->has('deleted_photos') && is_array($request->deleted_photos)) {
foreach ($request->deleted_photos as $deletedPath) {
if (Storage::disk('public')->exists($deletedPath)) {
Storage::disk('public')->delete($deletedPath);
}
$fotoLama = array_filter($fotoLama, function($item) use ($deletedPath) {
$currentPath = is_array($item) ? ($item['path'] ?? '') : $item;
return $currentPath !== $deletedPath;
});
}
}
$fotoLama = array_values($fotoLama);
if ($request->hasFile('foto')) {
foreach ($request->file('foto') as $file) {
$path = $file->store('lahan', 'public');
@@ -315,7 +397,7 @@ class PetaniLahanController extends Controller
unset($validated['foto']);
$lahan->update([...$validated,
'foto' => count($fotoLama) > 0 ? $fotoLama : null,
'foto' => count($fotoLama) > 0 ? json_encode($fotoLama) : null,
'updated_by' => auth()->id()]
);
@@ -326,8 +408,8 @@ class PetaniLahanController extends Controller
$this->syncTanamanPenaung($request);
if ($lahan && $lahan->jumlah_tanaman > $tanamanCount) {
$data = collect(range($tanamanCount + 1, $lahan->jumlah_tanaman))->map(function ($i) use ($lahan, $komoditas, $lahanUid) {
return [
$data = collect(range($tanamanCount + 1, $lahan->jumlah_tanaman))->map(function ($i) use ($lahan, $komoditas, $lahanUid, $autoPestDiseaseData, $tanamanHasPestDiseaseColumns) {
$row = [
'lahan_id' => $lahan->id,
'komoditas_id' => $lahan->komoditas_id,
'jenis_komoditas_id' => $lahan->jenis_komoditas_id,
@@ -345,6 +427,13 @@ class PetaniLahanController extends Controller
'created_at' => now(),
'updated_at' => now(),
];
if ($tanamanHasPestDiseaseColumns) {
$row['jenis_hama'] = json_encode($autoPestDiseaseData['jenis_hama'] ?? []);
$row['jenis_penyakit'] = json_encode($autoPestDiseaseData['jenis_penyakit'] ?? []);
}
return $row;
});
$data->chunk(500)->each(function ($chunk) {
@@ -352,20 +441,42 @@ class PetaniLahanController extends Controller
});
}
if ($tanamanHasPestDiseaseColumns) {
$lahan->tanaman()->update([
'jenis_hama' => json_encode($autoPestDiseaseData['jenis_hama'] ?? []),
'jenis_penyakit' => json_encode($autoPestDiseaseData['jenis_penyakit'] ?? []),
'updated_by' => auth()->id(),
]);
}
if ($request->ajax()) {
return response()->json([
'success' => true,
'redirect' => route('petani.lahan-tanaman.index', $petaniId),
'redirect' => route('petani.lahan-tanaman.edit', [$petaniId, $lahan->id]),
'message' => 'Lahan berhasil diupdate.'
]);
}
return redirect()->route('petani.lahan-tanaman.index', $petaniId)->with('success', 'Lahan berhasil diperbarui.');
return redirect()->route('petani.lahan-tanaman.edit', [$petaniId, $lahan->id])->with('success', 'Lahan berhasil diperbarui.');
}
public function destroy(string $id)
public function destroy(string $petaniId, string $id)
{
//
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
abort(403);
}
$lahan = Lahan::findOrFail($id);
$lahan->tanaman()->update([
'deleted_by' => auth()->id()
]);
$lahan->tanaman()->delete();
$lahan->update([
'deleted_by' => auth()->id()
]);
$lahan->delete();
return redirect()->route('petani.lahan-tanaman.index', $petaniId)->with('success', 'Lahan berhasil dihapus.');
}
public function summary(string $petaniId)
@@ -178,8 +178,14 @@ class PraktikBudidayaController extends Controller
$teknik_pemangkasan = array_values($teknik_pemangkasan);
if ((int) ($validatedData['frekuensi_pemangkasan_komoditas_utama'] ?? 0) === FrekuensiPemangkasanUtama::TIDAK_PERNAH->value) {
$teknik_pemangkasan = [];
}
$petani = Petani::findOrFail($petaniId);
$pemupukanTidakPernah = (int) ($validatedData['pemberian_pupuk'] ?? 0) === PemberianPupuk::TIDAK_PERNAH->value;
$praktikBudidaya = $petani->praktikBudidaya()->create([
'petani_id' => $petani->id,
'uid' => 'PB-' . strtoupper(Str::random(10)),
@@ -193,12 +199,12 @@ class PraktikBudidayaController extends Controller
'deskripsi_penyerbukan_manual' => $validatedData['alasan_tidak_penyerbukan'] ?? null,
'tingkat_keberhasilan_penyerbukan' => $validatedData['tingkat_keberhasilan_penyerbukan'] ?? null,
'pemberian_pupuk' => $validatedData['pemberian_pupuk'] ?? null,
'jenis_pupuk' => $validatedData['jenis_pupuk'] ?? null,
'frekuensi_pemberian_pupuk' => ($validatedData['frekuensi_pemupukan'] ?? null) === 'Lainnya' ? ($validatedData['frekuensi_pemupukan_lainnya'] ?? null) : ($validatedData['frekuensi_pemupukan'] ?? null),
'estimasi_dosis_pupuk_organik' => $validatedData['estimasi_dosis_pupuk_organik'] ?? null,
'estimasi_dosis_pupuk_anorganik' => $validatedData['estimasi_dosis_pupuk_anorganik'] ?? null,
'waktu_pemberian_pupuk' => ($validatedData['waktu_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['waktu_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['waktu_pemberian_pupuk'] ?? null),
'cara_pemberian_pupuk' => ($validatedData['cara_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['cara_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['cara_pemberian_pupuk'] ?? null),
'jenis_pupuk' => $pemupukanTidakPernah ? null : ($validatedData['jenis_pupuk'] ?? null),
'frekuensi_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['frekuensi_pemupukan'] ?? null) === 'Lainnya' ? ($validatedData['frekuensi_pemupukan_lainnya'] ?? null) : ($validatedData['frekuensi_pemupukan'] ?? null)),
'estimasi_dosis_pupuk_organik' => $pemupukanTidakPernah ? null : ($validatedData['estimasi_dosis_pupuk_organik'] ?? null),
'estimasi_dosis_pupuk_anorganik' => $pemupukanTidakPernah ? null : ($validatedData['estimasi_dosis_pupuk_anorganik'] ?? null),
'waktu_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['waktu_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['waktu_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['waktu_pemberian_pupuk'] ?? null)),
'cara_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['cara_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['cara_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['cara_pemberian_pupuk'] ?? null)),
'created_by' => auth()->id(),
'updated_by' => auth()->id(),
], [
@@ -555,6 +561,12 @@ class PraktikBudidayaController extends Controller
}
$teknikPemangkasan = array_values($teknik_pemangkasan);
if ((int) ($validatedData['frekuensi_pemangkasan_komoditas_utama'] ?? 0) === FrekuensiPemangkasanUtama::TIDAK_PERNAH->value) {
$teknikPemangkasan = [];
}
$pemupukanTidakPernah = (int) ($validatedData['pemberian_pupuk'] ?? 0) === PemberianPupuk::TIDAK_PERNAH->value;
$dataPraktikBudidaya = [
'tenaga_kerja' => $validatedData['tenaga_kerja'],
'frekuensi_pemangkasan_utama' => $validatedData['frekuensi_pemangkasan_komoditas_utama'],
@@ -566,12 +578,12 @@ class PraktikBudidayaController extends Controller
'deskripsi_penyerbukan_manual' => $validatedData['alasan_tidak_penyerbukan'] ?? null,
'tingkat_keberhasilan_penyerbukan' => $validatedData['tingkat_keberhasilan_penyerbukan'] ?? null,
'pemberian_pupuk' => $validatedData['pemberian_pupuk'] ?? null,
'jenis_pupuk' => $validatedData['jenis_pupuk'] ?? null,
'frekuensi_pemberian_pupuk' => ($validatedData['frekuensi_pemupukan'] ?? null) === 'Lainnya' ? ($validatedData['frekuensi_pemupukan_lainnya'] ?? null) : ($validatedData['frekuensi_pemupukan'] ?? null),
'estimasi_dosis_pupuk_organik' => $validatedData['estimasi_dosis_pupuk_organik'] ?? null,
'estimasi_dosis_pupuk_anorganik' => $validatedData['estimasi_dosis_pupuk_anorganik'] ?? null,
'waktu_pemberian_pupuk' => ($validatedData['waktu_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['waktu_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['waktu_pemberian_pupuk'] ?? null),
'cara_pemberian_pupuk' => ($validatedData['cara_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['cara_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['cara_pemberian_pupuk'] ?? null),
'jenis_pupuk' => $pemupukanTidakPernah ? null : ($validatedData['jenis_pupuk'] ?? null),
'frekuensi_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['frekuensi_pemupukan'] ?? null) === 'Lainnya' ? ($validatedData['frekuensi_pemupukan_lainnya'] ?? null) : ($validatedData['frekuensi_pemupukan'] ?? null)),
'estimasi_dosis_pupuk_organik' => $pemupukanTidakPernah ? null : ($validatedData['estimasi_dosis_pupuk_organik'] ?? null),
'estimasi_dosis_pupuk_anorganik' => $pemupukanTidakPernah ? null : ($validatedData['estimasi_dosis_pupuk_anorganik'] ?? null),
'waktu_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['waktu_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['waktu_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['waktu_pemberian_pupuk'] ?? null)),
'cara_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['cara_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['cara_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['cara_pemberian_pupuk'] ?? null)),
];
}
@@ -675,6 +687,17 @@ class PraktikBudidayaController extends Controller
}
}
return back()->with('success', 'Data berhasil diperbarui.');
return $this->redirectBackToFragment($request)->with('success', 'Data berhasil diperbarui.');
}
private function redirectBackToFragment(Request $request)
{
$fragment = $request->input('redirect_fragment');
if (!is_string($fragment) || !preg_match('/^[A-Za-z0-9_-]+$/', $fragment)) {
return back();
}
return redirect()->to(Str::before(url()->previous(), '#') . '#' . $fragment);
}
}
@@ -154,8 +154,7 @@ class SosialEkonomiController extends Controller
});
if (!$request->expectsJson()) {
return redirect()
->route('petani.sosial-ekonomi.edit', [$sosialEkonomi->petani_id, $sosialEkonomi->id])
return $this->redirectToEditSection($sosialEkonomi, $request)
->with('success', 'Data sosial ekonomi berhasil disimpan.');
}
@@ -206,8 +205,7 @@ class SosialEkonomiController extends Controller
});
if (!$request->expectsJson()) {
return redirect()
->route('petani.sosial-ekonomi.edit', [$sosialEkonomi->petani_id, $sosialEkonomi->id])
return $this->redirectToEditSection($sosialEkonomi, $request)
->with('success', 'Data sosial ekonomi berhasil diperbarui.');
}
@@ -218,6 +216,18 @@ class SosialEkonomiController extends Controller
]);
}
private function redirectToEditSection(SosialEkonomi $sosialEkonomi, Request $request): RedirectResponse
{
$url = route('petani.sosial-ekonomi.edit', [$sosialEkonomi->petani_id, $sosialEkonomi->id]);
$fragment = $request->input('redirect_fragment');
if (is_string($fragment) && preg_match('/^[A-Za-z0-9_-]+$/', $fragment)) {
$url .= '#' . $fragment;
}
return redirect()->to($url);
}
public function destroy(string $id): JsonResponse
{
$sosialEkonomi = SosialEkonomi::findOrFail($id);
@@ -589,6 +599,14 @@ class SosialEkonomiController extends Controller
$payload = $this->normalizeSkorPayload($payload);
if (array_key_exists('ada_sengketa', $payload) && !filter_var($payload['ada_sengketa'], FILTER_VALIDATE_BOOLEAN)) {
$payload['keterangan_sengketa'] = null;
$payload['pihak_membantu_konflik'] = null;
$payload['pihak_membantu_konflik_nama'] = null;
$payload['tahun_bantuan_konflik'] = null;
$payload['status_konflik'] = null;
}
if (($payload['pihak_membantu_konflik'] ?? null) === PihakMembantuKonflik::TIDAK_ADA_SELESAIKAN_SENDIRI->value) {
$payload['pihak_membantu_konflik_nama'] = null;
$payload['tahun_bantuan_konflik'] = null;
@@ -32,10 +32,10 @@ class SurveyProduktivitasController extends Controller
]);
}
return back()->with('success', 'Data produktivitas berhasil disimpan.');
return $this->redirectBackToFragment($request)->with('success', 'Data produktivitas berhasil disimpan.');
}
public function destroy($petaniId, $surveyProduktivitasId)
public function destroy($petaniId, $surveyProduktivitasId, Request $request)
{
$surveyProduktivitas = SurveyProduktivitas::where('petani_id', $petaniId)
->where('id', $surveyProduktivitasId)
@@ -44,6 +44,17 @@ class SurveyProduktivitasController extends Controller
$surveyProduktivitas->save();
$surveyProduktivitas->delete();
return back()->with('success', 'Data produktivitas berhasil dihapus.');
return $this->redirectBackToFragment($request)->with('success', 'Data produktivitas berhasil dihapus.');
}
private function redirectBackToFragment(Request $request)
{
$fragment = $request->input('redirect_fragment');
if (!is_string($fragment) || !preg_match('/^[A-Za-z0-9_-]+$/', $fragment)) {
return back();
}
return redirect()->to(Str::before(url()->previous(), '#') . '#' . $fragment);
}
}
+7 -2
View File
@@ -56,7 +56,10 @@ class Lahan extends Model
'komoditas_lain',
'tanaman_penaung',
'foto'
'foto',
'jenis_hama',
'jenis_penyakit',
];
protected $casts = [
@@ -68,7 +71,9 @@ class Lahan extends Model
'serangan_hama' => SeranganHama::class,
'penyakit_tanaman' => PenyakitTanaman::class,
'keparahan_serangan' => KeparahanSerangan::class,
'foto' => 'array'
'foto' => 'array',
'jenis_hama' => 'array',
'jenis_penyakit' => 'array'
];
public function profile(): BelongsTo
+28
View File
@@ -8,10 +8,13 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
use App\Models\Pertanian\Petani;
use App\Models\Pertanian\SkorPetani;
use App\Models\Pertanian\Tanaman;
use App\Models\Pertanian\Lahan;
class PraktikBudidaya extends Model
{
@@ -95,6 +98,31 @@ class PraktikBudidaya extends Model
$kebiasaan = $praktikBudidaya->kebiasaan_konservasi_tanah ? count($praktikBudidaya->kebiasaan_konservasi_tanah) : 0;
$pemahaman = $praktikBudidaya->pemahaman_manfaat_konservasi_tanah == 'Ya, tahu manfaatnya' ? 1 : 0;
$skor_konservasi_tanah = 0;
$jenisHama = $praktikBudidaya->jenis_hama ?? [];
$jenisPenyakit = $praktikBudidaya->jenis_penyakit ?? [];
if (Schema::hasColumn((new Lahan)->getTable(), 'jenis_hama')
&& Schema::hasColumn((new Lahan)->getTable(), 'jenis_penyakit')) {
Lahan::where('petani_id', $praktikBudidaya->petani_id)->get()->each(function (Lahan $lahan) use ($jenisHama, $jenisPenyakit, $praktikBudidaya) {
$lahan->update([
'jenis_hama' => $jenisHama,
'jenis_penyakit' => $jenisPenyakit,
'updated_by' => $praktikBudidaya->updated_by,
]);
});
}
if (Schema::hasColumn((new Tanaman)->getTable(), 'jenis_hama')
&& Schema::hasColumn((new Tanaman)->getTable(), 'jenis_penyakit')) {
Tanaman::where('petani_id', $praktikBudidaya->petani_id)->get()->each(function (Tanaman $tanaman) use ($jenisHama, $jenisPenyakit, $praktikBudidaya) {
$tanaman->update([
'jenis_hama' => $jenisHama,
'jenis_penyakit' => $jenisPenyakit,
'updated_by' => $praktikBudidaya->updated_by,
]);
});
}
if ($kebiasaan == 0) {
$skor_konservasi_tanah = 1;
} elseif ($kebiasaan == 1 && $pemahaman == 0) {
+5
View File
@@ -42,6 +42,9 @@ class Tanaman extends Model
'serangan_hama',
'penyakit_tanaman',
'keparahan_serangan',
'jenis_hama',
'jenis_penyakit',
];
protected $casts = [
@@ -49,6 +52,8 @@ class Tanaman extends Model
'serangan_hama' => SeranganHama::class,
'penyakit_tanaman' => PenyakitTanaman::class,
'keparahan_serangan' => KeparahanSerangan::class,
'jenis_hama' => 'array',
'jenis_penyakit' => 'array'
];
public function komoditas()
@@ -0,0 +1,57 @@
<?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) {
if (! Schema::hasColumn('map_lahan', 'jenis_hama')) {
$table->jsonb('jenis_hama')->nullable();
}
if (! Schema::hasColumn('map_lahan', 'jenis_penyakit')) {
$table->jsonb('jenis_penyakit')->nullable();
}
});
Schema::table('map_tanaman', function (Blueprint $table) {
if (! Schema::hasColumn('map_tanaman', 'jenis_hama')) {
$table->jsonb('jenis_hama')->nullable();
}
if (! Schema::hasColumn('map_tanaman', 'jenis_penyakit')) {
$table->jsonb('jenis_penyakit')->nullable();
}
});
}
public function down(): void
{
Schema::table('map_lahan', function (Blueprint $table) {
if (Schema::hasColumn('map_lahan', 'jenis_hama')) {
$table->dropColumn('jenis_hama');
}
if (Schema::hasColumn('map_lahan', 'jenis_penyakit')) {
$table->dropColumn('jenis_penyakit');
}
});
Schema::table('map_tanaman', function (Blueprint $table) {
if (Schema::hasColumn('map_tanaman', 'jenis_hama')) {
$table->dropColumn('jenis_hama');
}
if (Schema::hasColumn('map_tanaman', 'jenis_penyakit')) {
$table->dropColumn('jenis_penyakit');
}
});
}
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

+1 -1
View File
@@ -31,7 +31,7 @@
<i class="icon-base ti tabler-trees icon-28px"></i>
</span>
</div>
<h4 class="mb-0">{{ number_format($lahanSummary->sum('luas_lahan'), 0, ',', '.') }}m<sup>2</sup></h4>
<h4 class="mb-0">{{ number_format($lahanSummary->sum('luas_lahan') / 10000, 2, ',', '.') }} ha</h4>
</div>
<p class="mb-1">Lahan</p>
<p class="mb-0">
@@ -88,12 +88,13 @@
@if($profile)
<button
type="button"
class="btn btn-sm btn-icon btn-text-secondary rounded-pill"
class="btn btn-sm btn-outline-primary d-inline-flex align-items-center gap-1 px-3"
data-bs-toggle="offcanvas"
data-bs-target="#editProfileOffcanvas"
aria-controls="editProfileOffcanvas"
title="Edit profil">
<i class="icon-base ti tabler-edit icon-lg"></i>
<i class="icon-base ti tabler-edit icon-sm"></i>
<span>Edit</span>
</button>
@endif
</div>
+2 -2
View File
@@ -338,7 +338,7 @@
href="javascript:void(0);"
data-bs-toggle="dropdown">
<div class="avatar avatar-online">
<img src="../../assets/img/avatars/1.png" alt class="rounded-circle" />
<img src="{{ asset('assets/img/avatars/3.jpg') }}" alt="Avatar" class="rounded-circle" />
</div>
</a>
<ul class="dropdown-menu dropdown-menu-end">
@@ -347,7 +347,7 @@
<div class="d-flex align-items-center">
<div class="flex-shrink-0 me-2">
<div class="avatar avatar-online">
<img src="../../assets/img/avatars/1.png" alt class="rounded-circle" />
<img src="{{ asset('assets/img/avatars/3.jpg') }}" alt="Avatar" class="rounded-circle" />
</div>
</div>
<div class="flex-grow-1">
@@ -1,3 +1,17 @@
@push('style')
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.min.css" />
<style>
#croppie-container {
width: 100%;
height: 350px;
}
</style>
@endpush
@push('scripts')
<script src="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.min.js"></script>
@extends('layout.main')
@section('content')
@@ -29,7 +43,7 @@
<div class=" d-flex align-items-center flex-column">
<img id="fotoPreview"
class="img-fluid rounded mb-4"
src="{{ isset($petani) && $petani?->foto ? asset('storage/' . $petani->foto) : asset('assets/img/avatars/1.png') }}"
src="{{ isset($petani) && $petani?->foto ? asset('storage/' . $petani->foto) : asset('assets/img/avatars/3.jpg') }}"
height="120" width="120"
alt="Foto profil petani"
data-bs-toggle="tooltip" data-bs-placement="top"
@@ -230,6 +244,24 @@
</div>
</div>
</div>
<div class="modal fade" id="cropModal" tabindex="-1" aria-labelledby="cropModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="cropModalLabel">Sesuaikan Foto Profil</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="croppie-container"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
<button type="button" class="btn btn-primary" id="cropImageBtn">Potong & Simpan</button>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
@@ -301,23 +333,73 @@
});
$('#add-petani-desa').select2();
let croppieInstance = null;
$('#fotoPreview').on('click', function () {
$('#foto').val('');
$('#foto').click();
});
$('#foto').on('change', function (e) {
const file = e.target.files[0];
if (!file) return;
if(!file.type.match(/^image\/(png|jpeg|jpg)$/)) {
return;
}
const reader = new FileReader();
reader.onload = function (event) {
$('#fotoPreview').attr('src', event.target.result);
$('#cropModal').modal('show');
if (!croppieInstance) {
const el = document.getElementById('croppie-container');
croppieInstance = new Croppie(el, {
viewport: { width: 200, height: 200,},
boundary: { width: 300, height: 300 },
showZoomer: true,
enableOrientation: true
});
}
setTimeout(function() {
croppieInstance.bind({
url: event.target.result
});
}, 200);
};
reader.readAsDataURL(file);
});
$('#cropImageBtn').on('click', function() {
croppieInstance.result({
type: 'base64',
format: 'png',
size: 'viewport'
}).then(function(base64) {
$('#fotoPreview').attr('src', base64);
function dataURLtoFile(dataurl, filename) {
let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type: mime});
}
let croppedFile = dataURLtoFile(base64, 'foto_profil_crop.png');
let dataTransfer = new DataTransfer();
dataTransfer.items.add(croppedFile);
document.getElementById('foto').files = dataTransfer.files;
$('#cropModal').modal('hide');
});
});
// 1 MB = 1048576 bytes
$.validator.addMethod('maxfilesize', function (value, element, param) {
return this.optional(element) || (element.files[0] && element.files[0].size <= param);
@@ -93,34 +93,30 @@
</tr>
</thead>
<tbody>
@php($listBentukProduk = ['Buah segar hasil petik', 'Biji basah', 'Biji kering/Biji Kupas', 'Terfermentasi (Rp/kg)'])
@php($hargaJualPanen = $hargaJualPanen ?? collect())
@foreach ($listBentukProduk as $index => $bentuk)
@php($existingData = $hargaJualPanen->firstWhere('bentuk_produk', $bentuk))
@foreach ($hargaJualRows as $row)
<tr>
<td>
<input type="hidden" name="harga_jual[{{ $index }}][bentuk_produk]" value="{{ $bentuk }}">
<strong>{{ $bentuk }}:</strong>
<input type="hidden" name="harga_jual[{{ $row['index'] }}][bentuk_produk]" value="{{ $row['bentuk'] }}">
<strong>{{ $row['bentuk'] }}:</strong>
</td>
<td>
<div class="input-group">
<span class="input-group-text">Rp</span>
<input type="number" min="0" class="form-control" name="harga_jual[{{ $index }}][harga_panen_terakhir]" value="{{ old('harga_jual.' . $index . '.harga_panen_terakhir', $existingData?->harga_panen_terakhir) }}">
<input type="text" inputmode="numeric" class="form-control rupiah-input" name="harga_jual[{{ $row['index'] }}][harga_panen_terakhir]" value="{{ old('harga_jual.' . $row['index'] . '.harga_panen_terakhir', $row['harga_panen_terakhir']) }}" placeholder="Contoh: 12.000">
<span class="input-group-text">/kg</span>
</div>
</td>
<td>
<div class="input-group">
<span class="input-group-text">Rp</span>
<input type="number" min="0" class="form-control" name="harga_jual[{{ $index }}][harga_tahun_lalu]" value="{{ old('harga_jual.' . $index . '.harga_tahun_lalu', $existingData?->harga_tahun_lalu) }}">
<input type="text" inputmode="numeric" class="form-control rupiah-input" name="harga_jual[{{ $row['index'] }}][harga_tahun_lalu]" value="{{ old('harga_jual.' . $row['index'] . '.harga_tahun_lalu', $row['harga_tahun_lalu']) }}" placeholder="Contoh: 10.000">
<span class="input-group-text">/kg</span>
</div>
</td>
<td>
<div class="input-group">
<span class="input-group-text">Rp</span>
<input type="number" min="0" class="form-control" name="harga_jual[{{ $index }}][harga_dua_tahun_lalu]" value="{{ old('harga_jual.' . $index . '.harga_dua_tahun_lalu', $existingData?->harga_dua_tahun_lalu) }}">
<input type="text" inputmode="numeric" class="form-control rupiah-input" name="harga_jual[{{ $row['index'] }}][harga_dua_tahun_lalu]" value="{{ old('harga_jual.' . $row['index'] . '.harga_dua_tahun_lalu', $row['harga_dua_tahun_lalu']) }}" placeholder="Contoh: 8.000">
<span class="input-group-text">/kg</span>
</div>
</td>
@@ -232,6 +228,16 @@
const praktikBelumPernahValue = String(@json($praktikBelumPernahValue));
const skorPengalamanBerhentiValues = @json($skorPengalamanBerhentiValues ?? [2,3]).map(Number);
function onlyDigits(value) {
return String(value || '').replace(/\D/g, '');
}
function formatRupiah(value) {
const digits = onlyDigits(value);
return digits.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
}
function syncAlasanBerhenti() {
const val = Number($('input[name="skor_pengalaman"]:checked').val());
const isBerhenti = skorPengalamanBerhentiValues.includes(val);
@@ -256,6 +262,17 @@
$('input[name="skor_pengalaman"]').on('change', syncAlasanBerhenti);
$('input[name="saluran_terdahulu[]"]').on('change', syncSaluranLainnya);
$('input[name="praktik_fermentasi"]').on('change', syncPraktikFermentasi);
$(document).on('input', '.rupiah-input', function () {
const cursorAtEnd = this.selectionStart === this.value.length;
this.value = formatRupiah(this.value);
if (cursorAtEnd) {
this.setSelectionRange(this.value.length, this.value.length);
}
});
$('.rupiah-input').each(function () {
this.value = formatRupiah(this.value);
});
syncAlasanBerhenti();
syncSaluranLainnya();
@@ -1,5 +1,19 @@
@extends('layout.main')
@push('style')
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.min.css" />
<style>
#croppie-container {
width: 100%;
height: 350px;
}
</style>
@endpush
@push('scripts')
<script src="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.min.js"></script>
@section('content')
<div class="container-xxl flex-grow-1 container-p-y">
@if ($errors->any())
@@ -23,19 +37,23 @@
<form id="editPetaniForm" action="{{ route('petani.update', $petani->id) }}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<input type="hidden" name="hapus_foto" id="hapus_foto" value="0">
<input type="file" id="foto" name="foto" accept="image/png,image/jpeg,image/jpg" hidden>
<div class="row">
<div class="col-md-3">
<div class="user-avatar-section">
<div class=" d-flex align-items-center flex-column">
<img id="fotoPreview"
class="img-fluid rounded mb-4"
src="{{ $petani->foto ? route('petani.show-image', ['id' => $petani->id, 'field' => 'foto']) : asset('assets/img/avatars/1.png') }}"
height="120" width="120"
class="mb-3 shadow-sm rounded-3"
src="{{ $petani->foto ? route('petani.show-image', ['id' => $petani->id, 'field' => 'foto']) : asset('assets/img/avatars/3.jpg') }}"
alt="Foto profil petani"
data-bs-toggle="tooltip" data-bs-placement="top"
data-bs-original-title="Klik untuk mengganti foto profil petani"
style="cursor:pointer; object-fit:cover;" />
style="width: 120px !important; height: 120px !important; cursor:pointer; object-fit:cover; display:block; margin: 0 auto;" />
<button type="button" id="btnHapusFoto" class="btn btn-sm btn-outline-danger mb-4" style="display: {{ $petani->foto ? 'block' : 'none' }};">
Hapus Foto
</button>
<div class="user-info text-center">
<h5><i>{{ $petani->nama }}</i></h5>
<span class="badge bg-label-secondary">Petani {{ $petani->komoditas?->nama }}</span>
@@ -234,6 +252,24 @@
</div>
</div>
</div>
<div class="modal fade" id="cropModal" tabindex="-1" aria-labelledby="cropModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="cropModalLabel">Sesuaikan Foto Profil</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="croppie-container"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
<button type="button" class="btn btn-primary" id="cropImageBtn">Potong & Simpan</button>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
@@ -306,24 +342,86 @@
});
$('#edit-petani-desa').select2();
let croppieInstance = null;
$('#fotoPreview').on('click', function () {
$('#foto').val('');
$('#foto').click();
});
$('#foto').on('change', function (e) {
const file = e.target.files[0];
if (!file) return;
if(!file.type.match(/^image\/(png|jpeg|jpg)$/)) {
return;
}
const reader = new FileReader();
reader.onload = function (event) {
$('#fotoPreview').attr('src', event.target.result);
$('#cropModal').modal('show');
if (!croppieInstance) {
const el = document.getElementById('croppie-container');
croppieInstance = new Croppie(el, {
viewport: { width: 200, height: 200 },
boundary: { width: '100%', height: 280 },
showZoomer: true,
enableOrientation: true
});
}
setTimeout(function() {
croppieInstance.bind({
url: event.target.result
});
}, 200);
};
reader.readAsDataURL(file);
});
// 1 MB = 1048576 bytes
$('#cropImageBtn').on('click', function() {
croppieInstance.result({
type: 'base64',
format: 'png',
size: 'viewport',
}).then(function(base64) {
$('#fotoPreview').attr('src', base64);
$('#hapus_foto').val('0');
$('#btnHapusFoto').show();
function dataURLtoFile(dataurl, filename) {
let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type: mime});
}
let croppedFile = dataURLtoFile(base64, 'foto_profil_crop.png');
let dataTransfer = new DataTransfer();
dataTransfer.items.add(croppedFile);
document.getElementById('foto').files = dataTransfer.files;
$('#cropModal').modal('hide');
});
});
$('#btnHapusFoto').on('click', function() {
$('#hapus_foto').val('1');
$('#foto').val('');
$('#fotoPreview').attr('src', "{{ asset('assets/img/avatars/3.jpg') }}");
$(this).hide();
});
$.validator.addMethod('maxfilesize', function (value, element, param) {
return this.optional(element) || (element.files[0] && element.files[0].size <= param);
}, 'File size must be less than {0} bytes.');
@@ -1,3 +1,39 @@
<style>
@media (min-width: 768px) {
.nav-pills-custom-spacing {
display: flex;
width: 100%;
gap: 0.5rem;
flex-wrap: nowrap !important;
overflow-x: auto;
}
.nav-pills-custom-spacing::-webkit-scrollbar {
display: none;
}
.nav-pills-custom-spacing .nav-item {
margin-right: 0 !important;
flex: 1;
}
.nav-pills-custom-spacing .nav-link {
display: flex;
justify-content: center;
align-items: center;
padding-left: 0.5rem !important;
padding-right: 0.5rem !important;
width: 100%;
white-space: nowrap;
font-size: 0.9375rem !important;
}
.nav-pills-custom-spacing .nav-link i {
margin-right: 0.4rem !important;
}
}
</style>
<div class="row mb-4">
<div class="col-md-4 mb-2 mb-md-0">
@@ -7,10 +43,10 @@
<div class="d-flex justify-content-start align-items-center mb-3">
<div class="avatar me-2">
@if (!isset($petani))
<img src="{{ asset('assets/img/avatars/1.png') }}" alt="Foto Petani" class="rounded-circle" />
<img src="{{ asset('assets/img/avatars/3.jpg') }}" alt="Foto Petani"/>
@else
<img class="rounded-circle" alt="Foto Petani"
src="{{ $petani->foto ? route('petani.show-image', ['id' => $petani->id, 'field' => 'foto']) : asset('assets/img/avatars/1.png') }}" />
<img alt="Foto Petani"
src="{{ $petani->foto ? route('petani.show-image', ['id' => $petani->id, 'field' => 'foto']) : asset('assets/img/avatars/3.jpg') }}" class="rounded-3"/>
@endif
</div>
<div class="d-flex flex-column">
@@ -56,7 +92,13 @@
? $petani->lahans()->get()
: collect();
$totalLuasLahan = $petani ? $lahanPetani->where('komoditas_id', $petani->komoditas_id)->sum('luas_lahan') : 0;
$totalTanaman = $petani ? $lahanPetani->where('komoditas_id', $petani->komoditas_id)->sum('jumlah_tanaman') : 0;
$totalLuasLahanHa = $totalLuasLahan / 10000;
$lahanKomoditasUtamaIds = $petani
? $lahanPetani->where('komoditas_id', $petani->komoditas_id)->pluck('id')
: collect();
$totalTanaman = $petani && \Illuminate\Support\Facades\Schema::hasTable('map_tanaman')
? \App\Models\Pertanian\Tanaman::whereIn('lahan_id', $lahanKomoditasUtamaIds)->count()
: 0;
$pendidikanLabel = isset($petani) ? $petani->pendidikan_terakhir?->label() : null;
@endphp
@@ -79,7 +121,7 @@
</div>
<span class="avatar">
<span class="avatar-initial rounded">
<i class="icon-base ti tabler-user-star icon-22px"></i>
<i class="icon-base ti tabler-user-star icon-22px text-heading"></i>
</span>
</span>
</div>
@@ -90,7 +132,7 @@
<p class="mb-0 text-muted" style="font-size: 0.75rem;">Lahan & Tanaman</p>
<h5 class="mb-0">
@if($lahanPetani->isNotEmpty())
{{ number_format($totalLuasLahan, 0, ',', '.') }} m<sup>2</sup>
{{ number_format($totalLuasLahanHa, 2, ',', '.') }} ha
@else
-
@endif
@@ -105,7 +147,7 @@
</div>
<span class="avatar">
<span class="avatar-initial rounded">
<i class="icon-base ti tabler-trees icon-22px"></i>
<i class="icon-base ti tabler-trees icon-22px text-heading"></i>
</span>
</span>
</div>
@@ -127,7 +169,7 @@
</div>
<span class="avatar">
<span class="avatar-initial rounded">
<i class="icon-base ti tabler-books icon-22px"></i>
<i class="icon-base ti tabler-books icon-22px text-heading"></i>
</span>
</span>
</div>
@@ -181,7 +223,7 @@
</div>
<span class="avatar">
<span class="avatar-initial rounded">
<i class="icon-base ti tabler-seedling icon-22px"></i>
<i class="icon-base ti tabler-seedling icon-22px text-heading"></i>
</span>
</span>
</div>
@@ -232,7 +274,7 @@
</div>
<span class="avatar">
<span class="avatar-initial rounded">
<i class="icon-base ti tabler-social icon-22px"></i>
<i class="icon-base ti tabler-social icon-22px text-heading"></i>
</span>
</span>
</div>
@@ -291,7 +333,7 @@
</div>
<span class="avatar">
<span class="avatar-initial rounded">
<i class="icon-base ti tabler-building-store icon-22px"></i>
<i class="icon-base ti tabler-building-store icon-22px text-heading"></i>
</span>
</span>
</div>
@@ -306,7 +348,7 @@
<div class="nav-align-top">
@if(!$petani)
<ul class="nav nav-pills flex-column flex-md-row mb-6 row-gap-2">
<ul class="nav nav-pills flex-column flex-md-row mb-6 row-gap-2 nav-pills-custom-spacing">
<li class="nav-item">
<a class="nav-link active" href="{{ route('petani.create') }}">
<i class="icon-base ti tabler-user-check me-1_5 icon-sm"></i>Profil
@@ -344,40 +386,40 @@
</li>
</ul>
@else
<ul class="nav nav-pills flex-column flex-md-row mb-6 row-gap-2">
<ul class="nav nav-pills flex-column flex-md-row mb-6 row-gap-2 nav-pills-custom-spacing">
<li class="nav-item">
<a class="nav-link {{ request()->routeIs('petani.edit') ? 'active' : '' }}" href="{{ route('petani.edit', $petani->id) }}">
<i class="icon-base ti tabler-user-check me-1_5 icon-sm"></i>Profil
<i class="icon-base ti tabler-user-check icon-sm"></i>Profil
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ request()->routeIs('petani.lahan-tanaman.*') ? 'active' : '' }}" href="{{ route('petani.lahan-tanaman.index', $petani->id) }}">
<i class="icon-base ti tabler-trees me-1_5 icon-sm"></i>Lahan & Tanaman
<i class="icon-base ti tabler-trees icon-sm"></i>Lahan & Tanaman
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ request()->routeIs('petani.praktik-budidaya.*') ? 'active' : '' }}" href="{{ route('petani.praktik-budidaya.index', $petani->id) }}">
<i class="icon-base ti tabler-seedling me-1_5 icon-sm"></i>Praktik Budidaya
<i class="icon-base ti tabler-seedling icon-sm"></i>Praktik Budidaya
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ request()->routeIs('petani.pendidikan-pelatihan.*') ? 'active' : '' }}" href="{{ route('petani.pendidikan-pelatihan.index', $petani->id) }}">
<i class="icon-base ti tabler-books me-1_5 icon-sm"></i>Pendidikan & Pelatihan
<i class="icon-base ti tabler-books icon-sm"></i>Pendidikan & Pelatihan
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ request()->routeIs('petani.sosial-ekonomi.*') ? 'active' : '' }}" href="{{ route('petani.sosial-ekonomi.index', $petani->id) }}">
<i class="icon-base ti tabler-social me-1_5 icon-sm"></i>Sosial Ekonomi
<i class="icon-base ti tabler-social icon-sm"></i>Sosial Ekonomi
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ request()->routeIs('petani.akses-pasar.*') ? 'active' : '' }}" href="{{ route('petani.akses-pasar.index', $petani->id) }}">
<i class="icon-base ti tabler-building-store me-1_5 icon-sm"></i>Akses Pasar
<i class="icon-base ti tabler-building-store icon-sm"></i>Akses Pasar
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ request()->routeIs('petani.skor.*') ? 'active' : '' }}" href="{{ route('petani.skor.index', $petani->id) }}">
<i class="icon-base ti tabler-star me-1_5 icon-sm"></i>Kesiapan Adopsi
<i class="icon-base ti tabler-star icon-sm"></i>Kesiapan Adopsi
</a>
</li>
</ul>
@@ -15,7 +15,7 @@
<div class="w-25">
<x-summary-card
title="Lahan & Tanaman"
count="{{ number_format($lahan?->sum('luas_lahan'), 0, ',', '.') }}m<sup>2</sup>"
count="{{ number_format(($lahan?->sum('luas_lahan') ?? 0) / 10000, 2, ',', '.') }} ha"
subtitle="{{ $tanaman?->count() }} tanaman dari {{ $komoditas?->count() }} komoditas utama"
icon="trees"
color="success"
@@ -163,6 +163,10 @@
z-index: 100000 !important;
}
.foto-lightbox-close:hover { color: #dc3545 !important; }
.auto-pest-disease-field .form-check-label,
.auto-pest-disease-field .text-muted {
font-size: 0.875rem;
}
</style>
@endpush
@@ -203,8 +207,8 @@
<div class="row">
<div class="col-md-3 mb-3 form-control-validation">
<label class="form-label">Luas Lahan (m2) <span class="text-danger">*</span></label>
<input type="number" step="0.01" id="luas_lahan" name="luas_lahan" class="form-control @error('luas_lahan') is-invalid @enderror" placeholder="Contoh: 1.5" required />
<label class="form-label">Luas Lahan (ha) <span class="text-danger">*</span></label>
<input type="number" id="luas_lahan" name="luas_lahan" class="form-control @error('luas_lahan') is-invalid @enderror" placeholder="Contoh: 1.5" required />
@error('luas_lahan')<div class="error invalid-feedback">{{ $message }}</div>@enderror
</div>
<div class="col-md-3 mb-3 form-control-validation">
@@ -247,17 +251,134 @@
</div>
</div>
<div class="row">
<div class="col-md-3 mb-3 form-control-validation">
<div class="col-md-6 mb-3 form-control-validation">
<label class="form-label">Kondisi Umum Tanaman <span class="text-danger">*</span></label>
<select id="kondisi_tanaman" name="kondisi_tanaman" class="form-select @error('kondisi_tanaman') is-invalid @enderror">
<option value="">Pilih Kondisi Tanaman</option>
<option value="{{ \App\Enums\KondisiTanaman::BAIK }}" {{ old('kondisi_tanaman') == \App\Enums\KondisiTanaman::BAIK ? 'selected' : '' }}>Baik</option>
<option value="{{ \App\Enums\KondisiTanaman::SEDANG }}" {{ old('kondisi_tanaman') == \App\Enums\KondisiTanaman::SEDANG ? 'selected' : '' }}>Sedang</option>
<option value="{{ \App\Enums\KondisiTanaman::BURUK }}" {{ old('kondisi_tanaman') == \App\Enums\KondisiTanaman::BURUK ? 'selected' : '' }}>Buruk</option>
<option value="{{ \App\Enums\KondisiTanaman::BAIK }}" {{ old('kondisi_tanaman') == \App\Enums\KondisiTanaman::BAIK ? 'selected' : '' }}>{{ \App\Enums\KondisiTanaman::BAIK->label() }}</option>
<option value="{{ \App\Enums\KondisiTanaman::SEDANG }}" {{ old('kondisi_tanaman') == \App\Enums\KondisiTanaman::SEDANG ? 'selected' : '' }}>{{ \App\Enums\KondisiTanaman::SEDANG->label() }}</option>
<option value="{{ \App\Enums\KondisiTanaman::BURUK }}" {{ old('kondisi_tanaman') == \App\Enums\KondisiTanaman::BURUK ? 'selected' : '' }}>{{ \App\Enums\KondisiTanaman::BURUK->label() }}</option>
</select>
@error('kondisi_tanaman')<div class="error invalid-feedback">{{ $message }}</div>@enderror
</div>
<div class="col-md-3 mb-3 form-control-validation">
</div>
<div class="row">
<div class="col-md-3 mb-4 form-control-validation auto-pest-disease-field">
<label class="form-label">Jenis Hama</label>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_hama') is-invalid @enderror" disabled
type="checkbox"
name="jenis_hama[]"
value="Penggerek buah"
id="jenis-hama-penggerek-buah"
{{ in_array('Penggerek buah', $jenisHamaOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-hama-bentuk">Penggerek buah</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_hama') is-invalid @enderror" disabled
type="checkbox"
name="jenis_hama[]"
value="Penggerek batang"
id="jenis-hama-penggerek-batang"
{{ in_array('Penggerek batang', $jenisHamaOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-hama-bentuk">Penggerek batang</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_hama') is-invalid @enderror" disabled
type="checkbox"
name="jenis_hama[]"
value="Kutu putih/kutu sisik"
id="jenis-hama-kutu"
{{ in_array('Kutu putih/kutu sisik', $jenisHamaOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-hama-bentuk">Kutu putih/kutu sisik</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_hama') is-invalid @enderror" disabled
type="checkbox"
name="jenis_hama[]"
value="Ulat pemakan daun"
id="jenis-hama-ulat"
{{ in_array('Ulat pemakan daun', $jenisHamaOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-hama-bentuk">Ulat pemakan daun</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_hama') is-invalid @enderror" disabled
type="checkbox"
name="jenis_hama[]"
value="Tikus"
id="jenis-hama-tikus"
{{ in_array('Tikus', $jenisHamaOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-hama-bentuk">Tikus</label>
</div>
<small class="text-muted text-secondary">* Tidak diisi, terisi otomatis di Praktik Budidaya</small>
@error('jenis_hama')
<div class="error invalid-feedback d-block">{{ $message }}</div>
@enderror
</div>
<div class="col-md-3 mb-4 form-control-validation auto-pest-disease-field">
<label class="form-label">Jenis Penyakit</label>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_penyakit') is-invalid @enderror" disabled
type="checkbox"
name="jenis_penyakit[]"
value="Karat daun"
id="jenis-penyakit-karat-daun"
{{ in_array('Karat daun', $jenisPenyakitOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-penyakit-bentuk">Karat daun</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_penyakit') is-invalid @enderror" disabled
type="checkbox"
name="jenis_penyakit[]"
value="Busuk buah/antraknosa"
id="jenis-penyakit-busuk-buah"
{{ in_array('Busuk buah/antraknosa', $jenisPenyakitOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-penyakit-bentuk">Busuk buah/antraknosa</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_penyakit') is-invalid @enderror" disabled
type="checkbox"
name="jenis_penyakit[]"
value="Busuk akar"
id="jenis-penyakit-busuk-akar"
{{ in_array('Busuk akar', $jenisPenyakitOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-penyakit-bentuk">Busuk akar</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_penyakit') is-invalid @enderror" disabled
type="checkbox"
name="jenis_penyakit[]"
value="Bercak daun"
id="jenis-penyakit-bercak-daun"
{{ in_array('Bercak daun', $jenisPenyakitOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-penyakit-bentuk">Bercak daun</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_penyakit') is-invalid @enderror" disabled
type="checkbox"
name="jenis_penyakit[]"
value="Layu fusarium"
id="jenis-penyakit-layu-fusarium"
{{ in_array('Layu fusarium', $jenisPenyakitOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-penyakit-bentuk">Layu fusarium</label>
</div>
<small class="text-muted text-secondary">* Tidak diisi, terisi otomatis di praktik budidaya</small>
@error('jenis_penyakit')
<div class="error invalid-feedback d-block">{{ $message }}</div>
@enderror
</div>
<!-- <div class="col-md-3 mb-3 form-control-validation">
<label class="form-label">Serangan Hama</label>
<select id="serangan_hama" name="serangan_hama" class="form-select @error('serangan_hama') is-invalid @enderror">
<option value="">Pilih Serangan Hama</option>
@@ -276,14 +397,14 @@
<option value="{{ \App\Enums\PenyakitTanaman::DAUN_BERCAK }}" {{ old('penyakit_tanaman') == \App\Enums\PenyakitTanaman::DAUN_BERCAK ? 'selected' : '' }}>Daun Bercak</option>
<option value="{{ \App\Enums\PenyakitTanaman::TANAMAN_LAYU }}" {{ old('penyakit_tanaman') == \App\Enums\PenyakitTanaman::TANAMAN_LAYU ? 'selected' : '' }}>Tanaman Layu</option>
</select>
</div>
<div class="col-md-3 mb-3 form-control-validation">
</div> -->
<div class="col-md-6 mb-3 form-control-validation">
<label class="form-label">Keparahan Serangan Hama/Penyakit</label>
<select id="keparahan_serangan" name="keparahan_serangan" class="form-select @error('keparahan_serangan') is-invalid @enderror">
<option value="">Pilih Keparahan Serangan</option>
<option value="{{ \App\Enums\KeparahanSerangan::RINGAN }}" {{ old('keparahan_serangan') == \App\Enums\KeparahanSerangan::RINGAN ? 'selected' : '' }}>Ringan</option>
<option value="{{ \App\Enums\KeparahanSerangan::SEDANG }}" {{ old('keparahan_serangan') == \App\Enums\KeparahanSerangan::SEDANG ? 'selected' : '' }}>Sedang</option>
<option value="{{ \App\Enums\KeparahanSerangan::BERAT }}" {{ old('keparahan_serangan') == \App\Enums\KeparahanSerangan::BERAT ? 'selected' : '' }}>Berat</option>
<option value="{{ \App\Enums\KeparahanSerangan::RINGAN }}" {{ old('keparahan_serangan') == \App\Enums\KeparahanSerangan::RINGAN ? 'selected' : '' }}>{{ \App\Enums\KeparahanSerangan::RINGAN->label() }}</option>
<option value="{{ \App\Enums\KeparahanSerangan::SEDANG }}" {{ old('keparahan_serangan') == \App\Enums\KeparahanSerangan::SEDANG ? 'selected' : '' }}>{{ \App\Enums\KeparahanSerangan::SEDANG->label() }}</option>
<option value="{{ \App\Enums\KeparahanSerangan::BERAT }}" {{ old('keparahan_serangan') == \App\Enums\KeparahanSerangan::BERAT ? 'selected' : '' }}>{{ \App\Enums\KeparahanSerangan::BERAT->label() }}</option>
</select>
@error('keparahan_serangan')<div class="error invalid-feedback">{{ $message }}</div>@enderror
</div>
@@ -657,9 +778,9 @@
let area = L.GeometryUtil.geodesicArea(latlngs);
console.log(area);
let areaHa = area / 10000;
$('#luas_lahan').val(area.toFixed(2));
$('#luas_lahan').val(areaHa.toFixed(4));
}
const previewTemplate = `
@@ -826,8 +947,15 @@
'Accept': 'application/json'
},
success: function(res) {
alert('Data lahan berhasil ditambahkan!');
window.location.href = "{{ route('petani.index') }}";
Swal.fire({
icon: 'success',
title: 'Berhasil!',
text: 'Data lahan berhasil ditambahkan.',
showConfirmButton: false,
timer: 1500
}).then(() => {
window.location.href = res.redirect || window.location.href;
});
},
error: function(xhr) {
submitBtn.prop('disabled', false).html(originalText);
@@ -838,15 +966,26 @@
$.each(errors, function(key, val) {
errorMsg += val[0] + "\n";
});
alert("Penyimpanan Gagal:\n\n" + errorMsg);
Swal.fire({
icon: 'warning',
title: 'Penyimpanan Gagal',
text: errorMsg,
confirmButtonColor: '#dc3545'
});
} else {
let errorDetail = xhr.responseJSON && xhr.responseJSON.message ? xhr.responseJSON.message : xhr.statusText;
alert("Error " + xhr.status + ": " + errorDetail);
Swal.fire({
icon: 'error',
title: 'Terjadi Kesalahan',
text: "Error " + xhr.status + ": " + errorDetail,
confirmButtonColor: '#dc3545'
});
console.error(xhr.responseText);
}
}
});
return false;
}
});
@@ -34,6 +34,10 @@
.foto-lightbox img { max-width: 90vw !important; max-height: 85vh !important; object-fit: contain !important; border-radius: 8px !important; box-shadow: 0 10px 40px rgba(0,0,0,0.5) !important; }
.foto-lightbox-close { position: absolute !important; top: 20px !important; right: 30px !important; color: #fff !important; font-size: 40px !important; font-weight: bold !important; cursor: pointer !important; z-index: 100000 !important; }
.foto-lightbox-close:hover { color: #dc3545 !important; }
.auto-pest-disease-field .form-check-label,
.auto-pest-disease-field .text-muted {
font-size: 0.875rem;
}
</style>
@endpush
@@ -73,7 +77,7 @@
<div class="row">
<div class="col-md-3 mb-3 form-control-validation">
<label class="form-label">Luas Lahan (m2) <span class="text-danger">*</span></label>
<label class="form-label">Luas Lahan (ha) <span class="text-danger">*</span></label>
<input type="number" step="0.01" id="luas_lahan" name="luas_lahan" class="form-control @error('luas_lahan') is-invalid @enderror" placeholder="Contoh: 1.5" required
value="{{ old('luas_lahan', $lahanSelected->luas_lahan) }}" />
@error('luas_lahan')<div class="error invalid-feedback">{{ $message }}</div>@enderror
@@ -129,17 +133,19 @@
</div>
<div class="row">
<div class="col-md-3 mb-3 form-control-validation">
<div class="col-md-6 mb-3 form-control-validation">
<label class="form-label">Kondisi Umum Tanaman</label>
<select id="kondisi_tanaman" name="kondisi_tanaman" class="form-select @error('kondisi_tanaman') is-invalid @enderror">
<option value="">Pilih Kondisi Tanaman</option>
<option value="{{ \App\Enums\KondisiTanaman::BAIK }}" {{ old('kondisi_tanaman', $lahanSelected->kondisi_tanaman) == \App\Enums\KondisiTanaman::BAIK ? 'selected' : '' }}>Baik</option>
<option value="{{ \App\Enums\KondisiTanaman::SEDANG }}" {{ old('kondisi_tanaman', $lahanSelected->kondisi_tanaman) == \App\Enums\KondisiTanaman::SEDANG ? 'selected' : '' }}>Sedang</option>
<option value="{{ \App\Enums\KondisiTanaman::BURUK }}" {{ old('kondisi_tanaman', $lahanSelected->kondisi_tanaman) == \App\Enums\KondisiTanaman::BURUK ? 'selected' : '' }}>Buruk</option>
<option value="{{ \App\Enums\KondisiTanaman::BAIK }}" {{ old('kondisi_tanaman', $lahanSelected->kondisi_tanaman) == \App\Enums\KondisiTanaman::BAIK ? 'selected' : '' }}>{{ \App\Enums\KondisiTanaman::BAIK->label() }}</option>
<option value="{{ \App\Enums\KondisiTanaman::SEDANG }}" {{ old('kondisi_tanaman', $lahanSelected->kondisi_tanaman) == \App\Enums\KondisiTanaman::SEDANG ? 'selected' : '' }}>{{ \App\Enums\KondisiTanaman::SEDANG->label() }}</option>
<option value="{{ \App\Enums\KondisiTanaman::BURUK }}" {{ old('kondisi_tanaman', $lahanSelected->kondisi_tanaman) == \App\Enums\KondisiTanaman::BURUK ? 'selected' : '' }}>{{ \App\Enums\KondisiTanaman::BURUK->label() }}</option>
</select>
@error('kondisi_tanaman')<div class="error invalid-feedback">{{ $message }}</div>@enderror
</div>
<div class="col-md-3 mb-3 form-control-validation">
</div>
<div class="row">
<!-- <div class="col-md-3 mb-3 form-control-validation">
<label class="form-label">Serangan Hama</label>
<select id="serangan_hama" name="serangan_hama" class="form-select @error('serangan_hama') is-invalid @enderror">
<option value="">Pilih Serangan Hama</option>
@@ -158,14 +164,129 @@
<option value="{{ \App\Enums\PenyakitTanaman::DAUN_BERCAK }}" {{ old('penyakit_tanaman', $lahanSelected->penyakit_tanaman) == \App\Enums\PenyakitTanaman::DAUN_BERCAK ? 'selected' : '' }}>Daun Bercak</option>
<option value="{{ \App\Enums\PenyakitTanaman::TANAMAN_LAYU }}" {{ old('penyakit_tanaman', $lahanSelected->penyakit_tanaman) == \App\Enums\PenyakitTanaman::TANAMAN_LAYU ? 'selected' : '' }}>Tanaman Layu</option>
</select>
</div> -->
<div class="col-md-3 mb-4 form-control-validation auto-pest-disease-field">
<label class="form-label">Jenis Hama</label>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_hama') is-invalid @enderror" disabled
type="checkbox"
name="jenis_hama[]"
value="Penggerek buah"
id="jenis-hama-penggerek-buah"
{{ in_array('Penggerek buah', $jenisHamaOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-hama-bentuk">Penggerek buah</label>
</div>
<div class="col-md-3 mb-3 form-control-validation">
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_hama') is-invalid @enderror" disabled
type="checkbox"
name="jenis_hama[]"
value="Penggerek batang"
id="jenis-hama-penggerek-batang"
{{ in_array('Penggerek batang', $jenisHamaOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-hama-bentuk">Penggerek batang</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_hama') is-invalid @enderror" disabled
type="checkbox"
name="jenis_hama[]"
value="Kutu putih/kutu sisik"
id="jenis-hama-kutu"
{{ in_array('Kutu putih/kutu sisik', $jenisHamaOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-hama-bentuk">Kutu putih/kutu sisik</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_hama') is-invalid @enderror" disabled
type="checkbox"
name="jenis_hama[]"
value="Ulat pemakan daun"
id="jenis-hama-ulat"
{{ in_array('Ulat pemakan daun', $jenisHamaOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-hama-bentuk">Ulat pemakan daun</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_hama') is-invalid @enderror" disabled
type="checkbox"
name="jenis_hama[]"
value="Tikus"
id="jenis-hama-tikus"
{{ in_array('Tikus', $jenisHamaOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-hama-bentuk">Tikus</label>
</div>
<small class="text-muted text-secondary">* Tidak diisi, terisi otomatis di praktik budidaya</small>
@error('jenis_hama')
<div class="error invalid-feedback d-block">{{ $message }}</div>
@enderror
</div>
<div class="col-md-3 mb-4 form-control-validation auto-pest-disease-field">
<label class="form-label">Jenis Penyakit</label>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_penyakit') is-invalid @enderror" disabled
type="checkbox"
name="jenis_penyakit[]"
value="Karat daun"
id="jenis-penyakit-karat-daun"
{{ in_array('Karat daun', $jenisPenyakitOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-penyakit-bentuk">Karat daun</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_penyakit') is-invalid @enderror" disabled
type="checkbox"
name="jenis_penyakit[]"
value="Busuk buah/antraknosa"
id="jenis-penyakit-busuk-buah"
{{ in_array('Busuk buah/antraknosa', $jenisPenyakitOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-penyakit-bentuk">Busuk buah/antraknosa</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_penyakit') is-invalid @enderror" disabled
type="checkbox"
name="jenis_penyakit[]"
value="Busuk akar"
id="jenis-penyakit-busuk-akar"
{{ in_array('Busuk akar', $jenisPenyakitOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-penyakit-bentuk">Busuk akar</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_penyakit') is-invalid @enderror" disabled
type="checkbox"
name="jenis_penyakit[]"
value="Bercak daun"
id="jenis-penyakit-bercak-daun"
{{ in_array('Bercak daun', $jenisPenyakitOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-penyakit-bentuk">Bercak daun</label>
</div>
<div class="form-check mt-2">
<input class="form-check-input @error('jenis_penyakit') is-invalid @enderror" disabled
type="checkbox"
name="jenis_penyakit[]"
value="Layu fusarium"
id="jenis-penyakit-layu-fusarium"
{{ in_array('Layu fusarium', $jenisPenyakitOtomatis ?? [], true) ? 'checked' : '' }}>
<label class="form-check-label" for="jenis-penyakit-bentuk">Layu fusarium</label>
</div>
<small class="text-muted text-secondary">* Tidak diisi, terisi otomatis di Praktik Budidaya</small>
@error('jenis_penyakit')
<div class="error invalid-feedback d-block">{{ $message }}</div>
@enderror
</div>
<div class="col-md-6 mb-3 form-control-validation">
<label class="form-label">Keparahan Serangan Hama/Penyakit</label>
<select id="keparahan_serangan" name="keparahan_serangan" class="form-select @error('keparahan_serangan') is-invalid @enderror">
<option value="">Pilih Keparahan Serangan</option>
<option value="{{ \App\Enums\KeparahanSerangan::RINGAN }}" {{ old('keparahan_serangan', $lahanSelected->keparahan_serangan) == \App\Enums\KeparahanSerangan::RINGAN ? 'selected' : '' }}>Ringan</option>
<option value="{{ \App\Enums\KeparahanSerangan::SEDANG }}" {{ old('keparahan_serangan', $lahanSelected->keparahan_serangan) == \App\Enums\KeparahanSerangan::SEDANG ? 'selected' : '' }}>Sedang</option>
<option value="{{ \App\Enums\KeparahanSerangan::BERAT }}" {{ old('keparahan_serangan', $lahanSelected->keparahan_serangan) == \App\Enums\KeparahanSerangan::BERAT ? 'selected' : '' }}>Berat</option>
<option value="{{ \App\Enums\KeparahanSerangan::RINGAN }}" {{ old('keparahan_serangan', $lahanSelected->keparahan_serangan) == \App\Enums\KeparahanSerangan::RINGAN ? 'selected' : '' }}>{{ \App\Enums\KeparahanSerangan::RINGAN->label() }}</option>
<option value="{{ \App\Enums\KeparahanSerangan::SEDANG }}" {{ old('keparahan_serangan', $lahanSelected->keparahan_serangan) == \App\Enums\KeparahanSerangan::SEDANG ? 'selected' : '' }}>{{ \App\Enums\KeparahanSerangan::SEDANG->label() }}</option>
<option value="{{ \App\Enums\KeparahanSerangan::BERAT }}" {{ old('keparahan_serangan', $lahanSelected->keparahan_serangan) == \App\Enums\KeparahanSerangan::BERAT ? 'selected' : '' }}>{{ \App\Enums\KeparahanSerangan::BERAT->label() }}</option>
</select>
@error('keparahan_serangan')<div class="error invalid-feedback">{{ $message }}</div>@enderror
</div>
@@ -286,6 +407,7 @@
<div class="row mt-3">
<div class="col-12 text-end">
<a href="{{ route('petani.index') }}" class="btn btn-secondary me-2 wave-effect wave-light">Kembali</a>
<button id="delete-lahan"type="button" class="btn btn-danger data-submit wave-effect wave-light"><i class="ti tabler-trash me-2"></i> Hapus Lahan</button>
<button type="submit" class="btn btn-success data-submit wave-effect wave-light"><i class="ti tabler-device-floppy me-2"></i> Simpan Lahan</button>
</div>
</div>
@@ -702,7 +824,8 @@
});
document.getElementById('path').value = JSON.stringify(pathData);
let area = L.GeometryUtil.geodesicArea(latlngs);
$('#luas_lahan').val(area.toFixed(2));
let areaHa = area / 10000;
$('#luas_lahan').val(areaHa.toFixed(4));
}
const previewTemplate = `
@@ -764,6 +887,7 @@
name: "Foto Lahan " + (index + 1),
size: 1024,
id: index,
file_path: pathStr,
isServerFile: true,
accepted: true
};
@@ -782,7 +906,7 @@
let deleteInput = $('<input>').attr({
type: 'hidden',
name: 'deleted_photos[]',
value: file.id
value: file.file_path
});
$('#deleted-photos-container').append(deleteInput);
}
@@ -811,7 +935,7 @@
let deleteInput = $('<input>').attr({
type: 'hidden',
name: 'deleted_photos[]',
value: fileToReplace.id
value: fileToReplace.file_path
});
$('#deleted-photos-container').append(deleteInput);
}
@@ -836,8 +960,6 @@
}
});
// FORM VALIDATION & SUBMIT
$('#petani-lahan-tanaman').validate({
rules: {
luas_lahan: { required: true },
@@ -894,8 +1016,15 @@
'Accept': 'application/json'
},
success: function(res) {
alert('Data lahan berhasil disimpan!');
window.location.href = "{{ route('petani.index') }}";
Swal.fire({
icon: 'success',
title: 'Berhasil!',
text: 'Data lahan berhasil disimpan.',
showConfirmButton: false,
timer: 1500
}).then(() => {
window.location.href = res.redirect || window.location.href;
});
},
error: function(xhr) {
submitBtn.prop('disabled', false).html(originalText);
@@ -906,10 +1035,22 @@
$.each(errors, function(key, val) {
errorMsg += val[0] + "\n";
});
alert("Penyimpanan Gagal:\n\n" + errorMsg);
Swal.fire({
icon: 'warning',
title: 'Penyimpanan Gagal',
text: errorMsg,
confirmButtonColor: '#dc3545'
});
} else {
let errorDetail = xhr.responseJSON && xhr.responseJSON.message ? xhr.responseJSON.message : xhr.statusText;
alert("Error " + xhr.status + ": " + errorDetail);
Swal.fire({
icon: 'error',
title: 'Terjadi Kesalahan',
text: "Error " + xhr.status + ": " + errorDetail,
confirmButtonColor: '#dc3545'
});
console.error(xhr.responseText);
}
}
@@ -919,6 +1060,29 @@
}
});
$('#delete-lahan').click(function(e) {
e.preventDefault();
$.ajax({
url: "{{ route('petani.lahan-tanaman.destroy', ['petani' => $petani->id, 'lahan_tanaman' => $lahanSelected->id]) }}",
type: "POST",
data: {
_method: 'DELETE',
_token: $('input[name="_token"]').val()
},
success: function(res) {
Swal.fire({
icon: 'success',
title: 'Berhasil!',
text: 'Data lahan berhasil dihapus.',
showConfirmButton: false,
timer: 1500
}).then(() => {
window.location.href = "{{ route('petani.lahan-tanaman.index', ['petani' => $petani->id]) }}";
});
}
});
});
initWilayah();
initKomoditas();
});
@@ -29,6 +29,11 @@
white-space: nowrap !important;
line-height: 1.5 !important;
}
#section-pelatihan,
#section-sertifikasi {
scroll-margin-top: 96px;
}
</style>
@endpush
@@ -51,7 +56,7 @@
<div class="col-md-12">
@include('produktivitas.petani.header', ['petani' => $petani])
<div class="card mb-6">
<div class="card mb-6" id="section-pelatihan">
<div class="card-body pt-12">
<h5 class="pb-4 border-bottom mb-4">
Riwayat Pelatihan
@@ -83,6 +88,7 @@
class="delete-db-form">
@csrf
@method('DELETE')
<input type="hidden" name="redirect_fragment" value="section-pelatihan">
<button type="submit" class="btn btn-outline-danger">
<i class="icon-base ti tabler-trash icon-sm"></i>
@@ -101,6 +107,7 @@
action="{{ route('petani.pendidikan-pelatihan.pelatihan.store', $petani->id) }}"
class="form-repeater-pelatihan">
@csrf
<input type="hidden" name="redirect_fragment" value="section-sertifikasi">
<div data-repeater-list="riwayat_pelatihan">
<div data-repeater-item>
@@ -170,7 +177,7 @@
</div>
{{-- SERTIFIKASI KEAHLIAN --}}
<div class="card mb-6">
<div class="card mb-6" id="section-sertifikasi">
<div class="card-body pt-12">
<h5 class="pb-4 border-bottom mb-4">
Sertifikasi Keahlian
@@ -234,6 +241,7 @@
class="delete-db-form">
@csrf
@method('DELETE')
<input type="hidden" name="redirect_fragment" value="section-sertifikasi">
<button type="submit" class="btn btn-outline-danger">
<i class="icon-base ti tabler-trash icon-sm"></i>
@@ -252,6 +260,7 @@
action="{{ route('petani.pendidikan-pelatihan.sertifikasi.store', $petani->id) }}"
class="form-repeater-sertifikasi">
@csrf
<input type="hidden" name="redirect_fragment" value="section-sertifikasi">
<div data-repeater-list="sertifikasi">
<div data-repeater-item>
@@ -518,6 +518,57 @@
$('#tenaga-kerja, #frekuensi-pemangkasan-komoditas-utama, #frekuensi-pemangkasan-pohon-penaung, #penyerbukan-manual, #pemberian-pupuk, #jenis-pupuk').select2();
function syncTeknikPemangkasanState() {
const tidakPernahMemangkas = $('#frekuensi-pemangkasan-komoditas-utama').val() === '{{ \App\Enums\PraktikBudidaya\FrekuensiPemangkasanUtama::TIDAK_PERNAH->value }}';
const $teknikInputs = $('input[name="teknik_pemangkasan[]"]');
const $lainnyaInput = $('#input-teknik-pemangkasan-lainnya');
$teknikInputs
.prop('disabled', tidakPernahMemangkas)
.closest('.form-check')
.toggleClass('opacity-50', tidakPernahMemangkas);
if (tidakPernahMemangkas) {
$teknikInputs.prop('checked', false);
$lainnyaInput.val('');
}
$lainnyaInput.prop('disabled', tidakPernahMemangkas || !$('#teknik-pemangkasan-lainnya').is(':checked'));
}
$('#frekuensi-pemangkasan-komoditas-utama, #teknik-pemangkasan-lainnya').on('change select2:select select2:clear', syncTeknikPemangkasanState);
syncTeknikPemangkasanState();
function syncPemupukanState() {
const tidakPernahMemberiPupuk = $('#pemberian-pupuk').val() === '{{ \App\Enums\PraktikBudidaya\PemberianPupuk::TIDAK_PERNAH->value }}';
const $pemupukanFields = $(
'#jenis-pupuk, ' +
'input[name="frekuensi_pemupukan"], #input-frekuensi-pemupukan-lainnya, ' +
'#estimasi-dosis-pupuk-organik, #estimasi-dosis-pupuk-anorganik, ' +
'input[name="waktu_pemberian_pupuk"], #input-waktu-pemberian-pupuk-lainnya, ' +
'input[name="cara_pemberian_pupuk"], #input-cara-pemberian-pupuk-lainnya'
);
$pemupukanFields
.prop('disabled', tidakPernahMemberiPupuk)
.closest('.form-check, .form-control-validation')
.toggleClass('opacity-50', tidakPernahMemberiPupuk);
if (tidakPernahMemberiPupuk) {
$('#jenis-pupuk').val('').trigger('change.select2');
$('input[name="frekuensi_pemupukan"], input[name="waktu_pemberian_pupuk"], input[name="cara_pemberian_pupuk"]').prop('checked', false);
$('#input-frekuensi-pemupukan-lainnya, #estimasi-dosis-pupuk-organik, #estimasi-dosis-pupuk-anorganik, #input-waktu-pemberian-pupuk-lainnya, #input-cara-pemberian-pupuk-lainnya').val('');
} else {
$('#input-frekuensi-pemupukan-lainnya').prop('disabled', !$('input[data-target="#input-frekuensi-pemupukan-lainnya"]').is(':checked'));
$('#input-waktu-pemberian-pupuk-lainnya').prop('disabled', !$('input[data-target="#input-waktu-pemberian-pupuk-lainnya"]').is(':checked'));
$('#input-cara-pemberian-pupuk-lainnya').prop('disabled', !$('input[data-target="#input-cara-pemberian-pupuk-lainnya"]').is(':checked'));
}
}
$('#pemberian-pupuk').on('change select2:select select2:clear', syncPemupukanState);
syncPemupukanState();
setTimeout(syncPemupukanState, 0);
const $switch = $('input[name="disimpan_untuk_diri_sendiri"]');
const $text = $('#switch-text');
@@ -636,6 +687,35 @@
trigger.addEventListener('change', toggleInput);
toggleInput();
});
const frekuensiPemangkasan = document.getElementById('frekuensi-pemangkasan-komoditas-utama');
const teknikPemangkasanInputs = document.querySelectorAll('input[name="teknik_pemangkasan[]"]');
const teknikPemangkasanLainnya = document.getElementById('input-teknik-pemangkasan-lainnya');
function toggleTeknikPemangkasan() {
const tidakPernahMemangkas = frekuensiPemangkasan && frekuensiPemangkasan.value === '{{ \App\Enums\PraktikBudidaya\FrekuensiPemangkasanUtama::TIDAK_PERNAH->value }}';
teknikPemangkasanInputs.forEach(function (input) {
input.disabled = tidakPernahMemangkas;
input.closest('.form-check')?.classList.toggle('opacity-50', tidakPernahMemangkas);
if (tidakPernahMemangkas) {
input.checked = false;
}
});
if (teknikPemangkasanLainnya) {
teknikPemangkasanLainnya.disabled = tidakPernahMemangkas || !document.getElementById('teknik-pemangkasan-lainnya')?.checked;
if (tidakPernahMemangkas) {
teknikPemangkasanLainnya.value = '';
}
}
}
frekuensiPemangkasan?.addEventListener('change', toggleTeknikPemangkasan);
document.getElementById('teknik-pemangkasan-lainnya')?.addEventListener('change', toggleTeknikPemangkasan);
toggleTeknikPemangkasan();
});
</script>
@endpush
@@ -39,7 +39,8 @@
<form id="praktikBudidayaForm" action="{{ route('petani.praktik-budidaya.update', [$petani->id, $praktikBudidaya->id]) }}" method="POST">
@csrf
@method('PUT')
<div class="card mb-6">
<input type="hidden" name="redirect_fragment" value="section-opt">
<div class="card mb-6" id="section-praktik-pemupukan">
<div class="card-body pt-12">
<h5 class="pb-4 border-bottom mb-4">Persiapan Lahan & Tanaman</h5>
<div class="row">
@@ -541,8 +542,9 @@
<form id="praktikBudidayaForm" action="{{ route('petani.praktik-budidaya.update', [$petani->id, $praktikBudidaya->id]) }}" method="POST">
@csrf
@method('PUT')
<input type="hidden" name="redirect_fragment" value="section-biaya-produksi">
<div class="card mb-6">
<div class="card mb-6" id="section-opt">
<div class="card-body pt-12">
<!-- INFORMASI PETANI -->
<h5 class="pb-4 border-bottom mb-4">Pengendalian Organisme Pengganggu Tumbuhan (OPT)</h5>
@@ -1048,7 +1050,8 @@
<form id="praktikBudidayaForm" action="{{ route('petani.praktik-budidaya.update', [$petani->id, $praktikBudidaya->id]) }}" method="POST">
@csrf
@method('PUT')
<div class="card mb-6">
<input type="hidden" name="redirect_fragment" value="section-penanganan-panen">
<div class="card mb-6" id="section-biaya-produksi">
<div class="card-body pt-12">
<h5 class="pb-4 border-bottom mb-4">Struktur Biaya Produksi Permusim</h5>
<div class="row">
@@ -1360,7 +1363,8 @@
<form id="praktikBudidayaForm" action="{{ route('petani.praktik-budidaya.update', [$petani->id, $praktikBudidaya->id]) }}" method="POST">
@csrf
@method('PUT')
<div class="card mb-6">
<input type="hidden" name="redirect_fragment" value="section-produktivitas">
<div class="card mb-6" id="section-penanganan-panen">
<div class="card-body pt-12">
<h5 class="pb-4 border-bottom mb-4">Penanganan Awal Setelah Panen</h5>
<div class="row">
@@ -1546,7 +1550,7 @@
</div>
</div>
</form>
<div class="card mb-6">
<div class="card mb-6" id="section-produktivitas">
<div class="card-body pt-12">
<h5 class="pb-4 border-bottom mb-4">
Produktivitas Rata-rata 3 Musim Panen Terakhir per Komoditas
@@ -1579,6 +1583,7 @@
<form method="POST" action="{{ route('petani.survey-produktivitas.destroy', [$petani->id, $row->id]) }}">
@csrf
@method('DELETE')
<input type="hidden" name="redirect_fragment" value="section-produktivitas">
<button type="submit" class="btn btn-outline-danger">
<i class="icon-base ti tabler-trash icon-sm"></i>
</button>
@@ -1593,6 +1598,7 @@
action="{{ route('petani.survey-produktivitas.store', $petani->id) }}"
class="form-repeater">
@csrf
<input type="hidden" name="redirect_fragment" value="section-kehilangan-hasil">
<div data-repeater-list="produktivitas_komoditas">
<div data-repeater-item>
@@ -1657,7 +1663,8 @@
<form id="praktikBudidayaForm" action="{{ route('petani.praktik-budidaya.update', [$petani->id, $praktikBudidaya->id]) }}" method="POST">
@csrf
@method('PUT')
<div class="card mb-6">
<input type="hidden" name="redirect_fragment" value="section-kehilangan-hasil">
<div class="card mb-6" id="section-kehilangan-hasil">
<div class="card-body pt-12">
<h5 class="pb-4 border-bottom mb-4">Kehilangan Hasil Akibat Organisme Pengganggu Tumbuhan (OPT)</h5>
<div class="row">
@@ -1706,6 +1713,19 @@
</div>
@endsection
@push('scripts-head')
<style>
#section-praktik-pemupukan,
#section-opt,
#section-biaya-produksi,
#section-penanganan-panen,
#section-produktivitas,
#section-kehilangan-hasil {
scroll-margin-top: 96px;
}
</style>
@endpush
@push('scripts')
<script>
'use strict';
@@ -1713,6 +1733,57 @@
$('#tenaga-kerja, #frekuensi-pemangkasan-komoditas-utama, #frekuensi-pemangkasan-pohon-penaung, #penyerbukan-manual, #pemberian-pupuk, #jenis-pupuk, #metode-penanganan-hama-penyakit, #intensitas-serangan, #waktu-kemunculan-terparah, #frekuensi-sanitasi-lahan, #penanganan-sisa-buah-ranting, #penanganan-gulma, #kondisi-pengelolaan-air-irigasi, #kebutuhan-air-permusim, #pemahaman-manfaat-konservasi, #dasar-penentuan-panen, #praktik-sortasi, #bentuk-sortasi, #estimasi-kehilangan-akibat-opt, #tingkat-reject, #tindakan-hasil-reject, #estimasi-kehilangan-akibat-hama, #komoditas-id').select2();
function syncTeknikPemangkasanState() {
const tidakPernahMemangkas = $('#frekuensi-pemangkasan-komoditas-utama').val() === '{{ \App\Enums\PraktikBudidaya\FrekuensiPemangkasanUtama::TIDAK_PERNAH->value }}';
const $teknikInputs = $('input[name="teknik_pemangkasan[]"]');
const $lainnyaInput = $('#input-teknik-pemangkasan-lainnya');
$teknikInputs
.prop('disabled', tidakPernahMemangkas)
.closest('.form-check')
.toggleClass('opacity-50', tidakPernahMemangkas);
if (tidakPernahMemangkas) {
$teknikInputs.prop('checked', false);
$lainnyaInput.val('');
}
$lainnyaInput.prop('disabled', tidakPernahMemangkas || !$('#teknik-pemangkasan-lainnya').is(':checked'));
}
$('#frekuensi-pemangkasan-komoditas-utama, #teknik-pemangkasan-lainnya').on('change select2:select select2:clear', syncTeknikPemangkasanState);
syncTeknikPemangkasanState();
function syncPemupukanState() {
const tidakPernahMemberiPupuk = $('#pemberian-pupuk').val() === '{{ \App\Enums\PraktikBudidaya\PemberianPupuk::TIDAK_PERNAH->value }}';
const $pemupukanFields = $(
'#jenis-pupuk, ' +
'input[name="frekuensi_pemupukan"], #input-frekuensi-pemupukan-lainnya, ' +
'#estimasi-dosis-pupuk-organik, #estimasi-dosis-pupuk-anorganik, ' +
'input[name="waktu_pemberian_pupuk"], #input-waktu-pemberian-pupuk-lainnya, ' +
'input[name="cara_pemberian_pupuk"], #input-cara-pemberian-pupuk-lainnya'
);
$pemupukanFields
.prop('disabled', tidakPernahMemberiPupuk)
.closest('.form-check, .form-control-validation')
.toggleClass('opacity-50', tidakPernahMemberiPupuk);
if (tidakPernahMemberiPupuk) {
$('#jenis-pupuk').val('').trigger('change.select2');
$('input[name="frekuensi_pemupukan"], input[name="waktu_pemberian_pupuk"], input[name="cara_pemberian_pupuk"]').prop('checked', false);
$('#input-frekuensi-pemupukan-lainnya, #estimasi-dosis-pupuk-organik, #estimasi-dosis-pupuk-anorganik, #input-waktu-pemberian-pupuk-lainnya, #input-cara-pemberian-pupuk-lainnya').val('');
} else {
$('#input-frekuensi-pemupukan-lainnya').prop('disabled', !$('input[data-target="#input-frekuensi-pemupukan-lainnya"]').is(':checked'));
$('#input-waktu-pemberian-pupuk-lainnya').prop('disabled', !$('input[data-target="#input-waktu-pemberian-pupuk-lainnya"]').is(':checked'));
$('#input-cara-pemberian-pupuk-lainnya').prop('disabled', !$('input[data-target="#input-cara-pemberian-pupuk-lainnya"]').is(':checked'));
}
}
$('#pemberian-pupuk').on('change select2:select select2:clear', syncPemupukanState);
syncPemupukanState();
setTimeout(syncPemupukanState, 0);
const $switch = $('input[name="disimpan_untuk_diri_sendiri"]');
const $text = $('#switch-text');
@@ -1822,6 +1893,35 @@
toggleInput();
});
const frekuensiPemangkasan = document.getElementById('frekuensi-pemangkasan-komoditas-utama');
const teknikPemangkasanInputs = document.querySelectorAll('input[name="teknik_pemangkasan[]"]');
const teknikPemangkasanLainnya = document.getElementById('input-teknik-pemangkasan-lainnya');
function toggleTeknikPemangkasan() {
const tidakPernahMemangkas = frekuensiPemangkasan && frekuensiPemangkasan.value === '{{ \App\Enums\PraktikBudidaya\FrekuensiPemangkasanUtama::TIDAK_PERNAH->value }}';
teknikPemangkasanInputs.forEach(function (input) {
input.disabled = tidakPernahMemangkas;
input.closest('.form-check')?.classList.toggle('opacity-50', tidakPernahMemangkas);
if (tidakPernahMemangkas) {
input.checked = false;
}
});
if (teknikPemangkasanLainnya) {
teknikPemangkasanLainnya.disabled = tidakPernahMemangkas || !document.getElementById('teknik-pemangkasan-lainnya')?.checked;
if (tidakPernahMemangkas) {
teknikPemangkasanLainnya.value = '';
}
}
}
frekuensiPemangkasan?.addEventListener('change', toggleTeknikPemangkasan);
document.getElementById('teknik-pemangkasan-lainnya')?.addEventListener('change', toggleTeknikPemangkasan);
toggleTeknikPemangkasan();
const biayaProduksiFields = [
'upah-tenaga-kerja',
'biaya-bibit',
@@ -1,5 +1,17 @@
@extends('layout.main')
@push('scripts-head')
<style>
#section-utama,
#section-sosial-budaya,
#section-keanggotaan-kelompok,
#section-akses-keuangan,
#section-keterikatan-hutang {
scroll-margin-top: 96px;
}
</style>
@endpush
@section('content')
<div class="container-xxl flex-grow-1 container-p-y">
@if (session('success'))
@@ -1062,6 +1074,20 @@
const pinjamanTokohAdatAda = @json($pinjamanTokohAdatAdaValue);
const tekananJualSegeraAda = @json($tekananJualSegeraAdaValue);
const kebebasanMemilihPembeliCukupBebas = Number(@json($kebebasanMemilihPembeliCukupBebasValue));
const sectionAnchors = {
utama: 'section-utama',
sosial_budaya: 'section-sosial-budaya',
keanggotaan_kelompok: 'section-keanggotaan-kelompok',
akses_keuangan: 'section-akses-keuangan',
keterikatan_hutang: 'section-keterikatan-hutang'
};
const nextSectionAnchors = {
utama: 'section-sosial-budaya',
sosial_budaya: 'section-keanggotaan-kelompok',
keanggotaan_kelompok: 'section-akses-keuangan',
akses_keuangan: 'section-keterikatan-hutang',
keterikatan_hutang: 'section-keterikatan-hutang'
};
const fieldExamples = {
jumlah_tanggungan: 'Contoh: 4',
anak_masih_sekolah: 'Contoh: 2',
@@ -1399,7 +1425,8 @@
}
function syncPihakMembantuFields() {
const isTidakAda = $('#pihak-membantu').val() === pihakMembantuTanpaBantuan;
const isAdaSengketa = $('input[name="ada_sengketa"]:checked').val() === '1';
const isTidakAda = !isAdaSengketa || $('#pihak-membantu').val() === pihakMembantuTanpaBantuan;
const $fields = $('#pihak-membantu-nama, #tahun-bantuan');
$fields.prop('disabled', isTidakAda);
@@ -1409,6 +1436,21 @@
}
}
function syncSengketaFields() {
const isAdaSengketa = $('input[name="ada_sengketa"]:checked').val() === '1';
const $fields = $('#keterangan-sengketa, #pihak-membantu, #status-konflik');
const $assistanceFields = $('#pihak-membantu-nama, #tahun-bantuan');
$fields.prop('disabled', !isAdaSengketa);
if (!isAdaSengketa) {
$fields.add($assistanceFields).val('');
$fields.filter('select').trigger('change.select2');
}
syncPihakMembantuFields();
}
function syncPernahJualHargaLebihTinggiFields() {
const isPernah = $('#pernah-jual-harga-lebih-tinggi').val() === pernahJualHargaLebihTinggiPernah;
const $field = $('#penyebab-harga-lebih-tinggi');
@@ -1601,6 +1643,37 @@
clearPendapatanRowValidation($row);
}
function setupSectionAnchors() {
$('input[name="form_section"]').each(function () {
const section = this.value;
const anchor = sectionAnchors[section];
const nextAnchor = nextSectionAnchors[section] || anchor;
const $form = $(this).closest('form');
if (anchor) {
$form.find('> .card').first().attr('id', anchor);
}
if (nextAnchor && !$form.find('input[name="redirect_fragment"]').length) {
$('<input>', {
type: 'hidden',
name: 'redirect_fragment',
value: nextAnchor
}).appendTo($form);
}
});
if (window.location.hash) {
const target = document.getElementById(window.location.hash.substring(1));
if (target) {
setTimeout(function () {
target.scrollIntoView({ block: 'start' });
}, 0);
}
}
}
$(document).on('change', '.sosial-ekonomi-komoditas-utama', syncKomoditasLainnyaOptions);
$(document).on('input change', '.pendapatan-row input, .pendapatan-row select', function () {
clearPendapatanRowValidation($(this).closest('.pendapatan-row'));
@@ -1636,6 +1709,7 @@
});
});
$('#pihak-membantu').on('change', syncPihakMembantuFields);
$('input[name="ada_sengketa"]').on('change', syncSengketaFields);
$('#pernah-jual-harga-lebih-tinggi').on('change', syncPernahJualHargaLebihTinggiFields);
$('input[name="panutan_petani_sukses"]').on('change', syncPanutanFields);
$('input[name="terdaftar_kelompok_tani"]').on('change', syncTerdaftarKelompokFields);
@@ -1650,10 +1724,12 @@
$('#total-hutang-tidak-bersedia').on('change', syncTotalHutangFields);
$('input[name="tekanan_jual_segera"]').on('change', syncTekananJualFields);
$('input[name="kebebasan_memilih_pembeli"]').on('change', syncKebebasanPembeliFields);
setupSectionAnchors();
applySosialEkonomiExamples();
syncKomoditasLainnyaOptions();
setupAllPendapatanRows();
syncPihakMembantuFields();
syncSengketaFields();
syncPernahJualHargaLebihTinggiFields();
syncPanutanFields();
syncTerdaftarKelompokFields();
@@ -1,5 +1,17 @@
@extends('layout.main')
@push('scripts-head')
<style>
#section-utama,
#section-sosial-budaya,
#section-keanggotaan-kelompok,
#section-akses-keuangan,
#section-keterikatan-hutang {
scroll-margin-top: 96px;
}
</style>
@endpush
@section('content')
<div class="container-xxl flex-grow-1 container-p-y">
@if (session('success'))
@@ -1058,6 +1070,20 @@
const pinjamanTokohAdatAda = @json($pinjamanTokohAdatAdaValue);
const tekananJualSegeraAda = @json($tekananJualSegeraAdaValue);
const kebebasanMemilihPembeliCukupBebas = Number(@json($kebebasanMemilihPembeliCukupBebasValue));
const sectionAnchors = {
utama: 'section-utama',
sosial_budaya: 'section-sosial-budaya',
keanggotaan_kelompok: 'section-keanggotaan-kelompok',
akses_keuangan: 'section-akses-keuangan',
keterikatan_hutang: 'section-keterikatan-hutang'
};
const nextSectionAnchors = {
utama: 'section-sosial-budaya',
sosial_budaya: 'section-keanggotaan-kelompok',
keanggotaan_kelompok: 'section-akses-keuangan',
akses_keuangan: 'section-keterikatan-hutang',
keterikatan_hutang: 'section-keterikatan-hutang'
};
const fieldExamples = {
jumlah_tanggungan: 'Contoh: 4',
anak_masih_sekolah: 'Contoh: 2',
@@ -1395,7 +1421,8 @@
}
function syncPihakMembantuFields() {
const isTidakAda = $('#pihak-membantu').val() === pihakMembantuTanpaBantuan;
const isAdaSengketa = $('input[name="ada_sengketa"]:checked').val() === '1';
const isTidakAda = !isAdaSengketa || $('#pihak-membantu').val() === pihakMembantuTanpaBantuan;
const $fields = $('#pihak-membantu-nama, #tahun-bantuan');
$fields.prop('disabled', isTidakAda);
@@ -1405,6 +1432,21 @@
}
}
function syncSengketaFields() {
const isAdaSengketa = $('input[name="ada_sengketa"]:checked').val() === '1';
const $fields = $('#keterangan-sengketa, #pihak-membantu, #status-konflik');
const $assistanceFields = $('#pihak-membantu-nama, #tahun-bantuan');
$fields.prop('disabled', !isAdaSengketa);
if (!isAdaSengketa) {
$fields.add($assistanceFields).val('');
$fields.filter('select').trigger('change.select2');
}
syncPihakMembantuFields();
}
function syncPernahJualHargaLebihTinggiFields() {
const isPernah = $('#pernah-jual-harga-lebih-tinggi').val() === pernahJualHargaLebihTinggiPernah;
const $field = $('#penyebab-harga-lebih-tinggi');
@@ -1597,6 +1639,37 @@
clearPendapatanRowValidation($row);
}
function setupSectionAnchors() {
$('input[name="form_section"]').each(function () {
const section = this.value;
const anchor = sectionAnchors[section];
const nextAnchor = nextSectionAnchors[section] || anchor;
const $form = $(this).closest('form');
if (anchor) {
$form.find('> .card').first().attr('id', anchor);
}
if (nextAnchor && !$form.find('input[name="redirect_fragment"]').length) {
$('<input>', {
type: 'hidden',
name: 'redirect_fragment',
value: nextAnchor
}).appendTo($form);
}
});
if (window.location.hash) {
const target = document.getElementById(window.location.hash.substring(1));
if (target) {
setTimeout(function () {
target.scrollIntoView({ block: 'start' });
}, 0);
}
}
}
$(document).on('change', '.sosial-ekonomi-komoditas-utama', syncKomoditasLainnyaOptions);
$(document).on('input change', '.pendapatan-row input, .pendapatan-row select', function () {
clearPendapatanRowValidation($(this).closest('.pendapatan-row'));
@@ -1632,6 +1705,7 @@
});
});
$('#pihak-membantu').on('change', syncPihakMembantuFields);
$('input[name="ada_sengketa"]').on('change', syncSengketaFields);
$('#pernah-jual-harga-lebih-tinggi').on('change', syncPernahJualHargaLebihTinggiFields);
$('input[name="panutan_petani_sukses"]').on('change', syncPanutanFields);
$('input[name="terdaftar_kelompok_tani"]').on('change', syncTerdaftarKelompokFields);
@@ -1646,10 +1720,12 @@
$('#total-hutang-tidak-bersedia').on('change', syncTotalHutangFields);
$('input[name="tekanan_jual_segera"]').on('change', syncTekananJualFields);
$('input[name="kebebasan_memilih_pembeli"]').on('change', syncKebebasanPembeliFields);
setupSectionAnchors();
applySosialEkonomiExamples();
syncKomoditasLainnyaOptions();
setupAllPendapatanRows();
syncPihakMembantuFields();
syncSengketaFields();
syncPernahJualHargaLebihTinggiFields();
syncPanutanFields();
syncTerdaftarKelompokFields();