import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; class RiwayatDetailBalitaPage extends StatefulWidget { final Map balita; final String jenisImunisasi; const RiwayatDetailBalitaPage({ super.key, required this.balita, required this.jenisImunisasi, }); @override State createState() => _RiwayatDetailBalitaPageState(); } class _RiwayatDetailBalitaPageState extends State { List listRiwayat = []; String _query = ""; bool isLoading = true; int _currentPage = 0; final int _rowsPerPage = 5; @override void initState() { super.initState(); fetchDetailRiwayat(); } String formatTanggal(String tanggal) { if (tanggal.isEmpty || tanggal == "-") return "-"; try { final parts = tanggal.split("-"); if (parts.length != 3) return tanggal; final tahun = parts[0]; final bulan = int.parse(parts[1]); final hari = parts[2]; const namaBulan = [ "", "Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember" ]; return "$hari ${namaBulan[bulan]} $tahun"; } catch (e) { return tanggal; } } Future fetchDetailRiwayat() async { final String url = "http://ta.myhost.id/E31230549/mposyandu_api/imunisasi/get_riwayat_detail.php?id_balita=${widget.balita['id']}"; try { final response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { final data = jsonDecode(response.body); if (mounted) { setState(() { listRiwayat = data['data'] ?? []; isLoading = false; }); } } } catch (e) { debugPrint("ERROR FETCHING DETAIL: $e"); if (mounted) { setState(() => isLoading = false); } } } List get _filteredList { if (_query.isEmpty) return listRiwayat; return listRiwayat.where((item) { // Filter berdasarkan daftar imunisasi yang sudah digabung final nama = item['daftar_imunisasi']?.toString().toLowerCase() ?? ""; return nama.contains(_query.toLowerCase()); }).toList(); } List get _paginatedData { final start = _currentPage * _rowsPerPage; final end = start + _rowsPerPage; if (start >= _filteredList.length) return []; return _filteredList.sublist( start, end > _filteredList.length ? _filteredList.length : end, ); } @override Widget build(BuildContext context) { final totalPages = (_filteredList.length / _rowsPerPage).ceil() == 0 ? 1 : (_filteredList.length / _rowsPerPage).ceil(); return Scaffold( backgroundColor: const Color(0xFFF5F5F5), appBar: AppBar( backgroundColor: Colors.blue, elevation: 0, leading: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.white, size: 18), onPressed: () => Navigator.pop(context), ), ), body: isLoading ? const Center(child: CircularProgressIndicator()) : Column( children: [ Expanded( child: SingleChildScrollView( child: Column( children: [ _buildSearchHeader(), _paginatedData.isEmpty ? Padding( padding: const EdgeInsets.only(top: 50), child: Text( "Data tidak ditemukan", style: GoogleFonts.poppins(fontSize: 12), ), ) : ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: _paginatedData.length, itemBuilder: (context, index) => _buildHistoryCard(_paginatedData[index]), ), ], ), ), ), _buildPagination(totalPages), ], ), ); } Widget _buildSearchHeader() { return Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ Center( child: Text( "Riwayat Detail Balita", style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.bold), ), ), const SizedBox(height: 15), TextField( onChanged: (v) => setState(() { _query = v; _currentPage = 0; }), style: const TextStyle(fontSize: 12), decoration: InputDecoration( hintText: "Cari jenis imunisasi...", hintStyle: const TextStyle(fontSize: 12), prefixIcon: const Icon(Icons.search, size: 20), filled: true, fillColor: Colors.white, border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: BorderSide(color: Colors.grey[300]!), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: BorderSide(color: Colors.grey[300]!), ), contentPadding: const EdgeInsets.symmetric(vertical: 8), ), ), ], ), ); } Widget _buildHistoryCard(Map item) { return Container( margin: const EdgeInsets.only(bottom: 15), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 5), ) ], ), child: Column( children: [ Container( padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), width: double.infinity, decoration: const BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), ), ), child: Text( widget.balita['nama_balita'] ?? "Nama Balita", style: GoogleFonts.poppins( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 13, ), ), ), Padding( padding: const EdgeInsets.all(15), child: Column( children: [ // Menggunakan 'daftar_imunisasi' yang berisi string gabungan (HB0, BCG, dll) _buildInfoRow("Jenis Imunisasi", item['daftar_imunisasi']?.toString() ?? "-"), const SizedBox(height: 8), _buildInfoRow( "Tanggal Posyandu", formatTanggal( item['tanggal_pemberian']?.toString() ?? "-")), const SizedBox(height: 8), _buildInfoRow("Status", item['status']?.toString() ?? "-"), ], ), ) ], ), ); } Widget _buildInfoRow(String label, String value) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 130, child: Text( label, style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w500), ), ), Text(" : ", style: GoogleFonts.poppins(fontSize: 12)), Expanded( child: Text( value, style: GoogleFonts.poppins(fontSize: 12), ), ), ], ); } Widget _buildPagination(int totalPages) { return Container( width: double.infinity, color: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), decoration: BoxDecoration( border: Border(top: BorderSide(color: Colors.grey[200]!)), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("Halaman ${_currentPage + 1} dari $totalPages", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500)), Row( children: [ IconButton( icon: const Icon(Icons.chevron_left), onPressed: _currentPage == 0 ? null : () => setState(() => _currentPage--), ), IconButton( icon: const Icon(Icons.chevron_right), onPressed: _currentPage >= totalPages - 1 ? null : () => setState(() => _currentPage++), ), ], ), ], ), ); } }