import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import 'package:image_picker/image_picker.dart'; class TambahEdukasiBalitaPage extends StatefulWidget { const TambahEdukasiBalitaPage({super.key}); @override State createState() => _TambahEdukasiBalitaPageState(); } class _TambahEdukasiBalitaPageState extends State { final _formKey = GlobalKey(); final TextEditingController _judulController = TextEditingController(); // Menggunakan TextEditingController biasa untuk deskripsi agar fungsi ENTER lancar final TextEditingController _deskripsiController = TextEditingController(); File? _imageFile; Uint8List? _webImage; final ImagePicker _picker = ImagePicker(); bool isSubmitting = false; final String urlTambah = "http://ta.myhost.id/E31230549/mposyandu_api/edukasi_balita/tambah_edukasi_balita.php"; Future _pickImage() async { try { final XFile? pickedFile = await _picker.pickImage( source: ImageSource.gallery, imageQuality: 80, ); if (pickedFile == null) return; if (kIsWeb) { final bytes = await pickedFile.readAsBytes(); setState(() { _webImage = bytes; _imageFile = null; }); } else { setState(() { _imageFile = File(pickedFile.path); _webImage = null; }); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Gagal memilih gambar: $e")), ); } } Future _simpanData() async { if (!_formKey.currentState!.validate()) return; if (_imageFile == null && _webImage == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("Silakan pilih gambar terlebih dahulu")), ); return; } setState(() => isSubmitting = true); try { var request = http.MultipartRequest('POST', Uri.parse(urlTambah)); request.fields['judul'] = _judulController.text; // Kirim teks deskripsi apa adanya (mendukung pindah baris/newline) request.fields['deskripsi'] = _deskripsiController.text; if (kIsWeb) { request.files.add( http.MultipartFile.fromBytes( 'gambar', _webImage!, filename: "upload_web.jpg", ), ); } else { request.files.add( await http.MultipartFile.fromPath( 'gambar', _imageFile!.path, ), ); } var streamedResponse = await request.send(); var response = await http.Response.fromStream(streamedResponse); final data = jsonDecode(response.body); if (data['status'] == 'success') { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("Data berhasil disimpan")), ); Navigator.pop(context); } else { throw data['message']; } } catch (e) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Terjadi kesalahan: $e")), ); } finally { if (mounted) setState(() => isSubmitting = false); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF5F5F5), appBar: AppBar( title: const Text(""), backgroundColor: Colors.blue, elevation: 0, iconTheme: const IconThemeData(color: Colors.white), centerTitle: true, ), body: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Center( child: Container( constraints: const BoxConstraints(maxWidth: 900), child: Card( elevation: 3, color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), child: Padding( padding: const EdgeInsets.all(25), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Text( "Tambah Edukasi Balita", style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black87, ), ), ), const SizedBox(height: 10), const Divider(), const SizedBox(height: 20), _buildLabel("Gambar Edukasi"), const SizedBox(height: 8), InkWell( onTap: _pickImage, borderRadius: BorderRadius.circular(10), child: Container( width: double.infinity, height: 200, decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(10), border: Border.all(color: Colors.grey.shade300), ), child: _displayImage(), ), ), const SizedBox(height: 25), _buildLabel("Judul Edukasi"), _buildTitleField(), const SizedBox(height: 25), _buildLabel("Deskripsi"), // FIELD DESKRIPSI DENGAN FUNGSI ENTER (MULTILINE) _buildDescriptionField(), const SizedBox(height: 35), _buildSubmitButton(), ], ), ), ), ), ), ), ), ); } Widget _buildDescriptionField() { return TextFormField( controller: _deskripsiController, maxLines: 10, // Memberikan ruang untuk banyak baris keyboardType: TextInputType.multiline, // Mengaktifkan tombol ENTER di keyboard style: GoogleFonts.poppins(fontSize: 14), decoration: InputDecoration( hintText: "Tulis isi edukasi di sini...", hintStyle: GoogleFonts.poppins(color: Colors.grey, fontSize: 13), filled: true, fillColor: Colors.white, contentPadding: const EdgeInsets.all(15), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: BorderSide(color: Colors.grey.shade300), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: Colors.blue, width: 1.5), ), ), validator: (value) => value == null || value.isEmpty ? "Wajib diisi" : null, ); } Widget _displayImage() { if (_webImage != null || _imageFile != null) { return ClipRRect( borderRadius: BorderRadius.circular(10), child: kIsWeb ? Image.memory(_webImage!, fit: BoxFit.cover) : Image.file(_imageFile!, fit: BoxFit.cover), ); } return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.add_a_photo, color: Colors.blue, size: 40), const SizedBox(height: 8), Text( "Klik untuk pilih gambar", style: GoogleFonts.poppins(fontSize: 12, color: Colors.grey), ), ], ); } Widget _buildLabel(String label) { return Padding( padding: const EdgeInsets.only(bottom: 8), child: Text( label, style: GoogleFonts.poppins( fontSize: 13, fontWeight: FontWeight.bold, color: Colors.black87, ), ), ); } Widget _buildTitleField() { return TextFormField( controller: _judulController, style: GoogleFonts.poppins(fontSize: 14), decoration: InputDecoration( hintText: "Contoh: Pentingnya MPASI", hintStyle: GoogleFonts.poppins(color: Colors.grey, fontSize: 13), filled: true, fillColor: Colors.white, contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: BorderSide(color: Colors.grey.shade300), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: Colors.blue, width: 1.5), ), ), validator: (value) => value == null || value.isEmpty ? "Wajib diisi" : null, ); } Widget _buildSubmitButton() { return SizedBox( width: double.infinity, height: 50, child: ElevatedButton( onPressed: isSubmitting ? null : _simpanData, style: ElevatedButton.styleFrom( backgroundColor: Colors.blue, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), ), child: isSubmitting ? const CircularProgressIndicator(color: Colors.white) : Text( "Simpan Edukasi", style: GoogleFonts.poppins( fontWeight: FontWeight.bold, color: Colors.white, ), ), ), ); } }