MIF_E31230549/lib/bidan/crud_edukasi/tambah_edukasi_balita.dart

316 lines
9.7 KiB
Dart

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<TambahEdukasiBalitaPage> createState() =>
_TambahEdukasiBalitaPageState();
}
class _TambahEdukasiBalitaPageState extends State<TambahEdukasiBalitaPage> {
final _formKey = GlobalKey<FormState>();
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<void> _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<void> _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,
),
),
),
);
}
}