MIF_E31230549/lib/bidan/crud_imunisasi/riwayat_detail_imunisasi_ba...

305 lines
9.3 KiB
Dart

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<String, dynamic> balita;
final String jenisImunisasi;
const RiwayatDetailBalitaPage({
super.key,
required this.balita,
required this.jenisImunisasi,
});
@override
State<RiwayatDetailBalitaPage> createState() =>
_RiwayatDetailBalitaPageState();
}
class _RiwayatDetailBalitaPageState extends State<RiwayatDetailBalitaPage> {
List<dynamic> 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<void> 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<dynamic> 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<dynamic> 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<String, dynamic> 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++),
),
],
),
],
),
);
}
}