168 lines
4.6 KiB
Dart
168 lines
4.6 KiB
Dart
import 'dart:convert';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:monitoring/config.dart';
|
|
|
|
class AbsensiScreen extends StatefulWidget {
|
|
final String token;
|
|
const AbsensiScreen({super.key, required this.token});
|
|
|
|
@override
|
|
State<AbsensiScreen> createState() => _AbsensiScreenState();
|
|
}
|
|
|
|
class _AbsensiScreenState extends State<AbsensiScreen> {
|
|
List<dynamic> data = [];
|
|
List<dynamic> filteredData = [];
|
|
bool loading = true;
|
|
|
|
int selectedMonth = DateTime.now().month;
|
|
|
|
final List<String> months = [
|
|
'Januari',
|
|
'Februari',
|
|
'Maret',
|
|
'April',
|
|
'Mei',
|
|
'Juni',
|
|
'Juli',
|
|
'Agustus',
|
|
'September',
|
|
'Oktober',
|
|
'November',
|
|
'Desember',
|
|
];
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
fetchAbsensi();
|
|
}
|
|
|
|
Future<void> fetchAbsensi() async {
|
|
final url = Uri.parse('$baseUrl/absensi');
|
|
|
|
try {
|
|
final response = await http.get(
|
|
url,
|
|
headers: {
|
|
'Accept': 'application/json',
|
|
'Authorization': 'Bearer ${widget.token}',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final resData = json.decode(response.body);
|
|
setState(() {
|
|
data = resData['data'];
|
|
loading = false;
|
|
applyMonthFilter();
|
|
});
|
|
} else {
|
|
setState(() => loading = false);
|
|
}
|
|
} catch (e) {
|
|
setState(() => loading = false);
|
|
}
|
|
}
|
|
|
|
void applyMonthFilter() {
|
|
setState(() {
|
|
filteredData =
|
|
data.where((item) {
|
|
final date = DateTime.tryParse(item['tanggal'] ?? '');
|
|
return date != null && date.month == selectedMonth;
|
|
}).toList();
|
|
});
|
|
}
|
|
|
|
Color getStatusColor(String status) {
|
|
switch (status.toLowerCase()) {
|
|
case 'hadir':
|
|
return Colors.green;
|
|
case 'sakit':
|
|
return Colors.orange;
|
|
case 'izin':
|
|
return Colors.blue;
|
|
default:
|
|
return Colors.grey;
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Absensi'),
|
|
actions: [
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
|
child: DropdownButtonHideUnderline(
|
|
child: DropdownButton<int>(
|
|
value: selectedMonth,
|
|
items: List.generate(12, (index) {
|
|
final monthName = months[index];
|
|
return DropdownMenuItem(
|
|
value: index + 1,
|
|
child: Text(monthName),
|
|
);
|
|
}),
|
|
onChanged: (value) {
|
|
if (value != null) {
|
|
setState(() {
|
|
selectedMonth = value;
|
|
applyMonthFilter();
|
|
});
|
|
}
|
|
},
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
body:
|
|
loading
|
|
? const Center(child: CircularProgressIndicator())
|
|
: filteredData.isEmpty
|
|
? const Center(child: Text('Tidak ada data absensi bulan ini.'))
|
|
: ListView.builder(
|
|
itemCount: filteredData.length,
|
|
itemBuilder: (context, index) {
|
|
final item = filteredData[index];
|
|
final tanggal = item['tanggal'] ?? '-';
|
|
final status = item['status'] ?? '-';
|
|
final keterangan = item['keterangan'] ?? '';
|
|
|
|
return ListTile(
|
|
leading: const Icon(
|
|
Icons.calendar_today,
|
|
color: Colors.green,
|
|
),
|
|
title: Text(tanggal),
|
|
subtitle: keterangan.isNotEmpty ? Text(keterangan) : null,
|
|
trailing: Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 12,
|
|
vertical: 6,
|
|
),
|
|
decoration: BoxDecoration(
|
|
color: getStatusColor(status).withOpacity(0.1),
|
|
border: Border.all(color: getStatusColor(status)),
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
child: Text(
|
|
status.toUpperCase(),
|
|
style: TextStyle(
|
|
color: getStatusColor(status),
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 12,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|