211 lines
6.7 KiB
Dart
211 lines
6.7 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io'; // Tambahkan ini
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart'; // Tambahkan ini untuk SystemNavigator.pop
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../layout/main_layout.dart';
|
|
import '../pages/petugas_drawer.dart';
|
|
import '../pages/login_page.dart';
|
|
|
|
class DashboardAdminPage extends StatefulWidget {
|
|
const DashboardAdminPage({super.key});
|
|
|
|
@override
|
|
State<DashboardAdminPage> createState() => _DashboardAdminPageState();
|
|
}
|
|
|
|
class _DashboardAdminPageState extends State<DashboardAdminPage> {
|
|
bool _isAuthorized = false;
|
|
bool _isLoading = true;
|
|
String userName = "Loading...";
|
|
|
|
int jumlahKader = 0;
|
|
int jumlahBidan = 0;
|
|
int jumlahDesa = 0;
|
|
int jumlahDusun = 0;
|
|
|
|
final String dashboardUrl =
|
|
"http://ta.myhost.id/E31230549/mposyandu_api/dashboard_admin.php";
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_initPage();
|
|
}
|
|
|
|
Future<void> _initPage() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final isLogin = prefs.getBool("isLogin") ?? false;
|
|
|
|
if (!isLogin) {
|
|
if (!mounted) return;
|
|
Navigator.pushAndRemoveUntil(
|
|
context,
|
|
MaterialPageRoute(builder: (_) => const LoginPage(fromGuard: true)),
|
|
(route) => false,
|
|
);
|
|
return;
|
|
}
|
|
|
|
setState(() {
|
|
_isAuthorized = true;
|
|
String? savedName = prefs.getString('nama');
|
|
userName = (savedName == null || savedName.isEmpty) ? "Admin" : savedName;
|
|
});
|
|
|
|
await fetchDashboard();
|
|
}
|
|
|
|
Future<void> fetchDashboard() async {
|
|
if (!_isAuthorized) return;
|
|
try {
|
|
final response = await http.get(Uri.parse(dashboardUrl));
|
|
if (response.statusCode == 200) {
|
|
final data = json.decode(response.body);
|
|
if (data["success"] == true) {
|
|
if (mounted) {
|
|
setState(() {
|
|
jumlahKader = data["jumlah_kader"] ?? 0;
|
|
jumlahBidan = data["jumlah_bidan"] ?? 0;
|
|
jumlahDesa = data["jumlah_desa"] ?? 0;
|
|
jumlahDusun = data["jumlah_dusun"] ?? 0;
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
debugPrint("ERROR DASHBOARD: $e");
|
|
if (mounted) setState(() => _isLoading = false);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Logika Responsif
|
|
double screenWidth = MediaQuery.of(context).size.width;
|
|
|
|
// Jika lebar layar > 700px (Desktop/Tablet), gunakan 4 kolom. Jika tidak (HP), 2 kolom.
|
|
int crossAxisCount = screenWidth > 700 ? 4 : 2;
|
|
|
|
// Mengatur rasio tinggi kartu agar tetap proporsional
|
|
double aspectRatio = screenWidth > 700 ? 1.5 : 1.1;
|
|
|
|
// Membungkus dengan PopScope agar ketika klik back button aplikasi keluar
|
|
return PopScope(
|
|
canPop: false, // Menahan aksi "back" standar navigator
|
|
onPopInvokedWithResult: (didPop, result) {
|
|
if (didPop) return;
|
|
// Keluar dari aplikasi secara total
|
|
if (Platform.isAndroid) {
|
|
SystemNavigator.pop();
|
|
} else if (Platform.isIOS) {
|
|
exit(0);
|
|
}
|
|
},
|
|
child: MainLayout(
|
|
title: " ",
|
|
drawer: const DrawerPetugas(),
|
|
body: RefreshIndicator(
|
|
onRefresh: fetchDashboard,
|
|
child: _isLoading
|
|
? const Center(child: CircularProgressIndicator())
|
|
: SingleChildScrollView(
|
|
physics: const AlwaysScrollableScrollPhysics(),
|
|
padding:
|
|
const EdgeInsets.symmetric(horizontal: 20, vertical: 25),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// HEADER AREA
|
|
RichText(
|
|
text: TextSpan(
|
|
children: [
|
|
TextSpan(
|
|
text: 'Selamat Datang Admin\n',
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w500,
|
|
color: Colors.black54),
|
|
),
|
|
TextSpan(
|
|
text: userName,
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 22,
|
|
fontWeight: FontWeight.w700,
|
|
color: const Color(0xFF1385E2)),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 25),
|
|
|
|
// GRID AREA (Dinamis berdasarkan perangkat)
|
|
GridView.count(
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
crossAxisCount: crossAxisCount,
|
|
crossAxisSpacing: 15,
|
|
mainAxisSpacing: 15,
|
|
childAspectRatio: aspectRatio,
|
|
children: [
|
|
_card(
|
|
"Kader", jumlahKader, Icons.groups, Colors.blue),
|
|
_card("Bidan", jumlahBidan, Icons.medical_services,
|
|
Colors.green),
|
|
_card("Desa", jumlahDesa, Icons.location_city,
|
|
Colors.orange),
|
|
_card("Dusun", jumlahDusun, Icons.map, Colors.purple),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _card(String title, int val, IconData icon, Color color) {
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: color,
|
|
borderRadius: BorderRadius.circular(15),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: color.withOpacity(0.3),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, 5),
|
|
)
|
|
],
|
|
),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(icon, color: Colors.white, size: 28),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
val.toString(),
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
Text(
|
|
title,
|
|
style: const TextStyle(
|
|
color: Colors.white70,
|
|
fontSize: 12,
|
|
letterSpacing: 0.5,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|