import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:flutter_quill/flutter_quill.dart' as quill; // Pastikan package ini ada di pubspec.yaml import '../../layout/main_layout.dart'; import '../ibu_drawer.dart'; import '../dashboard_ibu.dart'; class EdukasiBalitaPage extends StatefulWidget { const EdukasiBalitaPage({super.key}); @override State createState() => _EdukasiBalitaPageState(); } class _EdukasiBalitaPageState extends State { List _listEdukasi = []; bool _isLoading = true; // Base URL Gambar disesuaikan dengan folder edukasi final String baseImageUrl = "http://ta.myhost.id/E31230549/mposyandu_api/upload/edukasi/"; @override void initState() { super.initState(); _fetchData(); } Future _fetchData() async { try { final response = await http.get( Uri.parse( "http://ta.myhost.id/E31230549/mposyandu_api/edukasi_balita/get_edukasi_balita.php", ), ); if (response.statusCode == 200) { final data = jsonDecode(response.body); if (data['success'] == true) { setState(() { _listEdukasi = data['data']; _isLoading = false; }); } else { setState(() => _isLoading = false); } } else { setState(() => _isLoading = false); } } catch (e) { setState(() => _isLoading = false); debugPrint("Error fetching data: $e"); } } // Fungsi untuk membersihkan JSON Quill menjadi teks paragraf biasa String _parseDescription(String? description) { String cleanText = description ?? ""; if (cleanText.startsWith('[') && cleanText.endsWith(']')) { try { final List json = jsonDecode(cleanText); final doc = quill.Document.fromJson(json); return doc.toPlainText().trim(); } catch (e) { return cleanText; } } return cleanText; } @override Widget build(BuildContext context) { return PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) async { if (didPop) return; Navigator.pushAndRemoveUntil( context, MaterialPageRoute( builder: (_) => const DashboardIbuPage(), ), (route) => false, ); }, child: MainLayout( title: "", drawer: const IbuDrawer(), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), child: Column( children: [ /// ===== JUDUL ===== Text( "Edukasi Balita", style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.w600, color: const Color.fromARGB(255, 24, 25, 26), ), ), const SizedBox(height: 16), Expanded( child: _isLoading ? const Center(child: CircularProgressIndicator()) : _listEdukasi.isEmpty ? const Center( child: Text("Belum ada data edukasi balita."), ) : RefreshIndicator( onRefresh: _fetchData, child: ListView.builder( itemCount: _listEdukasi.length, itemBuilder: (context, index) { final item = _listEdukasi[index]; // Gabungkan Base URL dengan nama file gambar String fullImageUrl = ""; if (item['gambar'] != null && item['gambar'].toString().isNotEmpty) { fullImageUrl = "$baseImageUrl${item['gambar']}"; } return _EdukasiCard( title: item['judul'] ?? '', content: _parseDescription(item['deskripsi']), ageRange: "Edukasi untuk balita umur ${item['umur_min']} - ${item['umur_max']} bulan", imageUrl: fullImageUrl, icon: Icons.menu_book_rounded, ); }, ), ), ), ], ), ), ), ); } } /// ================= CARD EDUKASI ================= class _EdukasiCard extends StatelessWidget { final String title; final String content; final String ageRange; final String imageUrl; final IconData icon; const _EdukasiCard({ required this.title, required this.content, required this.ageRange, required this.imageUrl, required this.icon, }); @override Widget build(BuildContext context) { return Container( margin: const EdgeInsets.only(bottom: 20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(14), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ /// ===== GAMBAR EDUKASI ===== if (imageUrl.isNotEmpty) ClipRRect( borderRadius: const BorderRadius.vertical(top: Radius.circular(14)), child: Image.network( imageUrl, width: double.infinity, height: 200, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Container( width: double.infinity, height: 150, color: Colors.grey[200], child: const Icon(Icons.broken_image, color: Colors.grey, size: 50), ); }, ), ), Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ /// ===== HEADER ===== Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: const Color(0xFFE8F1FF), borderRadius: BorderRadius.circular(8), ), child: Icon( icon, color: Colors.blueAccent, size: 20, ), ), const SizedBox(width: 12), Expanded( child: Text( title, style: GoogleFonts.poppins( fontWeight: FontWeight.bold, fontSize: 15, color: Colors.black87, ), ), ), ], ), const SizedBox(height: 12), /// ===== UMUR ===== Text( ageRange, style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, color: Colors.blueAccent, ), ), const SizedBox(height: 8), /// ===== DESKRIPSI (Rapi & Justify) ===== Text( content, textAlign: TextAlign.justify, style: GoogleFonts.poppins( fontSize: 13, height: 1.6, color: Colors.black54, ), ), ], ), ), ], ), ); } }