Files
finger_print_app/lib/screens/holiday_screen.dart
2025-12-07 12:53:43 +03:00

595 lines
17 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../screens/request_leave_screen.dart';
import '../screens/request_advance_scrren.dart';
import '../models/leave_request.dart';
import '../models/advance_request.dart';
import '../services/request_service.dart';
class HolidayScreen extends StatefulWidget {
const HolidayScreen({super.key});
@override
State<HolidayScreen> createState() => _HolidayScreenState();
}
class _HolidayScreenState extends State<HolidayScreen> {
int activeTab = 0; // 0 = السلف | 1 = الأجازات
// Use the singleton instance
final RequestService _requestService = RequestService();
late List<LeaveRequest> _leaveRequests;
late List<AdvanceRequest> _advanceRequests;
@override
void initState() {
super.initState();
_initializeData();
}
void _initializeData() async {
// Get initial data
_leaveRequests = await _requestService.getLeaveRequests();
_advanceRequests = await _requestService.getAdvanceRequests();
// Listen for updates
_requestService.leaveRequestsStream.listen((requests) {
setState(() {
_leaveRequests = requests;
});
});
_requestService.advanceRequestsStream.listen((requests) {
setState(() {
_advanceRequests = requests;
});
});
}
Color _getStatusColor(String status) {
switch (status) {
case 'approved':
return Colors.green;
case 'denied':
return Colors.red;
default:
return Colors.orange;
}
}
String _getStatusText(String status) {
switch (status) {
case 'approved':
return 'موافق عليه';
case 'denied':
return 'مرفوض';
default:
return 'قيد الانتظار';
}
}
String _getStatusIconPath(String status) {
switch (status) {
case 'approved':
return "assets/images/yes.svg";
case 'denied':
return "assets/images/no.svg";
default:
return "assets/images/waiting.svg";
}
}
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Stack(
children: [
// Tabs
Positioned(
top: 40,
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// الأجازات TAB
GestureDetector(
onTap: () => setState(() => activeTab = 1),
child: Column(
children: [
Text(
"الأجازات",
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w600,
color:
activeTab == 1
? const Color(0xFF8EFDC2)
: const Color(0x9EFFFFFF),
),
),
if (activeTab == 1)
Container(
width: 60,
height: 2,
margin: const EdgeInsets.only(top: 4),
color: const Color(0xFF8EFDC2),
),
],
),
),
const SizedBox(width: 70),
// السلف TAB
GestureDetector(
onTap: () => setState(() => activeTab = 0),
child: Column(
children: [
Text(
"السلف",
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w600,
color:
activeTab == 0
? const Color(0xFF8EFDC2)
: const Color(0x9EFFFFFF),
),
),
if (activeTab == 0)
Container(
width: 60,
height: 2,
margin: const EdgeInsets.only(top: 4),
color: const Color(0xFF8EFDC2),
),
],
),
),
],
),
),
// Content area for requests
Positioned(
top: 100, // Position below the tabs
left: 0,
right: 0,
bottom: 120, // Leave space for action buttons
child: activeTab == 1 ? _buildLeaveRequestsTab() : _buildAdvanceRequestsTab(),
),
// Action buttons
Positioned(
bottom: 30,
right: 20,
child: Column(
children: [
// Money icon (custom size)
_HolidayActionButton(
label: "طلب سلفة",
svgPath: "assets/images/money2.svg",
iconWidth: 38,
iconHeight: 30,
onTap: () async {
// Navigate to RequestAdvanceScreen
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const RequestAdvanceScreen(),
),
);
// Data will be updated automatically through the stream
},
),
const SizedBox(height: 18),
// Plus icon (custom size)
_HolidayActionButton(
label: "طلب إجازة",
svgPath: "assets/images/plus.svg",
iconWidth: 30,
iconHeight: 30,
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const RequestLeaveScreen(),
),
);
// Data will be updated automatically through the stream
},
),
],
),
),
],
),
);
}
Widget _buildLeaveRequestsTab() {
if (_leaveRequests.isEmpty) {
return const Center(
child: Text(
'لا توجد طلبات أجازة',
style: TextStyle(
color: Colors.white,
fontSize: 18,
),
),
);
}
return RefreshIndicator(
onRefresh: () async {
_initializeData();
},
color: Colors.white,
child: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 20),
itemCount: _leaveRequests.length,
itemBuilder: (context, index) {
final request = _leaveRequests[index];
return _buildLeaveRequestCard(request);
},
),
);
}
Widget _buildAdvanceRequestsTab() {
if (_advanceRequests.isEmpty) {
return const Center(
child: Text(
'لا توجد طلبات سلف',
style: TextStyle(
color: Colors.white,
fontSize: 18,
),
),
);
}
return RefreshIndicator(
onRefresh: () async {
_initializeData();
},
color: Colors.white,
child: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 20),
itemCount: _advanceRequests.length,
itemBuilder: (context, index) {
final request = _advanceRequests[index];
return _buildAdvanceRequestCard(request);
},
),
);
}
Widget _buildLeaveRequestCard(LeaveRequest request) {
return Container(
margin: const EdgeInsets.only(bottom: 16),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: const [
BoxShadow(
color: Color(0x33000000),
blurRadius: 10,
offset: Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
// Header with type and status
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Status icon instead of text
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: _getStatusColor(request.status),
shape: BoxShape.circle,
),
child: SvgPicture.asset(
_getStatusIconPath(request.status),
width: 24,
height: 24,
color: Colors.white,
),
),
Text(
request.isTimedLeave ? "أجازة زمنية" : request.leaveType,
style: const TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 12),
// Date range
Directionality(
textDirection: TextDirection.rtl,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
'من: ${request.fromDate.day}/${request.fromDate.month}/${request.fromDate.year}',
style: const TextStyle(
color: Colors.black87,
fontSize: 16,
),
),
const SizedBox(width: 20),
Text(
'إلى: ${request.toDate.day}/${request.toDate.month}/${request.toDate.year}',
style: const TextStyle(
color: Colors.black87,
fontSize: 16,
),
),
],
),
),
if (request.isTimedLeave) ...[
const SizedBox(height: 8),
Directionality(
textDirection: TextDirection.rtl,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
'من: ${request.fromTime.hour}:${request.fromTime.minute.toString().padLeft(2, '0')}',
style: const TextStyle(
color: Colors.black87,
fontSize: 16,
),
),
const SizedBox(width: 20),
Text(
'إلى: ${request.toTime.hour}:${request.toTime.minute.toString().padLeft(2, '0')}',
style: const TextStyle(
color: Colors.black87,
fontSize: 16,
),
),
],
),
),
],
const SizedBox(height: 12),
// Reason
Directionality(
textDirection: TextDirection.rtl,
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: const Color(0xFFF5F5F5),
borderRadius: BorderRadius.circular(8),
),
child: Text(
request.reason,
style: const TextStyle(
color: Colors.black87,
fontSize: 16,
),
),
),
),
const SizedBox(height: 12),
// Request date
Directionality(
textDirection: TextDirection.rtl,
child: Text(
'تاريخ الطلب: ${request.requestDate.day}/${request.requestDate.month}/${request.requestDate.year}',
style: const TextStyle(
color: Colors.grey,
fontSize: 14,
),
),
),
// Status text below the card
const SizedBox(height: 8),
Directionality(
textDirection: TextDirection.rtl,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
_getStatusText(request.status),
style: TextStyle(
color: _getStatusColor(request.status),
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
],
),
),
],
),
);
}
Widget _buildAdvanceRequestCard(AdvanceRequest request) {
return Container(
margin: const EdgeInsets.only(bottom: 16),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: const [
BoxShadow(
color: Color(0x33000000),
blurRadius: 10,
offset: Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
// Header with status icon
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Status icon instead of text
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: _getStatusColor(request.status),
shape: BoxShape.circle,
),
child: SvgPicture.asset(
_getStatusIconPath(request.status),
width: 24,
height: 24,
color: Colors.white,
),
),
Text(
'طلب سلفة',
style: const TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 12),
// Amount
Directionality(
textDirection: TextDirection.rtl,
child: Text(
'المبلغ: ${request.amount.toStringAsFixed(2)} دع',
style: const TextStyle(
color: Colors.black87,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 12),
// Reason
Directionality(
textDirection: TextDirection.rtl,
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: const Color(0xFFF5F5F5),
borderRadius: BorderRadius.circular(8),
),
child: Text(
request.reason,
style: const TextStyle(
color: Colors.black87,
fontSize: 16,
),
),
),
),
// Status text below the card
const SizedBox(height: 8),
Directionality(
textDirection: TextDirection.rtl,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
_getStatusText(request.status),
style: TextStyle(
color: _getStatusColor(request.status),
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
],
),
),
],
),
);
}
}
class _HolidayActionButton extends StatelessWidget {
final String label;
final String svgPath;
final VoidCallback onTap;
final double iconWidth;
final double iconHeight;
const _HolidayActionButton({
required this.label,
required this.svgPath,
required this.onTap,
required this.iconWidth,
required this.iconHeight,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
width: 80,
height: 80,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
boxShadow: const [
BoxShadow(
color: Color(0x4B00C68B),
blurRadius: 20,
offset: Offset(0, 6),
),
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: iconWidth,
height: iconHeight,
child: SvgPicture.asset(svgPath, fit: BoxFit.contain),
),
const SizedBox(height: 6),
Text(
label,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
],
),
),
);
}
}