- Hasil Klasifikasi Tomat -
-- {{ $description }} -
-From 70198dde563cf1037486cf8cc72c207a6cc807ea Mon Sep 17 00:00:00 2001 From: ramzdhani11 <158116439+ramzdhani11@users.noreply.github.com> Date: Wed, 15 Apr 2026 01:18:54 +0700 Subject: [PATCH] update fitur klasifikasi --- app/Http/Controllers/TomatController.php | 144 +++++++++++ composer.json | 3 +- resources/views/landing_page/result.blade.php | 125 --------- resources/views/landing_page/upload.blade.php | 243 ------------------ .../tomat/classification_result.blade.php | 136 ++++++++++ resources/views/tomat/upload.blade.php | 236 +++++++++++++++++ resources/views/welcome.blade.php | 4 +- routes/## GitHub Copilot Chat.md | 97 +++++++ routes/web.php | 33 ++- 9 files changed, 645 insertions(+), 376 deletions(-) create mode 100644 app/Http/Controllers/TomatController.php delete mode 100644 resources/views/landing_page/result.blade.php delete mode 100644 resources/views/landing_page/upload.blade.php create mode 100644 resources/views/tomat/classification_result.blade.php create mode 100644 resources/views/tomat/upload.blade.php create mode 100644 routes/## GitHub Copilot Chat.md diff --git a/app/Http/Controllers/TomatController.php b/app/Http/Controllers/TomatController.php new file mode 100644 index 0000000..e1cb3d2 --- /dev/null +++ b/app/Http/Controllers/TomatController.php @@ -0,0 +1,144 @@ +validate([ + 'image' => 'required|image|mimes:jpeg,png,jpg,gif|max:16384', + ]); + + try { + $uploadedFile = $request->file('image'); + + // Kirim file langsung ke Flask tanpa resize ulang di sini + // Flask sudah handle resize 256x256 sendiri + $response = Http::timeout(30) + ->attach( + 'image', + file_get_contents($uploadedFile->getRealPath()), + $uploadedFile->getClientOriginalName() + ) + ->post($this->apiUrl); + + if ($response->failed()) { + return back()->with('error', 'Gagal menghubungi API klasifikasi. Status: ' . $response->status()); + } + + $result = $response->json(); + + if (!isset($result['success']) || !$result['success']) { + $errorMsg = $result['message'] ?? 'Prediksi gagal'; + return back()->with('error', 'Error dari API: ' . $errorMsg); + } + + // Simpan hasil ke session + session([ + 'prediction_result' => $result, + 'processed_at' => now(), + 'original_size' => $uploadedFile->getSize(), + ]); + + return redirect()->route('tomat.result'); + + } catch (\Illuminate\Http\Client\ConnectionException $e) { + return back()->with('error', 'Tidak dapat terhubung ke API Flask. Pastikan server Python sudah berjalan (python app.py).'); + } catch (\Exception $e) { + return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage()); + } + } + + /** + * Show prediction result + */ + public function getResult() + { + $result = session('prediction_result'); + $processedAt = session('processed_at'); + + if (!$result) { + return redirect()->route('tomat.upload') + ->with('error', 'Tidak ada hasil prediksi. Silakan upload gambar terlebih dahulu.'); + } + + // ✅ FIX: nama view disesuaikan dengan file yang ada + return view('tomat.classification_result', compact('result', 'processedAt')); + } + + /** + * Check API service status + * Timeout 3 detik sudah cukup untuk health check lokal + */ + public function checkService() + { + try { + $response = Http::timeout(3)->get('http://127.0.0.1:5000/health'); + + if ($response->successful()) { + $health = $response->json(); + return response()->json([ + 'success' => true, + 'status' => 'online', + 'service' => $health['service'] ?? 'Tomat Classification API', + 'model_loaded' => $health['model_loaded'] ?? false + ]); + } + + return response()->json([ + 'success' => false, + 'status' => 'offline', + 'message' => 'API Flask tidak tersedia' + ], 503); + + } catch (\Exception $e) { + return response()->json([ + 'success' => false, + 'status' => 'error', + 'message' => 'Tidak dapat terhubung ke API Flask: ' . $e->getMessage() + ], 503); + } + } + + /** + * Get model info dari Flask API + */ + public function getModelInfo() + { + try { + $response = Http::timeout(5)->get('http://127.0.0.1:5000/info'); + + if ($response->successful()) { + return response()->json($response->json()); + } + + return response()->json([ + 'success' => false, + 'message' => 'Gagal mengambil info model' + ], 503); + + } catch (\Exception $e) { + return response()->json([ + 'success' => false, + 'message' => $e->getMessage() + ], 503); + } + } +} \ No newline at end of file diff --git a/composer.json b/composer.json index 44c6054..99639df 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,8 @@ "require": { "php": "^8.2", "laravel/framework": "^12.0", - "laravel/tinker": "^2.10.1" + "laravel/tinker": "^2.10.1", + "intervention/image": "^2.7" }, "require-dev": { "fakerphp/faker": "^1.23", diff --git a/resources/views/landing_page/result.blade.php b/resources/views/landing_page/result.blade.php deleted file mode 100644 index eb85a55..0000000 --- a/resources/views/landing_page/result.blade.php +++ /dev/null @@ -1,125 +0,0 @@ - - -
- - -- {{ $description }} -
-- Seret dan lepas gambar tomat Anda atau klik untuk memilih file. -
-{{ session('error') }}
+Sistem Klasifikasi Tingkat Kematangan Tomat menggunakan Machine Learning
+Sedang memproses gambar...
+Menggunakan Random Forest untuk klasifikasi akurat
+Ekstraksi fitur RGB 8x8x8 untuk analisis warna
+Proses klasifikasi cepat dan hasil instan
+