validate([ 'image' => 'required|image|mimes:jpg,jpeg,png|max:2048' ], [ 'image.required' => 'Gambar insang ikan wajib diunggah.', 'image.image' => 'File harus berupa gambar.', 'image.mimes' => 'Format yang diizinkan hanya JPG, JPEG, atau PNG.', 'image.max' => 'Ukuran gambar maksimal 2MB.' ]); // ====================================== // HAPUS FOTO LAMA — hanya untuk guest // ====================================== if (!Auth::check()) { $fotoGuest = Image::whereNull('user_id')->get(); foreach ($fotoGuest as $fotoLama) { \Storage::delete('public/' . $fotoLama->image_path); $fotoLama->delete(); } } // Simpan gambar baru $imageFile = $request->file('image'); $path = $imageFile->store('images', 'public'); // ============================================= // Simpan user_id kalau login, null kalau guest // ============================================= $image = Image::create([ 'user_id' => Auth::id(), // otomatis null kalau belum login 'image_path' => $path ]); $image_url = asset('storage/' . $path); // ========================================== // KONEKSI KE API PYTHON (FLASK) // ========================================== try { $apiUrl = 'http://127.0.0.1:5000/predict'; $response = Http::timeout(60)->attach( 'image', file_get_contents($imageFile->getRealPath()), $imageFile->getClientOriginalName() )->post($apiUrl); if ($response->successful()) { $result = $response->json(); // BUKAN INSANG if ($result['status'] == 'bukan_insang') { return redirect()->back()->with([ 'error_insang' => $result['pesan'], 'image_url' => $image_url ]); } // HASIL NORMAL if ($result['status'] == 'ok') { Classification::create([ 'image_id' => $image->id, 'kelas' => $result['prediksi_2kelas'], 'prob_fresh' => $result['prob_fresh'], 'tingkat_kesegaran' => $result['tingkat_kesegaran'] ]); return redirect()->back()->with([ 'success' => 'Gambar berhasil dianalisis oleh model AI!', 'kelas' => $result['prediksi_2kelas'], 'prob_fresh' => $result['prob_fresh'], 'tingkat_kesegaran' => $result['tingkat_kesegaran'], 'image_url' => $image_url, 'cropped_image' => $result['cropped_image'] ?? null ]); } } else { return redirect()->back()->withErrors([ 'image' => 'Terjadi kesalahan pada API: ' . $response->body() ]); } } catch (\Exception $e) { return redirect()->back()->withErrors([ 'image' => 'Gagal terhubung ke server AI (Flask).' ]); } } public function history() { $histories = Image::where('user_id', Auth::id()) ->with('classification') ->latest() ->paginate(10); return view('history.history', compact('histories')); } }