import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; class DataImunisasiBalitaPage extends StatefulWidget { final Map? balita; const DataImunisasiBalitaPage({super.key, this.balita}); @override State createState() => _DataImunisasiBalitaPageState(); } class _DataImunisasiBalitaPageState extends State { List riwayatData = []; String _searchQuery = ""; bool isLoading = true; int _currentPage = 0; final int _rowsPerPage = 5; final String urlRiwayat = "http://ta.myhost.id/E31230549/mposyandu_api/imunisasi/get_imunisasi_balita.php"; @override void initState() { super.initState(); fetchRiwayat(); } Future fetchRiwayat() async { try { final idBalita = widget.balita?['id']; final url = idBalita == null ? urlRiwayat : "$urlRiwayat?id_balita=$idBalita"; final response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { final data = jsonDecode(response.body); setState(() { riwayatData = data['data'] ?? []; isLoading = false; }); } } catch (e) { debugPrint("ERROR FETCH = $e"); setState(() => isLoading = false); } } // Fungsi Hitung Usia String hitungUsia(String? tanggalLahir) { if (tanggalLahir == null || tanggalLahir.isEmpty || tanggalLahir == "-") { return "Usia tidak diketahui"; } try { DateTime lahir = DateTime.parse(tanggalLahir); DateTime sekarang = DateTime.now(); int tahun = sekarang.year - lahir.year; int bulan = sekarang.month - lahir.month; if (bulan < 0) { tahun--; bulan += 12; } return "$tahun Tahun $bulan Bulan"; } catch (e) { return "Format tanggal salah"; } } List get _filteredData { if (_searchQuery.isEmpty) return riwayatData; return riwayatData.where((item) { final namaBalita = item['nama'].toString().toLowerCase(); final query = _searchQuery.toLowerCase(); return namaBalita.contains(query); }).toList(); } List get _paginatedData { final start = _currentPage * _rowsPerPage; final end = start + _rowsPerPage; if (start >= _filteredData.length) return []; return _filteredData.sublist( start, end > _filteredData.length ? _filteredData.length : end, ); } 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; } } @override Widget build(BuildContext context) { final totalPages = (_filteredData.length / _rowsPerPage).ceil() == 0 ? 1 : (_filteredData.length / _rowsPerPage).ceil(); return Scaffold( backgroundColor: const Color(0xFFF5F5F5), appBar: AppBar( title: Text("", style: GoogleFonts.poppins(color: Colors.white, fontSize: 16)), backgroundColor: Colors.blue, elevation: 0, iconTheme: const IconThemeData(color: Colors.white), ), body: isLoading ? const Center(child: CircularProgressIndicator()) : Column( children: [ Expanded( child: SingleChildScrollView( child: Column( children: [ _header(), _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) => _card(_paginatedData[index]), ), ], ), ), ), 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++), ), ], ), ], ), ), ], ), ); } Widget _header() { return Padding( padding: const EdgeInsets.all(16), child: Column( children: [ Text( "Data Imunisasi Balita", style: GoogleFonts.poppins(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 15), TextField( onChanged: (value) => setState(() { _searchQuery = value; _currentPage = 0; }), style: const TextStyle(fontSize: 12), decoration: InputDecoration( hintText: "Cari nama balita...", 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 _card(Map item) { String alamatLengkap = "Dusun ${item['nama_dusun'] ?? '-'}, Desa ${item['nama_desa'] ?? '-'}, ${item['alamat_detail'] ?? '-'}"; return Container( margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10) ], ), child: Column( children: [ Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), decoration: const BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item['nama'] ?? "Nama Balita", style: GoogleFonts.poppins( fontSize: 13, color: Colors.white, fontWeight: FontWeight.bold, ), ), // USIA DI BAWAH NAMA Text( "Usia: ${hitungUsia(item['tanggal_lahir'])}", style: GoogleFonts.poppins( fontSize: 11, color: Colors.white, fontWeight: FontWeight.w500, ), ), const SizedBox(height: 4), // NAMA ORANG TUA (WARNA PUTIH) Text( "Nama Orang Tua : ${item['nama_ibu'] ?? '-'}(${item['nama_suami'] ?? '-'})", style: GoogleFonts.poppins( fontSize: 11, color: Colors.white, ), ), // ALAMAT (WARNA PUTIH) Text( "Alamat : $alamatLengkap", style: GoogleFonts.poppins( fontSize: 11, color: Colors.white, fontStyle: FontStyle.normal, ), ), ], ), ), Padding( padding: const EdgeInsets.all(15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // POSISI TANGGAL DI ATAS IMUNISASI detail("Tanggal Posyandu", formatTanggal(item['tanggal_terakhir'] ?? "-")), const SizedBox(height: 8), detail("Jenis Imunisasi", item['daftar_imunisasi'] ?? "-"), const SizedBox(height: 8), detail("Status", item['status'] ?? "-"), // BUTTON RIWAYAT SUDAH DIHAPUS ], ), ) ], ), ); } Widget detail(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), ), ) ], ); } }