MIF_E31230549/lib/bidan/crud_edukasi/tambah_edukasi_ibu_hamil.dart

268 lines
8.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 TambahEdukasiBumilPage extends StatefulWidget {
const TambahEdukasiBumilPage({super.key});
@override
State<TambahEdukasiBumilPage> createState() => _TambahEdukasiBumilPageState();
}
class _TambahEdukasiBumilPageState extends State<TambahEdukasiBumilPage> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _judulController = TextEditingController();
// Menggunakan TextEditingController biasa untuk deskripsi
final TextEditingController _deskripsiController = TextEditingController();
bool isSubmitting = false;
File? selectedImage;
Uint8List? webImage;
final picker = ImagePicker();
final String urlTambah =
"http://ta.myhost.id/E31230549/mposyandu_api/edukasi_ibu_hamil/tambah_edukasi_ibu_hamil.php";
Future pickImage() async {
final picked = await picker.pickImage(
source: ImageSource.gallery,
imageQuality: 80,
);
if (picked == null) return;
if (kIsWeb) {
webImage = await picked.readAsBytes();
} else {
selectedImage = File(picked.path);
}
setState(() {});
}
Future _simpanData() async {
if (!_formKey.currentState!.validate()) return;
if (selectedImage == 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;
// Mengirim deskripsi sebagai teks biasa (mendukung enter/newline)
request.fields["deskripsi"] = _deskripsiController.text;
if (selectedImage != null) {
request.files.add(
await http.MultipartFile.fromPath("gambar", selectedImage!.path));
}
if (webImage != null) {
request.files.add(http.MultipartFile.fromBytes("gambar", webImage!,
filename: "upload.jpg"));
}
var response = await request.send();
var res = await http.Response.fromStream(response);
var data = jsonDecode(res.body);
if (data["status"] == "success") {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Edukasi berhasil ditambahkan")),
);
Navigator.pop(context);
}
} catch (e) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Error: $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,
centerTitle: true,
iconTheme: const IconThemeData(color: Colors.white),
),
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 Ibu Hamil",
style: GoogleFonts.poppins(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 10),
const Divider(),
const SizedBox(height: 20),
_buildImageSection(),
const SizedBox(height: 30),
_buildLabel("Judul Edukasi"),
_buildTextField(
_judulController, "Contoh: Perawatan ibu hamil", 1),
const SizedBox(height: 25),
_buildLabel("Deskripsi (Gunakan Enter untuk baris baru)"),
// Field deskripsi yang mendukung ENTER
_buildTextField(_deskripsiController,
"Tulis isi edukasi di sini...", 10),
const SizedBox(height: 35),
_buildSubmitButton(),
],
),
),
),
),
),
),
),
);
}
// Widget TextField Universal (bisa satu baris atau banyak baris)
Widget _buildTextField(
TextEditingController controller, String hint, int maxLines) {
return TextFormField(
controller: controller,
maxLines: maxLines, // Jika > 1, maka fungsi ENTER aktif secara otomatis
keyboardType: maxLines > 1 ? TextInputType.multiline : TextInputType.text,
style: GoogleFonts.poppins(fontSize: 14),
decoration: InputDecoration(
hintText: hint,
filled: true,
fillColor: Colors.white,
contentPadding:
const EdgeInsets.symmetric(horizontal: 15, vertical: 12),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
),
validator: (value) =>
value == null || value.isEmpty ? "Wajib diisi" : null,
);
}
// ... (Widget _buildImageSection, _buildSubmitButton, _buildLabel tetap sama)
// [Kode _buildImageSection dll disingkat karena sama dengan aslinya]
Widget _buildImageSection() {
return Center(
child: Column(
children: [
_buildLabel("Gambar Edukasi"),
InkWell(
onTap: pickImage,
child: Container(
height: 200,
width: 350,
decoration: BoxDecoration(
color: Colors.grey[50],
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey.shade300),
),
child: selectedImage != null || webImage != null
? ClipRRect(
borderRadius: BorderRadius.circular(10),
child: kIsWeb
? Image.memory(webImage!, fit: BoxFit.cover)
: Image.file(selectedImage!, fit: BoxFit.cover),
)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.add_a_photo,
size: 40, color: Colors.blue),
const SizedBox(height: 8),
Text(
"Klik untuk pilih gambar",
style: GoogleFonts.poppins(
fontSize: 12, color: Colors.grey),
),
],
),
),
),
],
),
);
}
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,
),
),
),
);
}
Widget _buildLabel(String text) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Text(
text,
style: GoogleFonts.poppins(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
);
}
}