import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:image_picker/image_picker.dart'; import 'dart:io'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:intl/intl.dart'; import 'package:image_cropper/image_cropper.dart'; import 'result_page.dart'; // Import ResultPage class SelectImagePage extends StatefulWidget { const SelectImagePage({super.key}); @override State createState() => _SelectImagePageState(); } class _SelectImagePageState extends State { File? _selectedImage; bool _isUploading = false; final String apiUrl = "http://172.20.10.10:5000/predict"; Future _pickImage() async { final pickedFile = await ImagePicker().pickImage(source: ImageSource.gallery); if (pickedFile != null) { File? croppedImage = await _cropImage(File(pickedFile.path)); if (croppedImage != null) { setState(() { _selectedImage = croppedImage; _isUploading = true; }); _uploadImage(croppedImage); } } else { print("❌ Gambar tidak dipilih."); } } Future _cropImage(File imageFile) async { try { final CroppedFile? croppedFile = await ImageCropper().cropImage( sourcePath: imageFile.path, compressFormat: ImageCompressFormat.jpg, compressQuality: 80, aspectRatioPresets: [ CropAspectRatioPreset.square, CropAspectRatioPreset.ratio3x2, CropAspectRatioPreset.original, CropAspectRatioPreset.ratio4x3, CropAspectRatioPreset.ratio16x9 ], uiSettings: [ AndroidUiSettings( toolbarTitle: 'Crop Gambar', toolbarColor: const Color(0xFF891A2D), toolbarWidgetColor: Colors.white, initAspectRatio: CropAspectRatioPreset.original, lockAspectRatio: false, ), IOSUiSettings(title: 'Crop Gambar'), ], ); return croppedFile != null ? File(croppedFile.path) : null; } catch (e) { print("❌ Error saat cropping gambar: $e"); return null; } } Future _uploadImage(File image) async { try { var request = http.MultipartRequest('POST', Uri.parse(apiUrl)); request.files.add(await http.MultipartFile.fromPath('file', image.path)); var response = await request.send(); print("📡 Status Code: ${response.statusCode}"); if (response.statusCode == 200) { var responseData = await response.stream.bytesToString(); var result = json.decode(responseData); print("✅ Response dari API: $responseData"); setState(() => _isUploading = false); // Sembunyikan loading setelah upload selesai // Navigasi ke ResultPage dengan hasil prediksi & gambar yang sudah di-crop Navigator.push( context, MaterialPageRoute( builder: (context) => ResultPage( image: image, // Kirim gambar ke ResultPage prediction: result['prediction'] ?? "-", date: DateFormat('dd MMM yyyy, HH:mm').format(DateTime.now()), ), ), ); } else { print("❌ Error Response: ${await response.stream.bytesToString()}"); setState(() => _isUploading = false); } } catch (e) { print("⚠️ Exception: $e"); setState(() => _isUploading = false); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, // Latar belakang putih appBar: AppBar( backgroundColor: const Color(0xFF891A2D), title: Text( "Pilih Gambar", style: GoogleFonts.poppins(color: Colors.white), ), centerTitle: true, iconTheme: const IconThemeData(color: Colors.white), ), body: SafeArea( child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ // Area Gambar dengan Efek Kartu Card( elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), ), child: AnimatedContainer( duration: const Duration(milliseconds: 300), width: double.infinity, height: 280, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), color: Colors.grey[200], ), child: _selectedImage != null ? ClipRRect( borderRadius: BorderRadius.circular(20), child: Image.file( _selectedImage!, width: double.infinity, height: 280, fit: BoxFit.cover, ), ) : const Center( child: Icon( Icons.image_outlined, size: 100, color: Colors.black26, ), ), ), ), const SizedBox(height: 20), // Tampilkan Loading dengan Animasi if (_isUploading) Column( children: [ const CircularProgressIndicator( color: const Color(0xFF891A2D), strokeWidth: 5, ), const SizedBox(height: 15), Text( "Mengunggah Gambar...", style: GoogleFonts.poppins( fontSize: 16, color: const Color.fromARGB(255, 0, 0, 0), fontWeight: FontWeight.w500, ), ), ], ), const SizedBox(height: 25), // Petunjuk Penggunaan dalam Kartu Card( elevation: 3, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15), ), color: Colors.grey[ 100], // Warna latar belakang seperti StrawberryInfoPage child: Padding( padding: const EdgeInsets.all(15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon( Icons.info_outline, color: Color(0xFF891A2D), // Warna merah tema size: 24, ), const SizedBox(width: 8), Text( "Petunjuk Penggunaan", style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.bold, color: const Color(0xFF891A2D), // Warna merah tema ), ), ], ), const SizedBox(height: 10), Text( "• Klik tombol 'Pilih dari Galeri' untuk memilih gambar.\n" "• Crop gambar pada bagian buah stroberi, hilangkan tangkainya, lalu tekan 'Simpan'.\n" "• Tunggu proses upload hingga selesai.\n" "• Hasil prediksi akan ditampilkan di halaman berikutnya.", textAlign: TextAlign.left, style: GoogleFonts.poppins( fontSize: 14, color: Colors.black87, height: 1.6, ), ), ], ), ), ), const SizedBox(height: 30), // Tombol Pilih Gambar dengan Animasi TweenAnimationBuilder( tween: Tween(begin: 1.0, end: 1.0), duration: const Duration(milliseconds: 200), builder: (context, scale, child) { return Transform.scale( scale: scale, child: child, ); }, child: ElevatedButton( onPressed: _pickImage, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF891A2D), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15), ), padding: const EdgeInsets.symmetric( vertical: 15, horizontal: 40), elevation: 5, ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon( Icons.photo_library, color: Colors.white, size: 24, ), const SizedBox(width: 10), Text( "Pilih dari Galeri", style: GoogleFonts.poppins( fontSize: 16, color: Colors.white, fontWeight: FontWeight.w600, ), ), ], ), ), ), ], ), ), ), ), ); } }