MIF_E31230549/lib/bidan/crud_edukasi/edit_edukasi_ibu_hamil.dart

314 lines
10 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 EditEdukasiBumilPage extends StatefulWidget {
final Map data;
const EditEdukasiBumilPage({super.key, required this.data});
@override
State<EditEdukasiBumilPage> createState() => _EditEdukasiBumilPageState();
}
class _EditEdukasiBumilPageState extends State<EditEdukasiBumilPage> {
final _formKey = GlobalKey<FormState>();
late TextEditingController _judulController;
late TextEditingController _deskripsiController;
File? selectedImage;
Uint8List? webImage;
bool isSubmitting = false;
final picker = ImagePicker();
// Jika nanti sudah migrasi ke hosting, ganti localhost menjadi ta.myhost.id
final String urlEdit =
"http://ta.myhost.id/E31230549/mposyandu_api/edukasi_ibu_hamil/edit_edukasi_ibu_hamil.php";
@override
void initState() {
super.initState();
_judulController = TextEditingController(text: widget.data['judul']);
// Mengambil deskripsi dan membersihkannya dari format JSON Delta
String rawDeskripsi = widget.data['deskripsi'] ?? "";
_deskripsiController = TextEditingController(
text: _convertJsonToPlainText(rawDeskripsi),
);
}
// Fungsi pembantu untuk mengonversi format JSON Quill ke teks biasa
String _convertJsonToPlainText(String input) {
try {
if (input.trim().startsWith('[')) {
List<dynamic> jsonDelta = jsonDecode(input);
String plainText = "";
for (var node in jsonDelta) {
if (node['insert'] != null) {
plainText += node['insert'];
}
}
return plainText;
}
} catch (e) {
debugPrint("Info: Menggunakan teks asli karena bukan format JSON.");
}
return input;
}
@override
void dispose() {
_judulController.dispose();
_deskripsiController.dispose();
super.dispose();
}
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 _updateData() async {
if (!_formKey.currentState!.validate()) return;
setState(() => isSubmitting = true);
try {
var request = http.MultipartRequest("POST", Uri.parse(urlEdit));
request.fields["id"] = widget.data['id'].toString();
request.fields["judul"] = _judulController.text;
request.fields["deskripsi"] = _deskripsiController.text;
if (selectedImage != null) {
request.files.add(
await http.MultipartFile.fromPath("gambar", selectedImage!.path));
} else 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("Data berhasil diperbarui")),
);
Navigator.pop(context, true);
} else {
throw data["message"] ?? "Gagal memperbarui data";
}
} catch (e) {
if (!mounted) return;
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: Text("",
style: GoogleFonts.poppins(color: Colors.white, fontSize: 16)),
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(
color: Colors.white,
elevation: 3,
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(
"Edit Edukasi Ibu Hamil",
style: GoogleFonts.poppins(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 10),
const Divider(),
const SizedBox(height: 20),
_buildLabel("Gambar Edukasi"),
_buildImageSection(),
const SizedBox(height: 25),
_buildLabel("Judul Edukasi"),
_buildTitleField(),
const SizedBox(height: 25),
_buildLabel("Deskripsi"),
_buildDescriptionField(),
const SizedBox(height: 35),
_buildSubmitButton(),
],
),
),
),
),
),
),
),
);
}
Widget _buildDescriptionField() {
return TextFormField(
controller: _deskripsiController,
maxLines: 12,
keyboardType: TextInputType.multiline,
style: GoogleFonts.poppins(fontSize: 14),
decoration: InputDecoration(
hintText: "Tulis isi materi di sini...",
filled: true,
fillColor: Colors.grey[50],
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade400),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.blue),
),
contentPadding: const EdgeInsets.all(15),
),
validator: (value) =>
value == null || value.isEmpty ? "Wajib diisi" : null,
);
}
Widget _buildImageSection() {
return Center(
child: Column(
children: [
Container(
height: 200,
width: 350,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey.shade200),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: selectedImage != null || webImage != null
? (kIsWeb
? Image.memory(webImage!, fit: BoxFit.cover)
: Image.file(selectedImage!, fit: BoxFit.cover))
: (widget.data["gambar"] != null
? Image.network(
"http://ta.myhost.id/E31230549/mposyandu_api/upload/edukasi/${widget.data['gambar']}",
fit: BoxFit.cover,
errorBuilder: (c, e, s) => const Icon(
Icons.broken_image,
size: 50,
color: Colors.grey),
)
: const Icon(Icons.image, size: 50, color: Colors.grey)),
),
),
const SizedBox(height: 10),
TextButton.icon(
onPressed: pickImage,
icon: const Icon(Icons.camera_alt),
label: Text("Ganti Gambar", style: GoogleFonts.poppins())),
],
),
);
}
Widget _buildTitleField() {
return TextFormField(
controller: _judulController,
style: GoogleFonts.poppins(fontSize: 14),
decoration: InputDecoration(
hintText: "Masukkan Judul",
filled: true,
fillColor: Colors.grey[50],
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade400),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.blue),
),
contentPadding:
const EdgeInsets.symmetric(horizontal: 15, vertical: 12),
),
validator: (value) =>
value == null || value.isEmpty ? "Wajib diisi" : null,
);
}
Widget _buildSubmitButton() {
return Align(
alignment: Alignment.centerRight,
child: SizedBox(
width: 200,
height: 50,
child: ElevatedButton(
onPressed: isSubmitting ? null : _updateData,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
elevation: 2,
),
child: isSubmitting
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
color: Colors.white, strokeWidth: 2))
: Text(
"Simpan Perubahan",
style: GoogleFonts.poppins(fontWeight: FontWeight.bold),
),
),
),
);
}
Widget _buildLabel(String text) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Text(text,
style: GoogleFonts.poppins(
fontWeight: FontWeight.bold,
fontSize: 13,
color: Colors.black87)),
);
}
}