MIF_E31230549/lib/bidan/crud_jadwal/riwayat_jadwal_posyandu.dart

343 lines
11 KiB
Dart

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<RiwayatJadwalPosyanduPage> createState() =>
_RiwayatJadwalPosyanduPageState();
}
class _RiwayatJadwalPosyanduPageState extends State<RiwayatJadwalPosyanduPage> {
List<Map<String, dynamic>> dataRiwayat = [];
List<Map<String, dynamic>> dataFilter = [];
bool isLoading = true;
final TextEditingController searchController = TextEditingController();
int _currentPage = 0;
final int _rowsPerPage = 5;
List<Map<String, dynamic>> 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<void> 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<Map<String, dynamic>>.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<String> 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<void> 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<String, dynamic> 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++),
),
],
)
],
),
)
],
),
);
}
}