import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; const String baseUrl = "http://ta.myhost.id/E31230549/mposyandu_api"; class RiwayatJadwalPosyanduPage extends StatefulWidget { const RiwayatJadwalPosyanduPage({super.key}); @override State createState() => _RiwayatJadwalPosyanduPageState(); } class _RiwayatJadwalPosyanduPageState extends State { List> dataRiwayat = []; List> dataFilter = []; bool isLoading = true; final TextEditingController searchController = TextEditingController(); int _currentPage = 0; final int _rowsPerPage = 5; List> get _paginatedData { if (dataFilter.isEmpty) return []; final start = _currentPage * _rowsPerPage; final end = start + _rowsPerPage; if (start >= dataFilter.length) return []; return dataFilter.sublist( start, end > dataFilter.length ? dataFilter.length : end); } @override void initState() { super.initState(); loadRiwayat(); } Future loadRiwayat() async { try { final res = await http.get( Uri.parse("$baseUrl/jadwal_posyandu/get_all_jadwal.php"), ); final data = jsonDecode(res.body); if (data['success']) { setState(() { dataRiwayat = List>.from(data['data']); dataFilter = dataRiwayat; isLoading = false; }); } } catch (e) { debugPrint("Error riwayat : $e"); setState(() => isLoading = false); } } String formatTanggal(String tanggal) { try { final parts = tanggal.split("-"); String tahun = parts[0]; int bulan = int.parse(parts[1]); String hari = parts[2]; List namaBulan = [ "", "Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember" ]; return "$hari ${namaBulan[bulan]} $tahun"; } catch (e) { return tanggal; } } void searchData(String keyword) { final key = keyword.toLowerCase(); setState(() { dataFilter = dataRiwayat.where((item) { return item['tanggal'].toString().toLowerCase().contains(key) || item['lokasi'].toString().toLowerCase().contains(key) || item['dusun'].toString().toLowerCase().contains(key); }).toList(); _currentPage = 0; }); } Future hapusJadwal(String id) async { final res = await http.post( Uri.parse("$baseUrl/jadwal_posyandu/hapus_jadwal_posyandu.php"), body: {"id": id}, ); final data = jsonDecode(res.body); if (data['success']) { loadRiwayat(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text("Jadwal berhasil dihapus", style: GoogleFonts.poppins(fontSize: 12))), ); } } void konfirmasiHapus(String id) { showDialog( context: context, builder: (_) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), title: Text("Hapus Jadwal", style: GoogleFonts.poppins(fontWeight: FontWeight.bold, fontSize: 14)), content: Text("Apakah yakin ingin menghapus jadwal ini?", style: GoogleFonts.poppins(fontSize: 12)), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text("Batal", style: TextStyle(fontSize: 12))), // Button Hapus di Dialog juga disesuaikan OutlinedButton( style: OutlinedButton.styleFrom( side: const BorderSide(color: Colors.redAccent), shape: const StadiumBorder(), ), onPressed: () { Navigator.pop(context); hapusJadwal(id); }, child: const Text("Hapus", style: TextStyle( color: Colors.redAccent, fontSize: 12, fontWeight: FontWeight.bold)), ) ], ), ); } Widget rowData(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 2), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 70, child: Text(label, style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600)), ), Text(" : ", style: GoogleFonts.poppins(fontSize: 12)), Expanded( child: Text(value, style: GoogleFonts.poppins(fontSize: 12), softWrap: true), ) ], ), ); } Widget cardJadwal(Map item) { return Center( child: Container( margin: const EdgeInsets.symmetric(horizontal: 25, vertical: 8), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey.shade300), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.03), blurRadius: 5, offset: const Offset(0, 2)), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.event_note, size: 16, color: Colors.blueAccent), const SizedBox(width: 6), Text("Data Jadwal Posyandu", style: GoogleFonts.poppins( fontWeight: FontWeight.bold, fontSize: 13)), ], ), const Divider(height: 16, thickness: 1), rowData("Tanggal", formatTanggal(item['tanggal'] ?? "-")), rowData("Jam", "${item['jam_mulai']} - ${item['jam_selesai']}"), rowData("Lokasi", item['lokasi'] ?? "-"), rowData("Dusun", item['dusun'] ?? "-"), rowData("Kader", item['kader'] ?? "-"), rowData("Ket", item['keterangan'] ?? "-"), const SizedBox(height: 8), Align( alignment: Alignment.centerRight, child: SizedBox( height: 32, // Sedikit disesuaikan untuk Outlined Style // MENGUBAH GAYA BUTTON HAPUS DI SINI child: OutlinedButton.icon( onPressed: () => konfirmasiHapus(item['id'].toString()), icon: const Icon(Icons.delete_outline, size: 14, color: Colors.redAccent), label: Text("Hapus", style: GoogleFonts.poppins( color: Colors.redAccent, fontSize: 10, fontWeight: FontWeight.bold)), style: OutlinedButton.styleFrom( side: const BorderSide(color: Colors.redAccent), padding: const EdgeInsets.symmetric(horizontal: 12), shape: const StadiumBorder(), // Membuat bentuk lonjong ), ), ), ) ], ), ), ); } @override Widget build(BuildContext context) { final totalPages = dataFilter.isEmpty ? 1 : (dataFilter.length / _rowsPerPage).ceil(); return Scaffold( backgroundColor: const Color(0xFFFDFDFD), appBar: AppBar( backgroundColor: Colors.blueAccent, elevation: 0, leading: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.white), onPressed: () => Navigator.pop(context), ), title: null, ), body: Column( children: [ Padding( padding: const EdgeInsets.only(top: 20, bottom: 12), child: Center( child: Text( "Riwayat Jadwal Posyandu", style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black, ), ), ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: TextField( controller: searchController, onChanged: searchData, style: GoogleFonts.poppins(fontSize: 12), decoration: InputDecoration( hintText: "Cari berdasarkan tanggal, lokasi, a...", hintStyle: GoogleFonts.poppins(fontSize: 12, color: Colors.grey), prefixIcon: const Icon(Icons.search, size: 20, color: Colors.grey), contentPadding: const EdgeInsets.symmetric(vertical: 10), border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: Colors.grey), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: Colors.grey), ), ), ), ), const SizedBox(height: 15), Expanded( child: isLoading ? const Center(child: CircularProgressIndicator()) : dataFilter.isEmpty ? Center( child: Text("Data tidak ditemukan", style: GoogleFonts.poppins(fontSize: 12))) : ListView.builder( itemCount: _paginatedData.length, itemBuilder: (context, index) { return cardJadwal(_paginatedData[index]); }, ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Halaman ${_currentPage + 1} dari $totalPages", style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), ), Row( children: [ IconButton( iconSize: 20, icon: const Icon(Icons.chevron_left), onPressed: _currentPage == 0 ? null : () => setState(() => _currentPage--), ), IconButton( iconSize: 20, icon: const Icon(Icons.chevron_right), onPressed: _currentPage >= totalPages - 1 ? null : () => setState(() => _currentPage++), ), ], ) ], ), ) ], ), ); } }