FarisaRahmaSari_E31222327/BBS/lib/view/home/statuscuti.dart

354 lines
14 KiB
Dart

import 'package:flutter/material.dart';
import 'package:qyuota/config/colors.dart';
import 'package:qyuota/view/home/home_view.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:qyuota/models/leave.dart';
import 'package:qyuota/config/api_config.dart';
import 'package:qyuota/services/api_service.dart';
import 'package:intl/intl.dart';
import 'package:qyuota/services/auth_service.dart';
class StatusCuti extends StatefulWidget {
const StatusCuti({Key? key}) : super(key: key);
@override
_StatusCutiState createState() => _StatusCutiState();
}
class _StatusCutiState extends State<StatusCuti> {
List<Leave> leaves = [];
bool isLoading = true;
bool _isSessionValid = true;
final ApiService _apiService = ApiService();
@override
void initState() {
super.initState();
_checkSessionAndLoadData();
}
Future<void> _checkSessionAndLoadData() async {
final isValid = await AuthService().checkSession(context);
if (isValid) {
setState(() {
_isSessionValid = true;
});
await _fetchLeaves();
} else {
setState(() {
_isSessionValid = false;
});
}
}
Future<void> _fetchLeaves() async {
setState(() {
isLoading = true;
});
try {
final leaves = await _apiService.getLeaves();
setState(() {
this.leaves = leaves;
isLoading = false;
});
} catch (e) {
setState(() {
leaves = [];
isLoading = false;
});
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error: ${e.toString()}'),
backgroundColor: Colors.red,
),
);
}
}
}
String formatDate(String date) {
try {
final DateTime parsed = DateTime.parse(date);
return DateFormat('dd MMM yyyy').format(parsed);
} catch (e) {
return date;
}
}
Color getStatusColor(String status) {
switch (status.toLowerCase()) {
case 'disetujui':
return Colors.green;
case 'ditolak':
return Colors.red;
case 'pending':
return Colors.orange;
default:
return Colors.grey;
}
}
IconData getStatusIcon(String status) {
switch (status.toLowerCase()) {
case 'disetujui':
return Icons.check_circle;
case 'ditolak':
return Icons.cancel;
case 'pending':
return Icons.access_time;
default:
return Icons.help;
}
}
@override
Widget build(BuildContext context) {
if (!_isSessionValid) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
return Scaffold(
backgroundColor: Colors.grey[50],
appBar: AppBar(
elevation: 0,
title: const Text(
"Status Cuti",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
centerTitle: true,
backgroundColor: ConstColors.primaryColor,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
onPressed: () => Navigator.of(context).pop(),
),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(20),
),
),
),
body: RefreshIndicator(
onRefresh: () async {
await _checkSessionAndLoadData();
},
child: isLoading
? const Center(child: CircularProgressIndicator())
: leaves.isEmpty
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.note_alt_outlined,
size: 64,
color: Colors.grey[400],
),
const SizedBox(height: 16),
Text(
'Belum ada pengajuan cuti',
style: TextStyle(
fontSize: 16,
color: Colors.grey[600],
),
),
],
),
)
: ListView.builder(
padding: const EdgeInsets.only(top: 12, bottom: 12),
itemCount: leaves.length,
itemBuilder: (context, index) {
final leave = leaves[index];
return Align(
alignment: Alignment.center,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 10,
offset: const Offset(0, 1),
),
],
),
child: Column(
children: [
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: getStatusColor(leave.status).withOpacity(0.1),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(15),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Row(
children: [
Icon(
getStatusIcon(leave.status),
color: getStatusColor(leave.status),
size: 24,
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Pengajuan Cuti',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 4),
Text(
leave.reason,
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
),
const SizedBox(width: 8),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
),
decoration: BoxDecoration(
color: getStatusColor(leave.status).withOpacity(0.1),
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: getStatusColor(leave.status).withOpacity(0.5),
),
),
child: Text(
leave.status,
style: TextStyle(
color: getStatusColor(leave.status),
fontWeight: FontWeight.bold,
fontSize: 12,
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'Tanggal Mulai',
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
),
const SizedBox(height: 4),
Text(
formatDate(leave.startDate),
style: const TextStyle(
fontWeight: FontWeight.w500,
),
),
],
),
),
Container(
height: 30,
width: 1,
color: Colors.grey[300],
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'Tanggal Selesai',
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
),
const SizedBox(height: 4),
Text(
formatDate(leave.endDate),
style: const TextStyle(
fontWeight: FontWeight.w500,
),
),
],
),
),
],
),
),
if (leave.status.toLowerCase() != 'pending')
Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Row(
children: [
Icon(
leave.status.toLowerCase() == 'disetujui'
? Icons.check_circle_outline
: Icons.person_off,
size: 16,
color: Colors.grey[600],
),
const SizedBox(width: 8),
Text(
leave.status.toLowerCase() == 'disetujui'
? 'Disetujui oleh: ${leave.approvedBy ?? "Admin"}'
: 'Ditolak oleh: ${leave.rejectedBy ?? "Admin"}',
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
),
],
),
),
],
),
),
);
},
),
),
);
}
}