diff --git a/app/Enums/KondisiTanaman.php b/app/Enums/KondisiTanaman.php index ee29a12..c847dbd 100644 --- a/app/Enums/KondisiTanaman.php +++ b/app/Enums/KondisiTanaman.php @@ -4,7 +4,9 @@ enum KondisiTanaman: string { - case SEHAT = 'sehat'; - case SAKIT = 'sakit'; - case MATI = 'mati'; + case PRODUKTIF = 'productive'; + case KURANG_PRODUKTIF = 'less_productive'; + case TIDAK_PRODUKTIF = 'not_productive'; + case SAKIT = 'sick'; + case MATI = 'dead'; } diff --git a/app/Http/Controllers/Api/KabupatenKotaController.php b/app/Http/Controllers/Api/KabupatenKotaController.php index 8f0b62e..d8a6e81 100644 --- a/app/Http/Controllers/Api/KabupatenKotaController.php +++ b/app/Http/Controllers/Api/KabupatenKotaController.php @@ -7,40 +7,44 @@ use Illuminate\Http\JsonResponse; use App\Models\Wilayah\Provinsi; use App\Models\Wilayah\KabupatenKota; +use App\Http\Resources\Wilayah\KabupatenKotaResource; +use Illuminate\Http\Resources\Json\AnonymousResourceCollection; class KabupatenKotaController extends Controller { /** * Display a listing of the resource. */ - public function index(Request $request): JsonResponse + public function index(Request $request): AnonymousResourceCollection { - $size = +$request->get('size') ?: 10; + $size = $request->integer('size') ?: 10; - $master = KabupatenKota::query(); + $master = KabupatenKota::with('provinsi') + ->when($request->search, function ($q, $search) { + $search = strtolower($search); + $q->where(function ($query) use ($search) { + $query->whereRaw('lower(kode) like ?', ["%{$search}%"]) + ->orWhereRaw('lower(nama) like ?', ["%{$search}%"]); + }); + }) + ->when($request->provinsi_id, fn($q,$v) => $q->where('provinsi_id',$v)); - if ($request->has('search')) { - $s = $request->get('search'); - $s = strtolower($s); - $master->where(function($query) use ($s) { - $query->whereRaw('lower(kode) like (?)',["%{$s}%"]) - ->orWhereRaw('lower(nama) like (?)',["%{$s}%"]); - }); - } - if ($request->has('sort')) { - $order = $request->get('sort'); - $d = substr($order, 0, 1); - $dir = $d === '-' ? 'desc' : 'asc'; - $order = $d === '-' ? substr($order, 1) : $order; - $master->orderBy($order, $dir); - } - if ($request->has('provinsi_id')) { - $master->where('provinsi_id', $request->get('provinsi_id')); + if ($request->filled('sort')) { + $dir = str_starts_with($request->sort, '-') ? 'desc' : 'asc'; + $column = ltrim($request->sort, '-'); + + $allowed = ['id', 'kode', 'nama']; + + if (in_array($column, $allowed)) { + $master->orderBy($column, $dir); + } + } else { + $master->orderBy('kode', 'asc'); } $masterList = $master->paginate($size); - return response()->json($masterList); + return KabupatenKotaResource::collection($masterList); } /** @@ -62,9 +66,9 @@ public function store(Request $request) /** * Display the specified resource. */ - public function show(string $id) + public function show(string $id): JsonResponse { - return response()->json(KabupatenKota::findOrFail($id)); + return response()->json(KabupatenKotaResource::make(KabupatenKota::with('provinsi')->findOrFail($id))); } /** diff --git a/app/Http/Controllers/Api/KecamatanController.php b/app/Http/Controllers/Api/KecamatanController.php index fd189bc..568a936 100644 --- a/app/Http/Controllers/Api/KecamatanController.php +++ b/app/Http/Controllers/Api/KecamatanController.php @@ -16,7 +16,7 @@ class KecamatanController extends Controller */ public function index(Request $request): AnonymousResourceCollection { - $size = $request->get('size') ?: 10; + $size = $request->integer('size') ?: 10; $master = Kecamatan::with('kabupatenKota') ->when($request->search, function ($q, $search) { diff --git a/app/Http/Controllers/Api/KomoditasController.php b/app/Http/Controllers/Api/KomoditasController.php index 62359ac..83b4569 100644 --- a/app/Http/Controllers/Api/KomoditasController.php +++ b/app/Http/Controllers/Api/KomoditasController.php @@ -5,16 +5,18 @@ use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Http\JsonResponse; -use App\Models\Komoditas\Komoditas; +use App\Models\Pertanian\Komoditas; +use Illuminate\Http\Resources\Json\AnonymousResourceCollection; +use App\Http\Resources\Pertanian\KomoditasResource; class KomoditasController extends Controller { /** * Display a listing of the resource. */ - public function index(): JsonResponse + public function index(): AnonymousResourceCollection { - return response()->json(Komoditas::all()); + return KomoditasResource::collection(Komoditas::all()); } /** @@ -38,7 +40,7 @@ public function store(Request $request) */ public function show(string $id): JsonResponse { - return response()->json(Komoditas::findOrFail($id)); + return response()->json(KomoditasResource::make(Komoditas::findOrFail($id))); } /** diff --git a/app/Http/Controllers/Api/LahanController.php b/app/Http/Controllers/Api/LahanController.php index 87ee3d2..c4e45f7 100644 --- a/app/Http/Controllers/Api/LahanController.php +++ b/app/Http/Controllers/Api/LahanController.php @@ -7,24 +7,66 @@ use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Gate; +use Illuminate\Http\Resources\Json\AnonymousResourceCollection; +use Illuminate\Validation\Rules\Enum; -use App\Models\Map\Lahan; +use App\Models\Pertanian\Lahan; +use App\Http\Resources\Pertanian\LahanResource; +use App\Enums\StatusLahan; class LahanController extends Controller { /** * Display a listing of the resource. */ - public function index(): JsonResponse + public function index(Request $request): AnonymousResourceCollection { Gate::authorize('petani'); $user = Auth::user(); $profile = $user->profile; - $listLahan = Lahan::where('profile_id', $profile->id)->get(); + $size = $request->integer('size') ?: 10; - return response()->json($listLahan); + $listLahan = Lahan::where('profile_id', $profile->id) + ->when($request->search, function ($q, $search) { + $search = strtolower($search); + $q->whereRaw('lower(nama) like ?', ["%{$search}%"]); + }) + ->when($request->status_kepemilikan, fn($q,$v) => $q->where('status_kepemilikan',$v)) + ->when($request->desa_kelurahan_id, fn($q,$v) => $q->where('desa_kelurahan_id',$v)) + ->when($request->kecamatan_id, fn ($q, $v) => + $q->whereHas('desaKelurahan', fn ($k) => + $k->where('kecamatan_id', $v) + ) + ) + ->when($request->kabupaten_kota_id, fn ($q, $v) => + $q->whereHas('desaKelurahan.kecamatan', fn ($k) => + $k->where('kabupaten_kota_id', $v) + ) + ) + ->when($request->provinsi_id, fn ($q, $v) => + $q->whereHas('desaKelurahan.kecamatan.kabupatenkota', fn ($k) => + $k->where('provinsi_id', $v) + ) + ); + if ($request->filled('sort')) { + $dir = str_starts_with($request->sort, '-') ? 'desc' : 'asc'; + $column = ltrim($request->sort, '-'); + + $allowed = ['id', 'nama']; + + if (in_array($column, $allowed)) { + $listLahan->orderBy($column, $dir); + } + } else { + $listLahan->orderBy('nama', 'asc'); + } + + $listLahan = $listLahan->paginate($size); + + + return LahanResource::collection($listLahan); } /** @@ -39,66 +81,76 @@ public function store(Request $request): JsonResponse $validated = $request->validate([ 'nama' => ['required', 'string', 'max:255'], - 'status_kepemilikan' => ['required', 'string'], - 'desa_kelurahan_id' => ['numeric'], - 'path' => ['string'], - 'luas_lahan' => ['numeric'], + 'status_kepemilikan' => ['required', new Enum(StatusLahan::class)], + 'desa_kelurahan_id' => ['nullable', 'numeric', 'exists:master_desa_kelurahan,id'], + 'path' => ['nullable', 'array'], + 'path.*' => ['array'], + 'luas_lahan' => ['nullable', 'numeric'], ]); $lahan = Lahan::create([ - 'nama' => $validated['nama'], - 'status_kepemilikan' => $validated['status_kepemilikan'], + ...$validated, 'profile_id' => $profile->id, - 'desa_kelurahan_id' => $validated['desa_kelurahan_id'] ?? null, - 'path' => $validated['path'] ?? null, - 'luas_lahan' => $validated['luas_lahan'] ?? null, ]); - return response()->json($lahan, 201); + return (new LahanResource($lahan)) + ->response() + ->setStatusCode(201); } /** * Display the specified resource. */ - public function show(string $id) + public function show(string $id): JsonResponse { Gate::authorize('petani'); - $lahan = Lahan::findOrFail($id); + $lahan = Lahan::with('desaKelurahan')->findOrFail($id); + if ($lahan->profile_id !== Auth::user()->profile->id) { + return response()->json(['message' => 'Unauthorized'], 403); + } - return response()->json($lahan); + return (new LahanResource($lahan))->response(); } /** * Update the specified resource in storage. */ - public function update(Request $request, string $id) + public function update(Request $request, string $id): JsonResponse { Gate::authorize('petani'); $lahan = Lahan::findOrFail($id); + if ($lahan->profile_id !== Auth::user()->profile->id) { + return response()->json(['message' => 'Unauthorized'], 403); + } $validated = $request->validate([ 'nama' => ['required', 'string', 'max:255'], - 'status_kepemilikan' => ['required', 'string'], - 'desa_kelurahan_id' => ['numeric'], - 'path' => ['string'], - 'luas_lahan' => ['numeric'], + 'status_kepemilikan' => ['required', new Enum(StatusLahan::class)], + 'desa_kelurahan_id' => ['nullable', 'numeric', 'exists:master_desa_kelurahan,id'], + 'path' => ['nullable', 'array'], + 'path.*' => ['array'], + 'luas_lahan' => ['nullable', 'numeric'], ]); $lahan->update($validated); - return response()->json($lahan); + return (new LahanResource($lahan))->response(); } /** * Remove the specified resource from storage. */ - public function destroy(string $id) + public function destroy(string $id): JsonResponse { Gate::authorize('petani'); - $lahan = Lahan::findOrFail($id); + $lahan = Lahan::findOrFail($id); + if ($lahan->profile_id !== Auth::user()->profile->id) { + return response()->json(['message' => 'Unauthorized'], 403); + } + $lahan->delete(); return response()->json(null, 204); diff --git a/app/Http/Controllers/Api/ProvinsiController.php b/app/Http/Controllers/Api/ProvinsiController.php index aca9ec6..c8df6c1 100644 --- a/app/Http/Controllers/Api/ProvinsiController.php +++ b/app/Http/Controllers/Api/ProvinsiController.php @@ -6,37 +6,42 @@ use Illuminate\Http\Request; use Illuminate\Http\JsonResponse; use App\Models\Wilayah\Provinsi; +use App\Http\Resources\Wilayah\ProvinsiResource; +use Illuminate\Http\Resources\Json\AnonymousResourceCollection; class ProvinsiController extends Controller { /** * Display a listing of the resource. */ - public function index(Request $request): JsonResponse + public function index(Request $request): AnonymousResourceCollection { - $size = +$request->get('size') ?: 10; + $size = $request->integer('size') ?: 10; - $master = Provinsi::query(); - - if ($request->has('search')) { - $s = $request->get('search'); - $s = strtolower($s); - $master->where(function($query) use ($s) { - $query->whereRaw('lower(kode) like (?)',["%{$s}%"]) - ->orWhereRaw('lower(nama) like (?)',["%{$s}%"]); + $master = Provinsi::when($request->search, function ($q, $search) { + $search = strtolower($search); + $q->where(function ($query) use ($search) { + $query->whereRaw('lower(kode) like ?', ["%{$search}%"]) + ->orWhereRaw('lower(nama) like ?', ["%{$search}%"]); + }); }); - } - if ($request->has('sort')) { - $order = $request->get('sort'); - $d = substr($order, 0, 1); - $dir = $d === '-' ? 'desc' : 'asc'; - $order = $d === '-' ? substr($order, 1) : $order; - $master->orderBy($order, $dir); + + if ($request->filled('sort')) { + $dir = str_starts_with($request->sort, '-') ? 'desc' : 'asc'; + $column = ltrim($request->sort, '-'); + + $allowed = ['id', 'kode', 'nama']; + + if (in_array($column, $allowed)) { + $master->orderBy($column, $dir); + } + } else { + $master->orderBy('kode', 'asc'); } $masterList = $master->paginate($size); - return response()->json($masterList); + return ProvinsiResource::collection($masterList); } /** @@ -60,7 +65,7 @@ public function store(Request $request) */ public function show(string $id): JsonResponse { - return response()->json(Provinsi::findOrFail($id)); + return response()->json(ProvinsiResource::make(Provinsi::findOrFail($id))); } /** diff --git a/app/Http/Controllers/Api/TanamanController.php b/app/Http/Controllers/Api/TanamanController.php index 9aba598..6d008f2 100644 --- a/app/Http/Controllers/Api/TanamanController.php +++ b/app/Http/Controllers/Api/TanamanController.php @@ -5,52 +5,74 @@ use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Http\JsonResponse; -use App\Models\Map\Tanaman; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Gate; +use Illuminate\Http\Resources\Json\AnonymousResourceCollection; +use Illuminate\Validation\Rules\Enum; +use Illuminate\Validation\Rule; + +use App\Http\Resources\Pertanian\TanamanResource; +use App\Models\Pertanian\Tanaman; +use App\Enums\KondisiTanaman; class TanamanController extends Controller { /** * Display a listing of the resource. */ - public function index(Request $request): JsonResponse + public function index(Request $request): AnonymousResourceCollection { Gate::authorize('petani'); - $user = Auth::user(); - $profile = $user->profile; + $profile = Auth::user()->profile; - $size = +$request->get('size') ?: 10; + $size = $request->integer('size') ?: 10; - $tanamanQuery = Tanaman::query(); + $tanamanList = Tanaman::where('profile_id', $profile->id) + ->when($request->search, function ($q, $search) { + $search = strtolower($search); + $q->whereRaw('lower(nama) like ?', ["%{$search}%"]); + }) + ->when($request->status_kepemilikan, fn($q,$v) => $q->where('status_kepemilikan',$v)) + ->when($request->lahan_id, fn($q,$v) => $q->where('lahan_id',$v)) + ->when($request->komoditas_id, fn($q,$v) => $q->where('komoditas_id',$v)) + ->when($request->desa_kelurahan_id, fn($q,$v) => + $q->whereHas('lahan', fn($k) + => $k->where('desa_kelurahan_id',$v) + ) + ) + ->when($request->kecamatan_id, fn ($q, $v) => + $q->whereHas('lahan.desaKelurahan', fn ($k) => + $k->where('kecamatan_id', $v) + ) + ) + ->when($request->kabupaten_kota_id, fn ($q, $v) => + $q->whereHas('lahan.desaKelurahan.kecamatan', fn ($k) => + $k->where('kabupaten_kota_id', $v) + ) + ) + ->when($request->provinsi_id, fn ($q, $v) => + $q->whereHas('lahan.desaKelurahan.kecamatan.kabupatenkota', fn ($k) => + $k->where('provinsi_id', $v) + ) + ); - $tanamanQuery = $tanamanQuery->where('profile_id', $profile->id); + if ($request->filled('sort')) { + $dir = str_starts_with($request->sort, '-') ? 'desc' : 'asc'; + $column = ltrim($request->sort, '-'); - if ($request->has('search')) { - $s = $request->get('search'); - $s = strtolower($s); - $tanamanQuery->where(function($query) use ($s) { - $query->whereRaw('lower(nama) like (?)',["%{$s}%"]); - }); - } - if ($request->has('sort')) { - $order = $request->get('sort'); - $d = substr($order, 0, 1); - $dir = $d === '-' ? 'desc' : 'asc'; - $order = $d === '-' ? substr($order, 1) : $order; - $tanamanQuery->orderBy($order, $dir); - } - if ($request->has('lahan_id')) { - $tanamanQuery->where('lahan_id', $request->get('lahan_id')); - } - if ($request->has('komoditas_id')) { - $tanamanQuery->where('komoditas_id', $request->get('komoditas_id')); + $allowed = ['id', 'nama']; + + if (in_array($column, $allowed)) { + $tanamanList->orderBy($column, $dir); + } + } else { + $tanamanList->orderBy('nama', 'asc'); } - $tanamanList = $tanamanQuery->paginate($size); + $tanamanList = $tanamanList->paginate($size); - return response()->json($tanamanList); + return TanamanResource::collection($tanamanList); } /** @@ -67,35 +89,46 @@ public function create() public function store(Request $request): JsonResponse { Gate::authorize('petani'); - $user = Auth::user(); - $profile = $user->profile; + $profile = Auth::user()->profile; $validated = $request->validate([ 'nama' => ['required', 'string', 'max:255'], 'komoditas_id' => ['required', 'exists:master_komoditas,id'], - 'lahan_id' => ['required', 'exists:map_lahan,id'], - 'latitude' => ['nullable', 'numeric'], - 'longitude' => ['nullable', 'numeric'], + 'lahan_id' => [ + 'required', + Rule::exists('map_lahan', 'id')->where(function ($query) use ($profile) { + $query->where('profile_id', $profile->id) + ->whereNull('deleted_at'); + }), + ], + 'latitude' => ['nullable', 'numeric', 'between:-90,90', 'required_with:longitude'], + 'longitude' => ['nullable', 'numeric', 'between:-180,180', 'required_with:latitude'], + 'kondisi_tanaman' => ['nullable', 'string', new Enum(KondisiTanaman::class)], ]); $tanaman = Tanaman::create([ - 'nama' => $validated['nama'], - 'komoditas_id' => $validated['komoditas_id'], - 'lahan_id' => $validated['lahan_id'], - 'latitude' => $validated['latitude'] ?? null, - 'longitude' => $validated['longitude'] ?? null, + ...$validated, 'profile_id' => $profile->id, ]); - return response()->json($tanaman); + return (new TanamanResource($tanaman)) + ->response() + ->setStatusCode(201); } /** * Display the specified resource. */ - public function show(string $id) + public function show(string $id): JsonResponse { - return response()->json(Tanaman::findOrFail($id)); + Gate::authorize('petani'); + + $tanaman = Tanaman::findOrFail($id); + if ($tanaman->profile_id !== Auth::user()->profile->id) { + return response()->json(['message' => 'Unauthorized'], 403); + } + + return (new TanamanResource($tanaman))->response(); } /** @@ -113,39 +146,45 @@ public function update(Request $request, string $id): JsonResponse { Gate::authorize('petani'); $tanaman = Tanaman::findOrFail($id); - $user = Auth::user(); - $profile = $user->profile; - - if ($tanaman->profile_id !== $profile->id) { + if ($tanaman->profile_id !== Auth::user()->profile->id) { return response()->json(['message' => 'Unauthorized'], 403); - } + } + + $profile = Auth::user()->profile; $validated = $request->validate([ 'nama' => ['required', 'string', 'max:255'], 'komoditas_id' => ['required', 'exists:master_komoditas,id'], - 'lahan_id' => ['required', 'exists:map_lahan,id'], - 'latitude' => ['nullable', 'numeric'], - 'longitude' => ['nullable', 'numeric'], - 'kondisi_tanaman' => ['nullable', 'string', 'in:sehat,sakit,mati'], + 'lahan_id' => [ + 'required', + Rule::exists('map_lahan', 'id')->where(function ($query) use ($profile) { + $query->where('profile_id', $profile->id) + ->whereNull('deleted_at'); + }), + ], + 'latitude' => ['nullable', 'numeric', 'between:-90,90', 'required_with:longitude'], + 'longitude' => ['nullable', 'numeric', 'between:-180,180', 'required_with:latitude'], + 'kondisi_tanaman' => ['nullable', 'string', new Enum(KondisiTanaman::class)], ]); - $tanaman->update([ - 'nama' => $validated['nama'], - 'komoditas_id' => $validated['komoditas_id'] ?? $tanaman->komoditas_id, - 'lahan_id' => $validated['lahan_id'] ?? $tanaman->lahan_id, - 'latitude' => $validated['latitude'] ?? $tanaman->latitude, - 'longitude' => $validated['longitude'] ?? $tanaman->longitude, - 'kondisi_tanaman' => $validated['kondisi_tanaman'] ?? $tanaman->kondisi_tanaman, - ]); + $tanaman->update($validated); - return response()->json($tanaman); + return (new TanamanResource($tanaman))->response(); } /** * Remove the specified resource from storage. */ - public function destroy(string $id) + public function destroy(string $id): JsonResponse { - // + Gate::authorize('petani'); + $tanaman = Tanaman::findOrFail($id); + if ($tanaman->profile_id !== Auth::user()->profile->id) { + return response()->json(['message' => 'Unauthorized'], 403); + } + + $tanaman->delete(); + + return response()->json(null, 204); } } diff --git a/app/Http/Resources/Pertanian/KomoditasResource.php b/app/Http/Resources/Pertanian/KomoditasResource.php new file mode 100644 index 0000000..9a41806 --- /dev/null +++ b/app/Http/Resources/Pertanian/KomoditasResource.php @@ -0,0 +1,22 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + 'nama' => $this->nama + ]; + } +} diff --git a/app/Http/Resources/Pertanian/LahanResource.php b/app/Http/Resources/Pertanian/LahanResource.php new file mode 100644 index 0000000..16eb72a --- /dev/null +++ b/app/Http/Resources/Pertanian/LahanResource.php @@ -0,0 +1,30 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + 'nama' => $this->nama, + 'status_kepemilikan' => $this->status_kepemilikan, + 'profile_id' => $this->profile_id, + 'desa_kelurahan' => $this->desaKelurahan ? new DesaKelurahanResource($this->desaKelurahan) : null, + 'path' => $this->path, + 'luas_lahan' => $this->luas_lahan, + 'keluarga_pengelola_id' => $this->keluarga_pengelola_id, + 'adat_pemilik_id' => $this->adat_pemilik_id, + ]; + } +} diff --git a/app/Http/Resources/Pertanian/TanamanResource.php b/app/Http/Resources/Pertanian/TanamanResource.php new file mode 100644 index 0000000..d1234fd --- /dev/null +++ b/app/Http/Resources/Pertanian/TanamanResource.php @@ -0,0 +1,29 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + 'nama' => $this->nama, + 'komoditas' => $this->komoditas ? new KomoditasResource($this->komoditas) : null, + 'profile_id' => $this->profile_id, + 'lahan' => $this->lahan ? new LahanResource($this->lahan) : null, + 'latitude' => $this->latitude, + 'longitude' => $this->longitude, + 'kondisi_tanaman' => $this->kondisi_tanaman, + ]; + } +} diff --git a/app/Models/Pertanian/Lahan.php b/app/Models/Pertanian/Lahan.php index 85db521..9cc6d78 100644 --- a/app/Models/Pertanian/Lahan.php +++ b/app/Models/Pertanian/Lahan.php @@ -7,6 +7,9 @@ use App\Models\Wilayah\DesaKelurahan; use App\Models\Pertanian\Tanaman; use App\Models\Profile; +use App\Enums\StatusLahan; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; class Lahan extends Model { @@ -28,17 +31,22 @@ class Lahan extends Model 'deleted_by', ]; - public function profile() + protected $casts = [ + 'status_kepemilikan' => StatusLahan::class, + 'path' => 'array', + ]; + + public function profile(): BelongsTo { return $this->belongsTo(Profile::class, 'profile_id'); } - public function desakelurahan() + public function desaKelurahan(): BelongsTo { return $this->belongsTo(DesaKelurahan::class, 'desa_kelurahan_id'); } - public function tanaman() + public function tanaman(): HasMany { return $this->hasMany(Tanaman::class, 'lahan_id'); }