chnages has been made for the request leave and request advance
This commit is contained in:
@@ -2,12 +2,12 @@ class AdvanceRequest {
|
|||||||
final String id;
|
final String id;
|
||||||
final double amount;
|
final double amount;
|
||||||
final String reason;
|
final String reason;
|
||||||
final String status; // e.g., "pending", "approved", "rejected"
|
final String status; // "waiting", "approved", or "denied"
|
||||||
|
|
||||||
AdvanceRequest({
|
AdvanceRequest({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.amount,
|
required this.amount,
|
||||||
required this.reason,
|
required this.reason,
|
||||||
this.status = "pending",
|
this.status = "waiting", // Default status is "waiting"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart' show TimeOfDay;
|
// LeaveRequest model
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class LeaveRequest {
|
class LeaveRequest {
|
||||||
final String id;
|
final String id;
|
||||||
@@ -10,7 +11,8 @@ class LeaveRequest {
|
|||||||
final TimeOfDay toTime;
|
final TimeOfDay toTime;
|
||||||
final String reason;
|
final String reason;
|
||||||
final DateTime requestDate;
|
final DateTime requestDate;
|
||||||
final String status; // e.g
|
final String status; // "waiting", "approved", or "denied"
|
||||||
|
|
||||||
LeaveRequest({
|
LeaveRequest({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.leaveType,
|
required this.leaveType,
|
||||||
@@ -21,6 +23,8 @@ class LeaveRequest {
|
|||||||
required this.toTime,
|
required this.toTime,
|
||||||
required this.reason,
|
required this.reason,
|
||||||
required this.requestDate,
|
required this.requestDate,
|
||||||
this.status = "pending",
|
this.status = "waiting", // Default status is "waiting"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AdvanceRequest model
|
||||||
|
|||||||
@@ -15,20 +15,33 @@ class HolidayScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _HolidayScreenState extends State<HolidayScreen> {
|
class _HolidayScreenState extends State<HolidayScreen> {
|
||||||
int activeTab = 0; // 0 = السلف | 1 = الأجازات
|
int activeTab = 0; // 0 = السلف | 1 = الأجازات
|
||||||
|
// Use the singleton instance
|
||||||
final RequestService _requestService = RequestService();
|
final RequestService _requestService = RequestService();
|
||||||
late Future<List<LeaveRequest>> _leaveRequestsFuture;
|
late List<LeaveRequest> _leaveRequests;
|
||||||
late Future<List<AdvanceRequest>> _advanceRequestsFuture;
|
late List<AdvanceRequest> _advanceRequests;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_refreshData();
|
_initializeData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _refreshData() {
|
void _initializeData() async {
|
||||||
|
// Get initial data
|
||||||
|
_leaveRequests = await _requestService.getLeaveRequests();
|
||||||
|
_advanceRequests = await _requestService.getAdvanceRequests();
|
||||||
|
|
||||||
|
// Listen for updates
|
||||||
|
_requestService.leaveRequestsStream.listen((requests) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_leaveRequestsFuture = Future.value(_requestService.leaveRequests);
|
_leaveRequests = requests;
|
||||||
_advanceRequestsFuture = Future.value(_requestService.advanceRequests);
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
_requestService.advanceRequestsStream.listen((requests) {
|
||||||
|
setState(() {
|
||||||
|
_advanceRequests = requests;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +49,7 @@ class _HolidayScreenState extends State<HolidayScreen> {
|
|||||||
switch (status) {
|
switch (status) {
|
||||||
case 'approved':
|
case 'approved':
|
||||||
return Colors.green;
|
return Colors.green;
|
||||||
case 'rejected':
|
case 'denied':
|
||||||
return Colors.red;
|
return Colors.red;
|
||||||
default:
|
default:
|
||||||
return Colors.orange;
|
return Colors.orange;
|
||||||
@@ -47,13 +60,24 @@ class _HolidayScreenState extends State<HolidayScreen> {
|
|||||||
switch (status) {
|
switch (status) {
|
||||||
case 'approved':
|
case 'approved':
|
||||||
return 'موافق عليه';
|
return 'موافق عليه';
|
||||||
case 'rejected':
|
case 'denied':
|
||||||
return 'مرفوض';
|
return 'مرفوض';
|
||||||
default:
|
default:
|
||||||
return 'قيد الانتظار';
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Directionality(
|
return Directionality(
|
||||||
@@ -148,14 +172,15 @@ class _HolidayScreenState extends State<HolidayScreen> {
|
|||||||
svgPath: "assets/images/money2.svg",
|
svgPath: "assets/images/money2.svg",
|
||||||
iconWidth: 38,
|
iconWidth: 38,
|
||||||
iconHeight: 30,
|
iconHeight: 30,
|
||||||
onTap: () {
|
onTap: () async {
|
||||||
// Navigate to RequestAdvanceScreen
|
// Navigate to RequestAdvanceScreen
|
||||||
Navigator.push(
|
await Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => const RequestAdvanceScreen(),
|
builder: (context) => const RequestAdvanceScreen(),
|
||||||
),
|
),
|
||||||
).then((_) => _refreshData()); // Refresh data when returning
|
);
|
||||||
|
// Data will be updated automatically through the stream
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 18),
|
const SizedBox(height: 18),
|
||||||
@@ -166,13 +191,14 @@ class _HolidayScreenState extends State<HolidayScreen> {
|
|||||||
svgPath: "assets/images/plus.svg",
|
svgPath: "assets/images/plus.svg",
|
||||||
iconWidth: 30,
|
iconWidth: 30,
|
||||||
iconHeight: 30,
|
iconHeight: 30,
|
||||||
onTap: () {
|
onTap: () async {
|
||||||
Navigator.push(
|
await Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => const RequestLeaveScreen(),
|
builder: (context) => const RequestLeaveScreen(),
|
||||||
),
|
),
|
||||||
).then((_) => _refreshData()); // Refresh data when returning
|
);
|
||||||
|
// Data will be updated automatically through the stream
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -184,14 +210,7 @@ class _HolidayScreenState extends State<HolidayScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildLeaveRequestsTab() {
|
Widget _buildLeaveRequestsTab() {
|
||||||
return FutureBuilder<List<LeaveRequest>>(
|
if (_leaveRequests.isEmpty) {
|
||||||
future: _leaveRequestsFuture,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
||||||
return const Center(child: CircularProgressIndicator(color: Colors.white));
|
|
||||||
} else if (snapshot.hasError) {
|
|
||||||
return Center(child: Text('Error: ${snapshot.error}', style: TextStyle(color: Colors.white)));
|
|
||||||
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
|
||||||
return const Center(
|
return const Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'لا توجد طلبات أجازة',
|
'لا توجد طلبات أجازة',
|
||||||
@@ -203,34 +222,24 @@ class _HolidayScreenState extends State<HolidayScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final leaveRequests = snapshot.data!;
|
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
_refreshData();
|
_initializeData();
|
||||||
},
|
},
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 20),
|
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 20),
|
||||||
itemCount: leaveRequests.length,
|
itemCount: _leaveRequests.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final request = leaveRequests[index];
|
final request = _leaveRequests[index];
|
||||||
return _buildLeaveRequestCard(request);
|
return _buildLeaveRequestCard(request);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAdvanceRequestsTab() {
|
Widget _buildAdvanceRequestsTab() {
|
||||||
return FutureBuilder<List<AdvanceRequest>>(
|
if (_advanceRequests.isEmpty) {
|
||||||
future: _advanceRequestsFuture,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
||||||
return const Center(child: CircularProgressIndicator(color: Colors.white));
|
|
||||||
} else if (snapshot.hasError) {
|
|
||||||
return Center(child: Text('Error: ${snapshot.error}', style: TextStyle(color: Colors.white)));
|
|
||||||
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
|
||||||
return const Center(
|
return const Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'لا توجد طلبات سلف',
|
'لا توجد طلبات سلف',
|
||||||
@@ -242,23 +251,20 @@ class _HolidayScreenState extends State<HolidayScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final advanceRequests = snapshot.data!;
|
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
_refreshData();
|
_initializeData();
|
||||||
},
|
},
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 20),
|
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 20),
|
||||||
itemCount: advanceRequests.length,
|
itemCount: _advanceRequests.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final request = advanceRequests[index];
|
final request = _advanceRequests[index];
|
||||||
return _buildAdvanceRequestCard(request);
|
return _buildAdvanceRequestCard(request);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildLeaveRequestCard(LeaveRequest request) {
|
Widget _buildLeaveRequestCard(LeaveRequest request) {
|
||||||
@@ -283,19 +289,18 @@ class _HolidayScreenState extends State<HolidayScreen> {
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
// Status icon instead of text
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
padding: const EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: _getStatusColor(request.status),
|
color: _getStatusColor(request.status),
|
||||||
borderRadius: BorderRadius.circular(20),
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: SvgPicture.asset(
|
||||||
_getStatusText(request.status),
|
_getStatusIconPath(request.status),
|
||||||
style: const TextStyle(
|
width: 24,
|
||||||
|
height: 24,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
@@ -399,43 +404,24 @@ class _HolidayScreenState extends State<HolidayScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Action buttons for pending requests
|
// Status text below the card
|
||||||
if (request.status == 'pending') ...[
|
const SizedBox(height: 8),
|
||||||
const SizedBox(height: 16),
|
Directionality(
|
||||||
Row(
|
textDirection: TextDirection.rtl,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
ElevatedButton(
|
Text(
|
||||||
onPressed: () {
|
_getStatusText(request.status),
|
||||||
_updateLeaveRequestStatus(request.id, 'approved');
|
style: TextStyle(
|
||||||
},
|
color: _getStatusColor(request.status),
|
||||||
style: ElevatedButton.styleFrom(
|
fontSize: 14,
|
||||||
backgroundColor: Colors.green,
|
fontWeight: FontWeight.w600,
|
||||||
foregroundColor: Colors.white,
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: const Text('موافق'),
|
|
||||||
),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
_updateLeaveRequestStatus(request.id, 'rejected');
|
|
||||||
},
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: const Text('رفض'),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -459,23 +445,22 @@ class _HolidayScreenState extends State<HolidayScreen> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
// Header with status
|
// Header with status icon
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
// Status icon instead of text
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
padding: const EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: _getStatusColor(request.status),
|
color: _getStatusColor(request.status),
|
||||||
borderRadius: BorderRadius.circular(20),
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: SvgPicture.asset(
|
||||||
_getStatusText(request.status),
|
_getStatusIconPath(request.status),
|
||||||
style: const TextStyle(
|
width: 24,
|
||||||
|
height: 24,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
@@ -526,69 +511,25 @@ class _HolidayScreenState extends State<HolidayScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Request date - removed since advance requests don't have request date
|
// Status text below the card
|
||||||
// Action buttons for pending requests
|
const SizedBox(height: 8),
|
||||||
if (request.status == 'pending') ...[
|
Directionality(
|
||||||
const SizedBox(height: 16),
|
textDirection: TextDirection.rtl,
|
||||||
Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
ElevatedButton(
|
Text(
|
||||||
onPressed: () {
|
_getStatusText(request.status),
|
||||||
_updateAdvanceRequestStatus(request.id, 'approved');
|
style: TextStyle(
|
||||||
},
|
color: _getStatusColor(request.status),
|
||||||
style: ElevatedButton.styleFrom(
|
fontSize: 14,
|
||||||
backgroundColor: Colors.green,
|
fontWeight: FontWeight.w600,
|
||||||
foregroundColor: Colors.white,
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: const Text('موافق'),
|
|
||||||
),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
_updateAdvanceRequestStatus(request.id, 'rejected');
|
|
||||||
},
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: const Text('رفض'),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
],
|
||||||
}
|
|
||||||
|
|
||||||
void _updateLeaveRequestStatus(String id, String status) async {
|
|
||||||
await _requestService.updateLeaveRequestStatus(id, status);
|
|
||||||
_refreshData();
|
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text('تم ${status == 'approved' ? 'قبول' : 'رفض'} الطلب'),
|
|
||||||
backgroundColor: status == 'approved' ? Colors.green : Colors.red,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _updateAdvanceRequestStatus(String id, String status) async {
|
|
||||||
await _requestService.updateAdvanceRequestStatus(id, status);
|
|
||||||
_refreshData();
|
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text('تم ${status == 'approved' ? 'قبول' : 'رفض'} الطلب'),
|
|
||||||
backgroundColor: status == 'approved' ? Colors.green : Colors.red,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class _RequestAdvanceScreenState extends State<RequestAdvanceScreen> {
|
|||||||
// Text controller for reason
|
// Text controller for reason
|
||||||
final TextEditingController reasonController = TextEditingController();
|
final TextEditingController reasonController = TextEditingController();
|
||||||
|
|
||||||
|
// Use the singleton instance
|
||||||
final RequestService _requestService = RequestService();
|
final RequestService _requestService = RequestService();
|
||||||
|
|
||||||
// Method to save the advance request
|
// Method to save the advance request
|
||||||
@@ -48,13 +49,15 @@ class _RequestAdvanceScreenState extends State<RequestAdvanceScreen> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new advance request
|
// Create a new advance request with default status "waiting"
|
||||||
final advanceRequest = AdvanceRequest(
|
final advanceRequest = AdvanceRequest(
|
||||||
id: DateTime.now().millisecondsSinceEpoch.toString(),
|
id: DateTime.now().millisecondsSinceEpoch.toString(),
|
||||||
amount: amount,
|
amount: amount,
|
||||||
reason: reasonController.text,
|
reason: reasonController.text,
|
||||||
|
status: "waiting", // Default status
|
||||||
);
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
// Save the advance request
|
// Save the advance request
|
||||||
await _requestService.addAdvanceRequest(advanceRequest);
|
await _requestService.addAdvanceRequest(advanceRequest);
|
||||||
|
|
||||||
@@ -68,6 +71,15 @@ class _RequestAdvanceScreenState extends State<RequestAdvanceScreen> {
|
|||||||
|
|
||||||
// Navigate back to the previous screen
|
// Navigate back to the previous screen
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
} catch (e) {
|
||||||
|
// Show an error message if something went wrong
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text('حدث خطأ: $e'),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class _RequestLeaveScreenState extends State<RequestLeaveScreen> {
|
|||||||
// Text controller for reason
|
// Text controller for reason
|
||||||
final TextEditingController reasonController = TextEditingController();
|
final TextEditingController reasonController = TextEditingController();
|
||||||
|
|
||||||
|
// Use the singleton instance
|
||||||
final RequestService _requestService = RequestService();
|
final RequestService _requestService = RequestService();
|
||||||
|
|
||||||
/// PICK DATE
|
/// PICK DATE
|
||||||
@@ -91,7 +92,7 @@ class _RequestLeaveScreenState extends State<RequestLeaveScreen> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new leave request
|
// Create a new leave request with default status "waiting"
|
||||||
final leaveRequest = LeaveRequest(
|
final leaveRequest = LeaveRequest(
|
||||||
id: DateTime.now().millisecondsSinceEpoch.toString(),
|
id: DateTime.now().millisecondsSinceEpoch.toString(),
|
||||||
leaveType: leaveType,
|
leaveType: leaveType,
|
||||||
@@ -102,8 +103,10 @@ class _RequestLeaveScreenState extends State<RequestLeaveScreen> {
|
|||||||
toTime: toTime!,
|
toTime: toTime!,
|
||||||
reason: reasonController.text,
|
reason: reasonController.text,
|
||||||
requestDate: DateTime.now(),
|
requestDate: DateTime.now(),
|
||||||
|
status: "waiting", // Default status
|
||||||
);
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
// Save the leave request
|
// Save the leave request
|
||||||
await _requestService.addLeaveRequest(leaveRequest);
|
await _requestService.addLeaveRequest(leaveRequest);
|
||||||
|
|
||||||
@@ -117,6 +120,15 @@ class _RequestLeaveScreenState extends State<RequestLeaveScreen> {
|
|||||||
|
|
||||||
// Navigate back to the previous screen
|
// Navigate back to the previous screen
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
} catch (e) {
|
||||||
|
// Show an error message if something went wrong
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text('حدث خطأ: $e'),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'dart:async';
|
||||||
import '../models/leave_request.dart';
|
import '../models/leave_request.dart';
|
||||||
import '../models/advance_request.dart';
|
import '../models/advance_request.dart';
|
||||||
|
|
||||||
class RequestService {
|
class RequestService {
|
||||||
|
// Singleton implementation
|
||||||
static final RequestService _instance = RequestService._internal();
|
static final RequestService _instance = RequestService._internal();
|
||||||
factory RequestService() => _instance;
|
factory RequestService() => _instance;
|
||||||
RequestService._internal();
|
RequestService._internal();
|
||||||
@@ -10,22 +11,47 @@ class RequestService {
|
|||||||
final List<LeaveRequest> _leaveRequests = [];
|
final List<LeaveRequest> _leaveRequests = [];
|
||||||
final List<AdvanceRequest> _advanceRequests = [];
|
final List<AdvanceRequest> _advanceRequests = [];
|
||||||
|
|
||||||
List<LeaveRequest> get leaveRequests => List.unmodifiable(_leaveRequests);
|
// Stream controllers to notify listeners of changes
|
||||||
List<AdvanceRequest> get advanceRequests => List.unmodifiable(_advanceRequests);
|
final _leaveRequestsController = StreamController<List<LeaveRequest>>.broadcast();
|
||||||
|
final _advanceRequestsController = StreamController<List<AdvanceRequest>>.broadcast();
|
||||||
|
|
||||||
|
// Stream getters
|
||||||
|
Stream<List<LeaveRequest>> get leaveRequestsStream => _leaveRequestsController.stream;
|
||||||
|
Stream<List<AdvanceRequest>> get advanceRequestsStream => _advanceRequestsController.stream;
|
||||||
|
|
||||||
|
// Get all leave requests as a Future
|
||||||
|
Future<List<LeaveRequest>> getLeaveRequests() async {
|
||||||
|
print("Getting ${_leaveRequests.length} leave requests");
|
||||||
|
return List.from(_leaveRequests);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all advance requests as a Future
|
||||||
|
Future<List<AdvanceRequest>> getAdvanceRequests() async {
|
||||||
|
print("Getting ${_advanceRequests.length} advance requests");
|
||||||
|
return List.from(_advanceRequests);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new leave request
|
||||||
Future<void> addLeaveRequest(LeaveRequest request) async {
|
Future<void> addLeaveRequest(LeaveRequest request) async {
|
||||||
_leaveRequests.add(request);
|
_leaveRequests.add(request);
|
||||||
// In a real app, you would save this to a database or API
|
print("Added leave request: ${request.id}, total: ${_leaveRequests.length}");
|
||||||
|
// Notify listeners
|
||||||
|
_leaveRequestsController.add(List.from(_leaveRequests));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a new advance request
|
||||||
Future<void> addAdvanceRequest(AdvanceRequest request) async {
|
Future<void> addAdvanceRequest(AdvanceRequest request) async {
|
||||||
_advanceRequests.add(request);
|
_advanceRequests.add(request);
|
||||||
// In a real app, you would save this to a database or API
|
print("Added advance request: ${request.id}, total: ${_advanceRequests.length}");
|
||||||
|
// Notify listeners
|
||||||
|
_advanceRequestsController.add(List.from(_advanceRequests));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update leave request status
|
||||||
Future<void> updateLeaveRequestStatus(String id, String status) async {
|
Future<void> updateLeaveRequestStatus(String id, String status) async {
|
||||||
final index = _leaveRequests.indexWhere((request) => request.id == id);
|
final index = _leaveRequests.indexWhere((request) => request.id == id);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
|
// Create a new request with the updated status
|
||||||
final updatedRequest = LeaveRequest(
|
final updatedRequest = LeaveRequest(
|
||||||
id: _leaveRequests[index].id,
|
id: _leaveRequests[index].id,
|
||||||
leaveType: _leaveRequests[index].leaveType,
|
leaveType: _leaveRequests[index].leaveType,
|
||||||
@@ -36,22 +62,40 @@ class RequestService {
|
|||||||
toTime: _leaveRequests[index].toTime,
|
toTime: _leaveRequests[index].toTime,
|
||||||
reason: _leaveRequests[index].reason,
|
reason: _leaveRequests[index].reason,
|
||||||
requestDate: _leaveRequests[index].requestDate,
|
requestDate: _leaveRequests[index].requestDate,
|
||||||
status: status,
|
status: status, // Updated status
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Replace the old request with the updated one
|
||||||
_leaveRequests[index] = updatedRequest;
|
_leaveRequests[index] = updatedRequest;
|
||||||
|
print("Updated leave request status: $id to $status");
|
||||||
|
// Notify listeners
|
||||||
|
_leaveRequestsController.add(List.from(_leaveRequests));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update advance request status
|
||||||
Future<void> updateAdvanceRequestStatus(String id, String status) async {
|
Future<void> updateAdvanceRequestStatus(String id, String status) async {
|
||||||
final index = _advanceRequests.indexWhere((request) => request.id == id);
|
final index = _advanceRequests.indexWhere((request) => request.id == id);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
|
// Create a new request with the updated status
|
||||||
final updatedRequest = AdvanceRequest(
|
final updatedRequest = AdvanceRequest(
|
||||||
id: _advanceRequests[index].id,
|
id: _advanceRequests[index].id,
|
||||||
amount: _advanceRequests[index].amount,
|
amount: _advanceRequests[index].amount,
|
||||||
reason: _advanceRequests[index].reason,
|
reason: _advanceRequests[index].reason,
|
||||||
status: status,
|
status: status, // Updated status
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Replace the old request with the updated one
|
||||||
_advanceRequests[index] = updatedRequest;
|
_advanceRequests[index] = updatedRequest;
|
||||||
|
print("Updated advance request status: $id to $status");
|
||||||
|
// Notify listeners
|
||||||
|
_advanceRequestsController.add(List.from(_advanceRequests));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dispose method to close streams
|
||||||
|
void dispose() {
|
||||||
|
_leaveRequestsController.close();
|
||||||
|
_advanceRequestsController.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user