Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sai Srinivas
GEN_ERP_2025
Commits
f6fbe101
Commit
f6fbe101
authored
Aug 29, 2025
by
Mohit Kumar
Browse files
AttendanceList
RewardList TourExpenses Implementation
parent
6d1deaf2
Changes
33
Hide whitespace changes
Inline
Side-by-side
lib/screens/hrm/LeaveApplicationDetailScreen.dart
0 → 100644
View file @
f6fbe101
import
'package:dotted_line/dotted_line.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:provider/provider.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
import
'../../Notifiers/hrmProvider/leaveApplicationDetailsProvider.dart'
;
import
'../../Notifiers/HomeScreenNotifier.dart'
;
import
'../../Utils/app_colors.dart'
;
import
'../finance/FileViewer.dart'
;
/// Screen for leave application details
class
LeaveApplicationDetailScreen
extends
StatefulWidget
{
final
String
leaveRequestId
;
const
LeaveApplicationDetailScreen
({
super
.
key
,
required
this
.
leaveRequestId
});
@override
State
<
LeaveApplicationDetailScreen
>
createState
()
=>
_LeaveApplicationDetailScreenState
();
}
class
_LeaveApplicationDetailScreenState
extends
State
<
LeaveApplicationDetailScreen
>
{
@override
Widget
build
(
BuildContext
context
)
{
return
ChangeNotifierProvider
(
create:
(
_
)
=>
LeaveApplicationDetailsProvider
()..
fetchLeaveApplicationDetails
(
context
,
widget
.
leaveRequestId
),
child:
Consumer
<
LeaveApplicationDetailsProvider
>(
builder:
(
context
,
provider
,
child
)
{
return
Scaffold
(
appBar:
AppBar
(
automaticallyImplyLeading:
false
,
backgroundColor:
const
Color
(
0xFFFFFFFF
),
title:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
children:
[
InkResponse
(
onTap:
()
=>
Navigator
.
pop
(
context
,
true
),
child:
SvgPicture
.
asset
(
"assets/svg/appbar_back_button.svg"
,
height:
25
,
),
),
const
SizedBox
(
width:
10
),
InkResponse
(
onTap:
()
=>
Navigator
.
pop
(
context
,
true
),
child:
Text
(
"Leave Application Details"
,
style:
TextStyle
(
fontSize:
18
,
height:
1.1
,
fontFamily:
"Plus Jakarta Sans"
,
fontWeight:
FontWeight
.
w600
,
color:
AppColors
.
semi_black
,
),
),
),
],
),
),
backgroundColor:
const
Color
(
0xFFF6F6F8
),
body:
Builder
(
builder:
(
context
)
{
if
(
provider
.
isLoading
)
{
return
const
Center
(
child:
CircularProgressIndicator
(
color:
Colors
.
blue
));
}
if
(
provider
.
errorMessage
!=
null
)
{
return
Center
(
child:
Text
(
provider
.
errorMessage
!));
}
if
(
provider
.
response
?.
requestDetails
==
null
)
{
return
const
Center
(
child:
Text
(
"No details found"
));
}
final
details
=
provider
.
response
!.
requestDetails
!;
/// Screen content
return
SingleChildScrollView
(
padding:
const
EdgeInsets
.
all
(
16.0
),
child:
Column
(
children:
[
Card
(
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
),
elevation:
2
,
child:
Padding
(
padding:
const
EdgeInsets
.
all
(
10.0
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
/// Header with status
Container
(
margin:
const
EdgeInsets
.
only
(
bottom:
0.5
),
padding:
const
EdgeInsets
.
symmetric
(
vertical:
10
,
horizontal:
2
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
12
),
),
child:
Row
(
children:
[
/// Left Avatar
Container
(
height:
48
,
width:
48
,
decoration:
BoxDecoration
(
shape:
BoxShape
.
circle
,
color:
const
Color
(
0xFFEDF8FF
),
// icon bg
),
child:
Center
(
child:
SvgPicture
.
asset
(
height:
28
,
width:
28
,
"assets/svg/hrm/leaveApplication.svg"
,
// Use appropriate icon
fit:
BoxFit
.
contain
,
),
),
),
const
SizedBox
(
width:
12
),
/// Middle text
Expanded
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
details
.
leaveType
??
"-"
,
style:
TextStyle
(
decoration:
TextDecoration
.
underline
,
decorationStyle:
TextDecorationStyle
.
dotted
,
decorationColor:
AppColors
.
grey_thick
,
height:
1.2
,
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
color:
AppColors
.
semi_black
,
),
),
const
SizedBox
(
height:
2
),
Text
(
"Applied:
${details.appliedDate ?? "-"}
"
,
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
color:
AppColors
.
app_blue
,
),
),
],
),
),
/// Right side status badge
Container
(
height:
30
,
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
5
,
vertical:
1
),
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
8
),
color:
_getStatusBackgroundColor
(
details
.
status
),
),
child:
Center
(
child:
Text
(
details
.
status
??
"-"
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
fontFamily:
"JakartaMedium"
,
fontSize:
12
,
color:
_getStatusTextColor
(
details
.
status
),
),
),
),
),
],
),
),
/// Leave Details
Padding
(
padding:
const
EdgeInsets
.
all
(
8.0
),
child:
Column
(
children:
[
_buildSectionHeader
(
"Leave Details"
),
_buildDetailTile
(
"Application ID"
,
details
.
id
),
_buildDetailTile
(
"Applied Date"
,
details
.
appliedDate
),
_buildDetailTile
(
"Leave Type"
,
details
.
leaveType
),
_buildDateRangeTile
(
"Leave Period"
,
details
.
fromDate
,
details
.
toDate
),
_buildTimeRangeTile
(
"Time Period"
,
details
.
fromTime
,
details
.
toTime
),
_buildDetailTile
(
"Reason"
,
details
.
reason
),
/// Approval Details
_buildSectionHeader
(
"Approval Details"
),
_buildDetailTile
(
"Requested To"
,
details
.
requestedTo
),
_buildDetailTile
(
"Approved By"
,
details
.
approvedBy
),
_buildDetailTile
(
"Approved Date"
,
details
.
approvedDate
),
_buildDetailTile
(
"Approval Remarks"
,
details
.
approvalRemarks
),
/// Additional Information
_buildSectionHeader
(
"Additional Information"
),
_buildDetailTile
(
"Status"
,
details
.
status
),
_buildDetailTile
(
"From Time"
,
details
.
fromTime
),
_buildDetailTile
(
"To Time"
,
details
.
toTime
),
],
),
),
],
),
),
),
const
SizedBox
(
height:
30
),
],
),
);
},
),
);
},
),
);
}
/// Reusable Row Widget for details
Widget
_buildDetailTile
(
String
label
,
String
?
value
)
{
return
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
3
),
child:
Row
(
children:
[
Expanded
(
flex:
6
,
child:
Text
(
label
,
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
color:
AppColors
.
semi_black
,
),
),
),
Expanded
(
flex:
0
,
child:
Text
(
value
??
"-"
,
style:
const
TextStyle
(
fontSize:
14
,
color:
Color
(
0xff818181
),
fontWeight:
FontWeight
.
w400
,
),
),
),
],
),
);
}
/// For date range display
Widget
_buildDateRangeTile
(
String
label
,
String
?
fromDate
,
String
?
toDate
)
{
return
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
3
),
child:
Row
(
children:
[
Expanded
(
flex:
6
,
child:
Text
(
label
,
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
color:
AppColors
.
semi_black
,
),
),
),
Expanded
(
flex:
0
,
child:
Text
(
'
${fromDate ?? "-"}
to
${toDate ?? "-"}
'
,
style:
const
TextStyle
(
fontSize:
14
,
color:
Color
(
0xff818181
),
fontWeight:
FontWeight
.
w400
,
),
),
),
],
),
);
}
/// For time range display
Widget
_buildTimeRangeTile
(
String
label
,
String
?
fromTime
,
String
?
toTime
)
{
if
((
fromTime
==
null
||
fromTime
.
isEmpty
)
&&
(
toTime
==
null
||
toTime
.
isEmpty
))
{
return
const
SizedBox
.
shrink
();
// Hide if no time data
}
return
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
3
),
child:
Row
(
children:
[
Expanded
(
flex:
6
,
child:
Text
(
label
,
style:
const
TextStyle
(
fontSize:
14
,
color:
Color
(
0xff2D2D2D
),
fontStyle:
FontStyle
.
normal
,
fontFamily:
"Plus Jakarta Sans"
,
fontWeight:
FontWeight
.
w400
,
),
),
),
Expanded
(
flex:
0
,
child:
Text
(
'
${fromTime ?? "-"}
to
${toTime ?? "-"}
'
,
style:
const
TextStyle
(
fontSize:
14
,
color:
Color
(
0xff818181
),
fontWeight:
FontWeight
.
w400
,
),
),
),
],
),
);
}
/// Section header with dotted line
Widget
_buildSectionHeader
(
String
title
)
{
return
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
8
),
child:
Row
(
children:
[
Text
(
title
,
style:
TextStyle
(
fontSize:
14
,
fontFamily:
"JakartaSemiBold"
,
),
),
const
SizedBox
(
width:
10
),
Expanded
(
child:
DottedLine
(
dashGapLength:
4
,
dashGapColor:
Colors
.
white
,
dashColor:
AppColors
.
grey_semi
,
dashLength:
2
,
lineThickness:
0.5
,
),
),
],
),
);
}
/// Status background color
Color
_getStatusBackgroundColor
(
String
?
status
)
{
switch
(
status
?.
toLowerCase
())
{
case
'approved'
:
return
AppColors
.
approved_bg_color
;
case
'rejected'
:
return
AppColors
.
rejected_bg_color
;
case
'requested'
:
default
:
return
AppColors
.
requested_bg_color
;
}
}
/// Status text color
Color
_getStatusTextColor
(
String
?
status
)
{
switch
(
status
?.
toLowerCase
())
{
case
'approved'
:
return
AppColors
.
approved_text_color
;
case
'rejected'
:
return
AppColors
.
rejected_text_color
;
case
'requested'
:
default
:
return
AppColors
.
requested_text_color
;
}
}
}
\ No newline at end of file
lib/screens/hrm/LeaveApplicationScreen.dart
View file @
f6fbe101
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_svg/flutter_svg.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:intl/intl.dart'
;
import
'package:provider/provider.dart'
;
import
'../../Notifiers/hrmProvider/leaveApplicationListProvider.dart'
;
import
'../../Utils/app_colors.dart'
;
import
'../../Utils/commonWidgets.dart'
;
import
'../commonDateRangeFilter.dart'
;
import
'AddLeaveRequestScreen.dart'
;
import
'LeaveApplicationDetailScreen.dart'
;
class
LeaveApplicationScreen
extends
StatefulWidget
{
class
LeaveApplication
List
Screen
extends
StatefulWidget
{
const
LeaveApplicationScreen
({
Key
?
key
})
:
super
(
key:
key
);
const
LeaveApplication
List
Screen
({
super
.
key
}
);
@override
@override
State
<
LeaveApplicationScreen
>
createState
()
=>
_LeaveApplicationScreenState
();
State
<
LeaveApplication
List
Screen
>
createState
()
=>
_LeaveApplication
List
ScreenState
();
}
}
class
_LeaveApplicationScreenState
extends
State
<
LeaveApplicationScreen
>
{
class
_LeaveApplicationListScreenState
extends
State
<
LeaveApplicationListScreen
>
{
final
TextEditingController
_reasonController
=
TextEditingController
();
// @override
DateTime
?
_startDate
;
// void initState() {
DateTime
?
_endDate
;
// super.initState();
// WidgetsBinding.instance.addPostFrameCallback((_) {
Future
<
void
>
_pickDate
({
required
bool
isStart
})
async
{
// final provider = Provider.of<LeaveApplicationListProvider>(context, listen: false);
final
DateTime
?
picked
=
await
showDatePicker
(
// provider.fetchLeaveApplications(context);
context:
context
,
// });
initialDate:
DateTime
.
now
(),
// }
firstDate:
DateTime
(
2020
),
lastDate:
DateTime
(
2100
),
);
if
(
picked
!=
null
)
{
setState
(()
{
if
(
isStart
)
{
_startDate
=
picked
;
}
else
{
_endDate
=
picked
;
}
});
}
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
return
ChangeNotifierProvider
(
appBar:
AppBar
(
create:
(
_
)
{
automaticallyImplyLeading:
false
,
final
provider
=
LeaveApplicationListProvider
();
backgroundColor:
Colors
.
white
,
Future
.
microtask
(()
{
title:
Row
(
provider
.
fetchLeaveApplications
(
context
);
children:
[
});
InkResponse
(
return
provider
;
onTap:
()
=>
Navigator
.
pop
(
context
,
true
),
},
child:
SvgPicture
.
asset
(
builder:
(
context
,
child
)
{
"assets/svg/appbar_back_button.svg"
,
return
Consumer
<
LeaveApplicationListProvider
>(
height:
25
,
builder:
(
context
,
provider
,
child
)
{
),
return
Scaffold
(
),
appBar:
appbar2New
(
const
SizedBox
(
width:
10
),
context
,
const
Text
(
"Leave Application List"
,
"Leave Application"
,
provider
.
resetForm
,
style:
TextStyle
(
Row
(
fontSize:
18
,
children:
[
fontFamily:
"Plus Jakarta Sans"
,
InkResponse
(
fontWeight:
FontWeight
.
w600
,
onTap:
()
async
{
color:
Colors
.
black87
,
var
cf
=
Commondaterangefilter
();
),
var
result
=
await
cf
.
showFilterBottomSheet
(
context
);
),
if
(
result
!=
null
)
{
],
var
dateRange
=
result
[
'dateRange'
]
as
DateTimeRange
?;
),
var
formatted
=
result
[
'formatted'
]
as
List
<
String
>;
),
if
(
formatted
.
isNotEmpty
)
{
body:
Padding
(
provider
.
setDateRangeFilter
(
"Custom"
,
customRange:
dateRange
);
padding:
const
EdgeInsets
.
all
(
16.0
),
provider
.
fetchLeaveApplications
(
child:
Column
(
context
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
dateRange:
"Custom"
,
children:
[
customRange:
dateRange
,
Align
(
);
alignment:
Alignment
.
topRight
,
}
child:
Text
(
}
"Dummy Screen !"
,
},
style:
TextStyle
(
child:
SvgPicture
.
asset
(
"assets/svg/filter_ic.svg"
,
height:
25
),
fontSize:
10
,
),
height:
1
,
],
fontWeight:
FontWeight
.
bold
,
),
),
),
const
Text
(
"Apply for Leave"
,
style:
TextStyle
(
fontSize:
20
,
fontWeight:
FontWeight
.
bold
,
),
),
const
SizedBox
(
height:
20
),
TextField
(
controller:
_reasonController
,
decoration:
const
InputDecoration
(
labelText:
"Reason for Leave"
,
border:
OutlineInputBorder
(),
),
maxLines:
3
,
),
const
SizedBox
(
height:
20
),
Row
(
children:
[
Expanded
(
child:
ElevatedButton
(
onPressed:
()
=>
_pickDate
(
isStart:
true
),
child:
Text
(
_startDate
==
null
?
"Select Start Date"
:
"Start:
${_startDate!.toLocal()}
"
.
split
(
' '
)[
0
]),
),
),
0xFFFFFFFF
,
),
),
const
SizedBox
(
width:
10
),
backgroundColor:
const
Color
(
0xFFF6F6F8
),
Expanded
(
body:
Column
(
child:
ElevatedButton
(
children:
[
onPressed:
()
=>
_pickDate
(
isStart:
false
),
/// Filter chips (if you want visible filter indicators)
child:
Text
(
_endDate
==
null
// if (provider.selectedStatus != "All" || provider.selectedDateRange != "This Month")
?
"Select End Date"
// Container(
:
"End:
${_endDate!.toLocal()}
"
.
split
(
' '
)[
0
]),
// padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
// color: Colors.white,
// child: Row(
// children: [
// if (provider.selectedStatus != "All")
// Chip(
// label: Text('Status: ${provider.selectedStatus}'),
// onDeleted: () {
// provider.setStatusFilter("All");
// provider.fetchLeaveApplications(context);
// },
// ),
// if (provider.selectedDateRange != "This Month")
// Chip(
// label: Text('Date: ${provider.selectedDateRange}'),
// onDeleted: () {
// provider.setDateRangeFilter("This Month");
// provider.fetchLeaveApplications(context);
// },
// ),
// ],
// ),
// ),
/// Leave application list
Expanded
(
child:
Builder
(
builder:
(
context
)
{
if
(
provider
.
isLoading
)
{
return
const
Center
(
child:
CircularProgressIndicator
(
color:
Colors
.
blue
));
}
if
(
provider
.
errorMessage
!=
null
)
{
return
Center
(
child:
Text
(
provider
.
errorMessage
!));
}
if
(
provider
.
response
?.
requestList
==
null
||
provider
.
response
!.
requestList
!.
isEmpty
)
{
return
const
Center
(
child:
Text
(
"No leave applications found"
));
}
final
list
=
provider
.
response
!.
requestList
!;
return
ListView
.
builder
(
padding:
const
EdgeInsets
.
all
(
8
),
itemCount:
list
.
length
,
itemBuilder:
(
context
,
index
)
{
final
item
=
list
[
index
];
// Parse the full string into a DateTime object
DateTime
parsedFromDate
=
DateFormat
(
"dd MMM yyyy, hh:mm a"
).
parse
(
item
.
fromPeriod
.
toString
());
String
dateFromMonth
=
DateFormat
(
"dd MMM"
).
format
(
parsedFromDate
);
// Parse the full string into a DateTime object
DateTime
parsedToDate
=
DateFormat
(
"dd MMM yyyy, hh:mm a"
).
parse
(
item
.
toPeriod
.
toString
());
String
dateToMonth
=
DateFormat
(
"dd MMM yyyy"
).
format
(
parsedToDate
);
return
InkWell
(
borderRadius:
BorderRadius
.
circular
(
16
),
onTap:
()
{
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
LeaveApplicationDetailScreen
(
leaveRequestId:
item
.
id
.
toString
(),
),
),
).
then
((
_
)
{
provider
.
fetchLeaveApplications
(
context
);
});
},
child:
Container
(
margin:
const
EdgeInsets
.
symmetric
(
horizontal:
8.5
,
vertical:
5
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
12
,
vertical:
12
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
),
),
child:
Row
(
children:
[
/// Left Status Circle
Container
(
height:
48
,
width:
48
,
padding:
const
EdgeInsets
.
all
(
8.0
),
decoration:
BoxDecoration
(
color:
_getStatusBackgroundColor
(
item
.
status
),
shape:
BoxShape
.
circle
,
),
child:
Center
(
child:
Text
(
_getStatusInitials
(
item
.
status
),
style:
TextStyle
(
color:
_getStatusTextColor
(
item
.
status
),
fontSize:
14
,
fontWeight:
FontWeight
.
bold
,
),
),
),
),
const
SizedBox
(
width:
12
),
/// Middle Section - Leave Details
Expanded
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
item
.
leaveType
??
"-"
,
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
color:
AppColors
.
semi_black
,
),
),
const
SizedBox
(
height:
4
),
Row
(
children:
[
Text
(
dateFromMonth
??
"-"
,
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
color:
AppColors
.
grey_semi
,
),
),
Text
(
" -
${dateToMonth}
"
??
"-"
,
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
color:
AppColors
.
grey_semi
,
),
),
],
),
// const SizedBox(height: 2),
// Text(
// "Period: ${item.fromPeriod ?? "-"} to ${item.toPeriod ?? "-"}",
// style: const TextStyle(
// fontSize: 12.5,
// color: Color(0xff818181),
// fontFamily: "Plus Jakarta Sans",
// ),
// ),
],
),
),
// /// Right Status
// Container(
// padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
// decoration: BoxDecoration(
// color: _getStatusBackgroundColor(item.status),
// borderRadius: BorderRadius.circular(10),
// ),
// child: Text(
// item.status ?? "-",
// style: TextStyle(
// fontFamily: "JakartaMedium",
// fontSize: 13,
// color: _getStatusTextColor(item.status),
// ),
// ),
// ),
],
),
),
);
},
);
},
),
)
],
),
floatingActionButtonLocation:
FloatingActionButtonLocation
.
centerFloat
,
floatingActionButton:
InkResponse
(
onTap:
()
{
HapticFeedback
.
selectionClick
();
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
_
)
=>
ChangeNotifierProvider
(
create:
(
_
)
=>
LeaveApplicationListProvider
(),
child:
AddLeaveRequest
(
pageTitleName:
"Add Leave Request"
),
),
),
).
then
((
_
)
{
provider
.
fetchLeaveApplications
(
context
);
});
// show add bill screen here
},
child:
Container
(
height:
45
,
alignment:
Alignment
.
center
,
margin:
EdgeInsets
.
symmetric
(
horizontal:
20
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
5
),
decoration:
BoxDecoration
(
color:
AppColors
.
app_blue
,
borderRadius:
BorderRadius
.
circular
(
15
),
),
child:
Text
(
"Add Leave Request"
,
style:
TextStyle
(
fontSize:
15
,
fontFamily:
"JakartaMedium"
,
color:
Colors
.
white
,
),
),
),
),
),
],
),
const
Spacer
(),
SizedBox
(
width:
double
.
infinity
,
child:
ElevatedButton
(
onPressed:
()
{
// Handle submission logic here
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
"Leave application submitted"
)),
);
},
child:
const
Text
(
"Submit Application"
),
),
),
)
,
)
;
]
,
}
,
)
,
)
;
)
,
}
,
);
);
}
}
}
/// Get status background color
Color
_getStatusBackgroundColor
(
String
?
status
)
{
switch
(
status
?.
toLowerCase
())
{
case
'approved'
:
return
AppColors
.
approved_bg_color
;
case
'rejected'
:
return
AppColors
.
rejected_bg_color
;
case
'requested'
:
default
:
return
AppColors
.
requested_bg_color
;
}
}
/// Get status text color
Color
_getStatusTextColor
(
String
?
status
)
{
switch
(
status
?.
toLowerCase
())
{
case
'approved'
:
return
AppColors
.
approved_text_color
;
case
'rejected'
:
return
AppColors
.
rejected_text_color
;
case
'requested'
:
default
:
return
AppColors
.
requested_text_color
;
}
}
/// Get status initials
String
_getStatusInitials
(
String
?
status
)
{
switch
(
status
?.
toLowerCase
())
{
case
'approved'
:
return
"A"
;
case
'rejected'
:
return
"R"
;
case
'requested'
:
default
:
return
"P"
;
// Pending
}
}
}
\ No newline at end of file
lib/screens/hrm/OrganizationStructureScreen.dart
0 → 100644
View file @
f6fbe101
import
'package:flutter/material.dart'
;
class
OrganizationStructureScreen
extends
StatelessWidget
{
final
List
<
Department
>
departments
=
[
Department
(
name:
"Engineering"
,
teams:
[
Team
(
name:
"Mobile Team"
,
members:
[
"Mohit"
,
"Srinivas"
,
]),
Team
(
name:
"Backend Team"
,
members:
[
"Dheeraj"
,
"Satya"
,
"Sneha"
]),
],
),
Department
(
name:
"Sales & Marketing"
,
teams:
[
Team
(
name:
"Digital Marketing"
,
members:
[
"Kiran"
,
"Priya"
]),
Team
(
name:
"Field Sales"
,
members:
[
"Raj"
,
"Anjali"
]),
],
),
Department
(
name:
"HR & Admin"
,
teams:
[
Team
(
name:
"Recruitment"
,
members:
[
"Naresh"
]),
Team
(
name:
"Operations"
,
members:
[
"Suresh"
,
"Divya"
]),
],
),
];
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
appBar:
AppBar
(
title:
const
Text
(
"Organization Structure"
)),
body:
ListView
.
builder
(
padding:
const
EdgeInsets
.
all
(
16
),
itemCount:
departments
.
length
,
itemBuilder:
(
context
,
deptIndex
)
{
final
dept
=
departments
[
deptIndex
];
return
Card
(
margin:
const
EdgeInsets
.
only
(
bottom:
16
),
elevation:
2
,
child:
ExpansionTile
(
title:
Text
(
"
${dept.name}
not ready"
,
style:
const
TextStyle
(
fontSize:
18
,
fontWeight:
FontWeight
.
bold
),
),
children:
dept
.
teams
.
map
((
team
)
{
return
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
team
.
name
,
style:
const
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
w600
),
),
const
SizedBox
(
height:
4
),
Wrap
(
spacing:
8
,
children:
team
.
members
.
map
((
member
)
{
return
Chip
(
label:
Text
(
member
),
backgroundColor:
Colors
.
blue
.
shade50
,
);
}).
toList
(),
),
const
SizedBox
(
height:
8
),
],
),
);
}).
toList
(),
),
);
},
),
);
}
}
class
Department
{
final
String
name
;
final
List
<
Team
>
teams
;
Department
({
required
this
.
name
,
required
this
.
teams
});
}
class
Team
{
final
String
name
;
final
List
<
String
>
members
;
Team
({
required
this
.
name
,
required
this
.
members
});
}
lib/screens/hrm/RewardListScreen.dart
View file @
f6fbe101
...
@@ -47,27 +47,27 @@ class _RewardListScreenState extends State<RewardListScreen> {
...
@@ -47,27 +47,27 @@ class _RewardListScreenState extends State<RewardListScreen> {
),
),
],
],
),
),
actions:
[
//
actions: [
InkResponse
(
//
InkResponse(
onTap:
()
{
//
onTap: () {
Navigator
.
push
(
//
Navigator.push(
context
,
//
context,
MaterialPageRoute
(
//
MaterialPageRoute(
builder:
(
context
)
=>
RewardSearchScreen
(),
//
builder: (context) => RewardSearchScreen(),
settings:
const
RouteSettings
(
//
settings: const RouteSettings(
name:
'AddLiveAttendanceScreen'
,
//
name: 'AddLiveAttendanceScreen',
),
//
),
),
//
),
).
then
((
_
)
{
//
).then((_) {
});
//
});
},
//
},
child:
SvgPicture
.
asset
(
//
child: SvgPicture.asset(
"assets/svg/search_ic.svg"
,
//
"assets/svg/search_ic.svg",
height:
25
,
//
height: 25,
),
//
),
),
//
),
const
SizedBox
(
width:
20
),
//
const SizedBox(width: 20),
],
//
],
),
),
backgroundColor:
Color
(
0xFFF6F6F8
),
backgroundColor:
Color
(
0xFFF6F6F8
),
...
@@ -95,37 +95,65 @@ class _RewardListScreenState extends State<RewardListScreen> {
...
@@ -95,37 +95,65 @@ class _RewardListScreenState extends State<RewardListScreen> {
children:
[
children:
[
/// --- Top Summary Cards ---
/// --- Top Summary Cards ---
Container
(
Stack
(
height:
110
,
children:
[
width:
double
.
infinity
,
Container
(
padding:
const
EdgeInsets
.
all
(
18
),
height:
110
,
decoration:
BoxDecoration
(
width:
double
.
infinity
,
color:
const
Color
(
0xffd9ffd6
),
padding:
const
EdgeInsets
.
all
(
18
),
borderRadius:
BorderRadius
.
circular
(
18
),
decoration:
BoxDecoration
(
),
color:
const
Color
(
0xffd9ffd6
),
child:
Column
(
borderRadius:
BorderRadius
.
circular
(
18
),
crossAxisAlignment:
CrossAxisAlignment
.
start
,
),
mainAxisAlignment:
MainAxisAlignment
.
center
,
child:
Column
(
children:
[
crossAxisAlignment:
CrossAxisAlignment
.
start
,
Text
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
"₹
${achieved}
"
,
// Achieved Amount from response
children:
[
style:
const
TextStyle
(
Text
(
fontSize:
20
,
"₹
${achieved}
"
,
// Achieved Amount from response
color:
Color
(
0xff0D9C00
),
style:
const
TextStyle
(
fontStyle:
FontStyle
.
normal
,
fontSize:
20
,
fontWeight:
FontWeight
.
w500
),
color:
Color
(
0xff0D9C00
),
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
w500
,
),
),
const
SizedBox
(
height:
10
),
const
Text
(
"Achievement Amount"
,
style:
TextStyle
(
fontSize:
14
,
color:
Color
(
0xff2D2D2D
),
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
w400
,
),
),
],
),
),
const
SizedBox
(
height:
10
),
),
const
Text
(
"Achievement Amount"
,
// Positioned SVG Icon
style:
TextStyle
(
Positioned
(
fontSize:
14
,
bottom:
8
,
color:
Color
(
0xff2D2D2D
),
right:
12
,
fontStyle:
FontStyle
.
normal
,
child:
Container
(
fontWeight:
FontWeight
.
w400
),
height:
42
,
width:
42
,
decoration:
BoxDecoration
(
shape:
BoxShape
.
circle
,
color:
const
Color
(
0xA0FFFFFF
),
// icon bg
),
child:
Center
(
child:
SvgPicture
.
asset
(
height:
25
,
width:
25
,
"assets/svg/hrm/achievement_ic.svg"
,
fit:
BoxFit
.
contain
,
),
),
),
),
]
,
)
,
)
,
]
,
),
),
const
SizedBox
(
height:
12
),
const
SizedBox
(
height:
12
),
...
@@ -139,24 +167,50 @@ class _RewardListScreenState extends State<RewardListScreen> {
...
@@ -139,24 +167,50 @@ class _RewardListScreenState extends State<RewardListScreen> {
color:
const
Color
(
0xffe8ddff
),
color:
const
Color
(
0xffe8ddff
),
borderRadius:
BorderRadius
.
circular
(
16
),
borderRadius:
BorderRadius
.
circular
(
16
),
),
),
child:
Column
(
child:
Stack
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
children:
[
Text
(
Column
(
"₹
${disbursed}
"
,
// Disbursed Amount
crossAxisAlignment:
CrossAxisAlignment
.
start
,
style:
const
TextStyle
(
children:
[
fontSize:
20
,
Text
(
color:
Color
(
0xff493272
),
"₹
${disbursed}
"
,
// Disbursed Amount
fontStyle:
FontStyle
.
normal
,
style:
const
TextStyle
(
fontWeight:
FontWeight
.
w500
),
fontSize:
20
,
),
color:
Color
(
0xff493272
),
const
SizedBox
(
height:
8
),
fontWeight:
FontWeight
.
w500
,
const
Text
(
"Disbursed Amount"
,
),
style:
TextStyle
(
),
const
SizedBox
(
height:
8
),
const
Text
(
"Disbursed
\n
Amount"
,
style:
TextStyle
(
fontSize:
14
,
fontSize:
14
,
color:
Color
(
0xff2D2D2D
),
color:
Color
(
0xff2D2D2D
),
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
w400
,
fontWeight:
FontWeight
.
w400
)),
),
),
],
),
Positioned
(
bottom:
2
,
right:
2
,
child:
Container
(
height:
42
,
width:
42
,
decoration:
BoxDecoration
(
shape:
BoxShape
.
circle
,
color:
const
Color
(
0xA0FFFFFF
),
// icon bg
),
child:
Center
(
child:
SvgPicture
.
asset
(
height:
25
,
width:
25
,
"assets/svg/hrm/location_ic.svg"
,
fit:
BoxFit
.
contain
,
),
),
),
),
],
],
),
),
),
),
...
@@ -170,26 +224,49 @@ class _RewardListScreenState extends State<RewardListScreen> {
...
@@ -170,26 +224,49 @@ class _RewardListScreenState extends State<RewardListScreen> {
color:
const
Color
(
0xfffffbc3
),
color:
const
Color
(
0xfffffbc3
),
borderRadius:
BorderRadius
.
circular
(
16
),
borderRadius:
BorderRadius
.
circular
(
16
),
),
),
child:
Column
(
child:
Stack
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
children:
[
Text
(
Column
(
"₹
${balance}
"
,
// Balance Amount
crossAxisAlignment:
CrossAxisAlignment
.
start
,
style:
const
TextStyle
(
children:
[
fontSize:
18
,
Text
(
color:
Color
(
0xff605C00
),
"₹
${balance}
"
,
// Balance Amount
fontFamily:
"Plus Jakarta Sans"
,
style:
const
TextStyle
(
fontStyle:
FontStyle
.
normal
,
fontSize:
18
,
fontWeight:
FontWeight
.
w500
),
color:
Color
(
0xff605C00
),
),
),
const
SizedBox
(
height:
8
),
),
const
Text
(
"Balance Amount"
,
const
SizedBox
(
height:
8
),
style:
TextStyle
(
const
Text
(
"Balance
\n
Amount"
,
style:
TextStyle
(
fontSize:
14
,
fontSize:
14
,
color:
Color
(
0xff2D2D2D
),
color:
Color
(
0xff2D2D2D
),
fontFamily:
"Plus Jakarta Sans"
,
fontWeight:
FontWeight
.
w400
,
fontStyle:
FontStyle
.
normal
,
),
fontWeight:
FontWeight
.
w400
)),
),
],
),
Positioned
(
bottom:
2
,
right:
2
,
child:
Container
(
height:
42
,
width:
42
,
decoration:
BoxDecoration
(
shape:
BoxShape
.
circle
,
color:
const
Color
(
0xA0FFFFFF
),
// icon bg
),
child:
Center
(
child:
SvgPicture
.
asset
(
height:
25
,
width:
25
,
"assets/svg/hrm/ballance_ic.svg"
,
fit:
BoxFit
.
contain
,
),
),
),
),
],
],
),
),
),
),
...
@@ -303,20 +380,19 @@ class _RewardListScreenState extends State<RewardListScreen> {
...
@@ -303,20 +380,19 @@ class _RewardListScreenState extends State<RewardListScreen> {
const
Text
(
const
Text
(
"Amount Details"
,
"Amount Details"
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
15
,
fontSize:
14
,
color:
Color
(
0xff2D2D2D
),
fontFamily:
"JakartaSemiBold"
,
fontFamily:
"Plus Jakarta Sans"
,
),
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
w600
),
),
),
const
SizedBox
(
width:
10
),
const
SizedBox
(
width:
10
),
Expanded
(
Expanded
(
child:
DottedLine
(
child:
DottedLine
(
dashLength:
4
,
dashGapLength:
4
,
dashGapLength:
2
,
dashGapColor:
Colors
.
white
,
lineThickness:
1
,
dashColor:
AppColors
.
grey_semi
,
dashColor:
Color
(
0xff999999
),
dashLength:
2
,
)
lineThickness:
0.5
,
),
),
),
],
],
),
),
...
@@ -337,20 +413,19 @@ class _RewardListScreenState extends State<RewardListScreen> {
...
@@ -337,20 +413,19 @@ class _RewardListScreenState extends State<RewardListScreen> {
const
Text
(
const
Text
(
"Employee Details"
,
"Employee Details"
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
15
,
fontSize:
14
,
color:
Color
(
0xff2D2D2D
),
fontFamily:
"JakartaSemiBold"
,
fontFamily:
"Plus Jakarta Sans"
,
),
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
w600
),
),
),
const
SizedBox
(
width:
10
),
const
SizedBox
(
width:
10
),
Expanded
(
Expanded
(
child:
DottedLine
(
child:
DottedLine
(
dashLength:
4
,
dashGapLength:
4
,
dashGapLength:
2
,
dashGapColor:
Colors
.
white
,
lineThickness:
1
,
dashColor:
AppColors
.
grey_semi
,
dashColor:
Color
(
0xff999999
),
dashLength:
2
,
)
lineThickness:
0.5
,
),
),
),
],
],
),
),
...
@@ -369,20 +444,19 @@ class _RewardListScreenState extends State<RewardListScreen> {
...
@@ -369,20 +444,19 @@ class _RewardListScreenState extends State<RewardListScreen> {
child:
Row
(
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
children:
[
Text
(
key
,
style:
const
TextStyle
(
Text
(
key
,
style:
TextStyle
(
fontSize:
14
,
fontFamily:
"JakartaRegular"
,
color:
Color
(
0xff2D2D2D
),
fontSize:
14
,
fontFamily:
"Plus Jakarta Sans"
,
color:
AppColors
.
semi_black
,
fontStyle:
FontStyle
.
normal
,
),
fontWeight:
FontWeight
.
w400
)
),
),
Text
(
value
,
style:
const
TextStyle
(
Text
(
fontSize:
14
,
value
,
color:
Color
(
0xff2D2D2D
),
style:
const
TextStyle
(
font
Family:
"Plus Jakarta Sans"
,
font
Size:
14
,
fontStyle:
FontStyle
.
normal
,
color:
Color
(
0xFF818181
)
,
fontWeight:
FontWeight
.
w400
)
)
,
),
),
],
],
),
),
...
...
lib/screens/hrm/TourExpensesDetailsScreen.dart
View file @
f6fbe101
...
@@ -8,17 +8,20 @@ import '../../Utils/app_colors.dart';
...
@@ -8,17 +8,20 @@ import '../../Utils/app_colors.dart';
import
'../finance/FileViewer.dart'
;
import
'../finance/FileViewer.dart'
;
class
TourExpensesDetailsScreen
extends
State
less
Widget
{
class
TourExpensesDetailsScreen
extends
State
ful
Widget
{
final
String
tourBillId
;
final
String
tourBillId
;
const
TourExpensesDetailsScreen
({
Key
?
key
,
required
this
.
tourBillId
})
const
TourExpensesDetailsScreen
({
Key
?
key
,
required
this
.
tourBillId
})
:
super
(
key:
key
);
:
super
(
key:
key
);
@override
State
<
TourExpensesDetailsScreen
>
createState
()
=>
_TourExpensesDetailsScreenState
();
}
class
_TourExpensesDetailsScreenState
extends
State
<
TourExpensesDetailsScreen
>{
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
ChangeNotifierProvider
(
return
ChangeNotifierProvider
(
create:
(
_
)
=>
TourExpensesDetailsProvider
()
create:
(
_
)
=>
TourExpensesDetailsProvider
()
..
fetchTourExpensesDetails
(
context
,
tourBillId
),
..
fetchTourExpensesDetails
(
context
,
widget
.
tourBillId
),
child:
Scaffold
(
child:
Scaffold
(
appBar:
AppBar
(
appBar:
AppBar
(
automaticallyImplyLeading:
false
,
automaticallyImplyLeading:
false
,
...
@@ -66,17 +69,22 @@ class TourExpensesDetailsScreen extends StatelessWidget {
...
@@ -66,17 +69,22 @@ class TourExpensesDetailsScreen extends StatelessWidget {
if
(
response
==
null
)
{
if
(
response
==
null
)
{
return
const
Center
(
child:
Text
(
"No data available"
));
return
const
Center
(
child:
Text
(
"No data available"
));
}
}
debugPrint
(
"==================requestDetails:
${response.requestDetails?.approvalStatus}
"
);
return
SingleChildScrollView
(
return
SingleChildScrollView
(
child:
Column
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
children:
[
/// Header Card at the very top
/// Header Card at the very top
_expenseHeaderCard
(
_expenseHeaderCard
(
title:
response
.
requestDetails
?.
placeOfVisit
??
"Tour"
,
title:
response
.
requestDetails
?.
placeOfVisit
??
"Tour"
,
date:
response
.
tourExpenses
?.
fromDate
??
"-"
,
date:
response
.
tourExpenses
?.
fromDate
??
"-"
,
status:
response
.
requestDetails
?.
approvalStatus
??
"-"
,
status:
(
response
.
requestDetails
?.
approvalStatus
?.
isNotEmpty
??
false
)
?
response
.
requestDetails
!.
approvalStatus
!
:
"No Status"
,
details:
[
details:
[
{
"key"
:
"TL Pending Approval Amount"
,
"value"
:
"-"
},
{
"key"
:
"TL Pending Approval Amount"
,
"value"
:
"-"
},
{
"key"
:
"Total Approved Amount"
,
"value"
:
response
.
tourExpenses
?.
appliedAmount
??
"-"
},
{
"key"
:
"Total Approved Amount"
,
"value"
:
response
.
tourExpenses
?.
appliedAmount
??
"-"
},
...
@@ -167,17 +175,12 @@ class TourExpensesDetailsScreen extends StatelessWidget {
...
@@ -167,17 +175,12 @@ class TourExpensesDetailsScreen extends StatelessWidget {
debugPrint
(
"Open:
${t.imageDirFilePath}
"
);
debugPrint
(
"Open:
${t.imageDirFilePath}
"
);
//Fileviewer(fileName: "", fileUrl: t.imageDirFilePath.toString())
//Fileviewer(fileName: "", fileUrl: t.imageDirFilePath.toString())
showDialog
(
Navigator
.
push
(
context:
context
,
context
,
builder:
(
_
)
=>
Dialog
(
MaterialPageRoute
(
shape:
RoundedRectangleBorder
(
builder:
borderRadius:
BorderRadius
.
circular
(
12
),
(
context
)
=>
Image
.
network
(
t
.
imageDirFilePath
.
toString
()),
),
// Fileviewer(fileName: label, fileUrl: "assets/images/capa.svg"),
child:
ClipRRect
(
borderRadius:
BorderRadius
.
circular
(
12
),
child:
Image
.
network
(
t
.
imageDirFilePath
.
toString
())
),
),
),
);
);
},
},
...
...
lib/screens/hrm/TourExpensesListScreen.dart
View file @
f6fbe101
...
@@ -129,20 +129,18 @@ class _TourExpensesListScreenState extends State<TourExpensesListScreen> {
...
@@ -129,20 +129,18 @@ class _TourExpensesListScreenState extends State<TourExpensesListScreen> {
item
.
placeOfVisit
??
"-"
,
item
.
placeOfVisit
??
"-"
,
maxLines:
1
,
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
overflow:
TextOverflow
.
ellipsis
,
style:
const
TextStyle
(
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
fontSize:
14
,
fontFamily:
"Plus Jakarta Sans"
,
color:
AppColors
.
semi_black
,
fontWeight:
FontWeight
.
w400
,
color:
Color
(
0xff2d2d2d
),
),
),
),
),
Text
(
Text
(
item
.
appliedDate
??
"-"
,
item
.
appliedDate
??
"-"
,
style:
const
TextStyle
(
style:
TextStyle
(
fontSize:
12
,
fontFamily:
"JakartaRegular"
,
fontFamily:
"Plus Jakarta Sans"
,
fontSize:
14
,
fontWeight:
FontWeight
.
w400
,
color:
AppColors
.
grey_semi
,
color:
Color
(
0xff818181
),
),
),
),
),
],
],
...
@@ -153,9 +151,8 @@ class _TourExpensesListScreenState extends State<TourExpensesListScreen> {
...
@@ -153,9 +151,8 @@ class _TourExpensesListScreenState extends State<TourExpensesListScreen> {
Text
(
Text
(
"₹
${item.appliedAmount ?? '0'}
"
,
"₹
${item.appliedAmount ?? '0'}
"
,
style:
const
TextStyle
(
style:
const
TextStyle
(
fontFamily:
"JakartaMedium"
,
fontSize:
14
,
fontSize:
14
,
fontFamily:
"Plus Jakarta Sans"
,
fontWeight:
FontWeight
.
w500
,
color:
Color
(
0xff1487c9
),
color:
Color
(
0xff1487c9
),
)
)
),
),
...
@@ -185,7 +182,7 @@ class _TourExpensesListScreenState extends State<TourExpensesListScreen> {
...
@@ -185,7 +182,7 @@ class _TourExpensesListScreenState extends State<TourExpensesListScreen> {
name:
'AddTourExpBillScreen'
),
name:
'AddTourExpBillScreen'
),
),
),
).
then
((
_
)
{
).
then
((
_
)
{
provider
.
fetchTourExpenses
(
context
,
"1"
);
});
});
// show add bill screen here
// show add bill screen here
},
},
...
@@ -280,7 +277,7 @@ class _TourExpensesListScreenState extends State<TourExpensesListScreen> {
...
@@ -280,7 +277,7 @@ class _TourExpensesListScreenState extends State<TourExpensesListScreen> {
case
'Updated'
:
case
'Updated'
:
return
"U"
;
return
"U"
;
default
:
default
:
return
"R
equested
"
;
return
"R"
;
}
}
}
}
...
...
lib/screens/notifierExports.dart
View file @
f6fbe101
...
@@ -62,4 +62,6 @@ export 'package:generp/Notifiers/hrmProvider/AttendanceDetailsProvider.dart';
...
@@ -62,4 +62,6 @@ export 'package:generp/Notifiers/hrmProvider/AttendanceDetailsProvider.dart';
export
'package:generp/Notifiers/hrmProvider/tourExpensesProvider.dart'
;
export
'package:generp/Notifiers/hrmProvider/tourExpensesProvider.dart'
;
export
'package:generp/Notifiers/hrmProvider/tourExpensesDetailsProvider.dart'
;
export
'package:generp/Notifiers/hrmProvider/tourExpensesDetailsProvider.dart'
;
export
'package:generp/Notifiers/hrmProvider/rewardListProvider.dart'
;
export
'package:generp/Notifiers/hrmProvider/rewardListProvider.dart'
;
export
'package:generp/Notifiers/hrmProvider/LeaveApplicationListProvider.dart'
;
export
'package:generp/Notifiers/hrmProvider/LeaveApplicationDetailsProvider.dart'
;
lib/services/api_calling.dart
View file @
f6fbe101
...
@@ -26,7 +26,10 @@ import 'package:generp/Models/crmModels/crmProspectDetailsResponse.dart';
...
@@ -26,7 +26,10 @@ import 'package:generp/Models/crmModels/crmProspectDetailsResponse.dart';
import
'package:generp/Models/financeModels/addDirectPaymentResponse.dart'
;
import
'package:generp/Models/financeModels/addDirectPaymentResponse.dart'
;
import
'package:generp/Models/financeModels/paymentRequisitionPaymentsListResponse.dart'
;
import
'package:generp/Models/financeModels/paymentRequisitionPaymentsListResponse.dart'
;
import
'package:generp/Models/hrmModels/attendanceRequestListResponse.dart'
;
import
'package:generp/Models/hrmModels/attendanceRequestListResponse.dart'
;
import
'package:generp/Models/hrmModels/leaveApplicationDetailsResponse.dart'
;
import
'package:generp/Models/hrmModels/leaveApplicationLIstResponse.dart'
;
import
'package:generp/Models/hrmModels/rewardListResponse.dart'
;
import
'package:generp/Models/hrmModels/rewardListResponse.dart'
;
import
'package:generp/Models/hrmModels/tourExpensesAddViewResponse.dart'
;
import
'package:generp/Models/hrmModels/tourExpensesDetailsResponse.dart'
;
import
'package:generp/Models/hrmModels/tourExpensesDetailsResponse.dart'
;
import
'package:generp/Models/hrmModels/tourExpensesListResponse.dart'
;
import
'package:generp/Models/hrmModels/tourExpensesListResponse.dart'
;
import
'package:generp/Models/ordersModels/PendingTPCAgentListResponse.dart'
;
import
'package:generp/Models/ordersModels/PendingTPCAgentListResponse.dart'
;
...
@@ -35,6 +38,7 @@ import 'package:generp/Models/ordersModels/TPCListResponse.dart';
...
@@ -35,6 +38,7 @@ import 'package:generp/Models/ordersModels/TPCListResponse.dart';
import
'package:generp/Models/ordersModels/orderDashboardResponse.dart'
;
import
'package:generp/Models/ordersModels/orderDashboardResponse.dart'
;
import
'package:generp/services/api_names.dart'
;
import
'package:generp/services/api_names.dart'
;
import
'package:generp/services/api_post_request.dart'
;
import
'package:generp/services/api_post_request.dart'
;
import
'package:http/http.dart'
as
http
;
import
'package:path_provider/path_provider.dart'
;
import
'package:path_provider/path_provider.dart'
;
import
'../Models/AccountSuggestionResponse.dart'
;
import
'../Models/AccountSuggestionResponse.dart'
;
...
@@ -97,6 +101,7 @@ import '../Models/financeModels/paymentRequisitionPaymentsReceiptsDetailsRespons
...
@@ -97,6 +101,7 @@ import '../Models/financeModels/paymentRequisitionPaymentsReceiptsDetailsRespons
import
'../Models/financeModels/paymentRequisitionPaymentsReceiptsListResponse.dart'
;
import
'../Models/financeModels/paymentRequisitionPaymentsReceiptsListResponse.dart'
;
import
'../Models/generatorComplaintResponse.dart'
;
import
'../Models/generatorComplaintResponse.dart'
;
import
'../Models/hrmModels/attendanceRequestDetailsResponse.dart'
;
import
'../Models/hrmModels/attendanceRequestDetailsResponse.dart'
;
import
'../Models/hrmModels/hrmAccessiblePagesResponse.dart'
;
import
'../Models/loadGeneratorDetailsResponse.dart'
;
import
'../Models/loadGeneratorDetailsResponse.dart'
;
import
'../Models/financeModels/financeDashboardPagesResponse.dart'
;
import
'../Models/financeModels/financeDashboardPagesResponse.dart'
;
import
'../Models/ordersModels/AddOrderPaymentSelectAccountResponse.dart'
;
import
'../Models/ordersModels/AddOrderPaymentSelectAccountResponse.dart'
;
...
@@ -121,6 +126,7 @@ import '../Models/ordersModels/paymentListByModeResponse.dart';
...
@@ -121,6 +126,7 @@ import '../Models/ordersModels/paymentListByModeResponse.dart';
import
'../Models/ordersModels/technicianAddPaymentResendOTPResponse.dart'
;
import
'../Models/ordersModels/technicianAddPaymentResendOTPResponse.dart'
;
import
'../Notifiers/financeProvider/approveRejectPaymentRequestResponse.dart'
;
import
'../Notifiers/financeProvider/approveRejectPaymentRequestResponse.dart'
;
import
'../Utils/commonServices.dart'
;
import
'../Utils/commonServices.dart'
;
import
'package:http_parser/http_parser.dart'
;
class
ApiCalling
{
class
ApiCalling
{
static
Future
download_files
(
empId
,
session
,
url
,
cntxt
)
async
{
static
Future
download_files
(
empId
,
session
,
url
,
cntxt
)
async
{
...
@@ -4905,6 +4911,30 @@ class ApiCalling {
...
@@ -4905,6 +4911,30 @@ class ApiCalling {
///hrm modules
///hrm modules
///
///
static
Future
<
hrmAccessiblePagesResponse
?>
hrmAccessiblePagesAPI
(
empId
,
session
,
)
async
{
try
{
Map
<
String
,
String
>
data
=
{
'emp_id'
:
(
empId
).
toString
(),
'session_id'
:
(
session
).
toString
(),
};
final
res
=
await
post
(
data
,
HrmAccessiblePagesUrl
,
{});
if
(
res
!=
null
)
{
print
(
data
);
debugPrint
(
res
.
body
);
return
hrmAccessiblePagesResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
debugPrint
(
"Null Response"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
'hello bev=bug
$e
'
);
return
null
;
}
}
static
Future
<
attendanceRequestListResponse
?>
attendanceRequestListAPI
(
static
Future
<
attendanceRequestListResponse
?>
attendanceRequestListAPI
(
empId
,
empId
,
session
,
session
,
...
@@ -4961,6 +4991,82 @@ class ApiCalling {
...
@@ -4961,6 +4991,82 @@ class ApiCalling {
}
}
}
}
static
Future
<
CommonResponse
?>
addAttendanceRequestAPI
({
required
String
sessionId
,
required
String
empId
,
required
String
process
,
required
String
type
,
required
String
loc
,
required
String
checkDate
,
String
?
checkInTime
,
String
?
checkInLoc
,
File
?
checkInProof
,
String
?
checkOutTime
,
String
?
checkOutLoc
,
File
?
checkOutProof
,
String
?
note
,
})
async
{
try
{
var
request
=
http
.
MultipartRequest
(
'POST'
,
Uri
.
parse
(
AddAttendanceRequestUrl
));
// Add basic fields that are always required
Map
<
String
,
String
>
fields
=
{
"session_id"
:
sessionId
,
"emp_id"
:
empId
,
"process"
:
process
,
"type"
:
type
,
"loc"
:
loc
,
"check_date"
:
checkDate
,
"note"
:
note
??
""
,
};
// Conditionally add check-in fields based on type
if
(
type
==
"Check In"
||
type
==
"Check In/Out"
)
{
fields
[
"check_in_time"
]
=
checkInTime
??
""
;
fields
[
"check_in_loc"
]
=
checkInLoc
??
""
;
if
(
checkInProof
!=
null
)
{
request
.
files
.
add
(
await
http
.
MultipartFile
.
fromPath
(
"check_in_proof"
,
checkInProof
.
path
));
}
}
// Conditionally add check-out fields based on type
if
(
type
==
"Check Out"
||
type
==
"Check In/Out"
)
{
fields
[
"check_out_time"
]
=
checkOutTime
??
""
;
fields
[
"check_out_loc"
]
=
checkOutLoc
??
""
;
if
(
checkOutProof
!=
null
)
{
request
.
files
.
add
(
await
http
.
MultipartFile
.
fromPath
(
"check_out_proof"
,
checkOutProof
.
path
));
}
}
// Add all fields to the request
request
.
fields
.
addAll
(
fields
);
// Log the actual fields being sent
debugPrint
(
"addAttendanceRequestAPI - Type:
$type
"
);
debugPrint
(
"addAttendanceRequestAPI - Fields:
$fields
"
);
debugPrint
(
"addAttendanceRequestAPI - Files:
${request.files.map((f) => f.filename).toList()}
"
);
var
response
=
await
request
.
send
();
var
resBody
=
await
response
.
stream
.
bytesToString
();
debugPrint
(
"Server Response:
$resBody
"
);
if
(
response
.
statusCode
==
200
)
{
return
CommonResponse
.
fromJson
(
jsonDecode
(
resBody
));
}
else
{
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
"API Error:
$e
"
);
return
null
;
}
}
//reward list
//reward list
static
Future
<
rewardListResponse
?>
rewardListAPI
(
static
Future
<
rewardListResponse
?>
rewardListAPI
(
empId
,
empId
,
...
@@ -5039,6 +5145,215 @@ class ApiCalling {
...
@@ -5039,6 +5145,215 @@ class ApiCalling {
}
}
}
}
static
Future
<
tourExpensesAddViewResponse
?>
tourExpensesAddViewAPI
(
empId
,
session
,
tourBillId
,
)
async
{
try
{
Map
<
String
,
String
>
data
=
{
'session_id'
:
(
session
).
toString
(),
'emp_id'
:
(
empId
).
toString
(),
'tour_bill_id'
:
(
tourBillId
),
};
final
res
=
await
post
(
data
,
TourExpensesAddViewUrl
,
{});
if
(
res
!=
null
)
{
print
(
data
);
debugPrint
(
res
.
body
);
return
tourExpensesAddViewResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
debugPrint
(
"Null Response"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
'hello bev=bug
$e
'
);
return
null
;
}
}
static
Future
<
CommonResponse
?>
addTourBillAPI
({
required
String
sessionId
,
required
String
empId
,
required
String
placeOfVisit
,
required
String
daAmount
,
required
String
tourType
,
required
String
tourDate
,
required
List
<
Map
<
String
,
dynamic
>>
travelExpenses
,
required
List
<
Map
<
String
,
dynamic
>>
hotelExpenses
,
required
List
<
Map
<
String
,
dynamic
>>
otherExpenses
,
List
<
File
>?
travelImages
,
List
<
File
>?
hotelImages
,
List
<
File
>?
otherImages
,
})
async
{
try
{
var
request
=
http
.
MultipartRequest
(
"POST"
,
Uri
.
parse
(
AddTourExpensesUrl
));
/// Add text fields
request
.
fields
[
'session_id'
]
=
sessionId
;
request
.
fields
[
'emp_id'
]
=
empId
;
request
.
fields
[
'place_of_visit'
]
=
placeOfVisit
;
request
.
fields
[
'da_amount'
]
=
daAmount
;
request
.
fields
[
'tour_type'
]
=
tourType
;
request
.
fields
[
'tour_date'
]
=
tourDate
;
/// Convert expense lists to JSON string
request
.
fields
[
'travel_expenses'
]
=
jsonEncode
(
travelExpenses
);
request
.
fields
[
'hotel_expenses'
]
=
jsonEncode
(
hotelExpenses
);
request
.
fields
[
'other_expenses'
]
=
jsonEncode
(
otherExpenses
);
/// Add hotel images
if
(
hotelImages
!.
isNotEmpty
)
{
for
(
var
file
in
hotelImages
)
{
if
(
file
.
path
.
isNotEmpty
)
{
request
.
files
.
add
(
await
http
.
MultipartFile
.
fromPath
(
"hotel_images[]"
,
file
.
path
,
),
);
}
}
}
/// Add travel images
if
(
travelImages
!.
isNotEmpty
)
{
for
(
var
file
in
travelImages
)
{
if
(
file
.
path
.
isNotEmpty
)
{
request
.
files
.
add
(
await
http
.
MultipartFile
.
fromPath
(
"travel_images[]"
,
file
.
path
,
),
);
}
}
}
/// Add other images
if
(
otherImages
!.
isNotEmpty
)
{
for
(
var
file
in
otherImages
)
{
if
(
file
.
path
.
isNotEmpty
)
{
request
.
files
.
add
(
await
http
.
MultipartFile
.
fromPath
(
"other_images[]"
,
file
.
path
,
),
);
}
}
}
/// Send request
var
response
=
await
request
.
send
();
var
resBody
=
await
response
.
stream
.
bytesToString
();
debugPrint
(
"Request Fields:
${request.fields}
"
);
debugPrint
(
"Response:
$resBody
"
);
if
(
response
.
statusCode
==
200
)
{
return
CommonResponse
.
fromJson
(
jsonDecode
(
resBody
));
}
else
{
debugPrint
(
"Error:
${response.statusCode}
-
$resBody
"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
"Error in addTourBillAPI:
$e
"
);
return
null
;
}
}
// Leave Application api
static
Future
<
leaveApplicationLIstResponse
?>
leaveApplicationListAPI
(
session
,
empId
,
dateFrom
,
dateTo
)
async
{
try
{
Map
<
String
,
String
>
data
=
{
'session_id'
:
(
session
).
toString
(),
'emp_id'
:
(
empId
).
toString
(),
'requested_date_from'
:
(
dateFrom
),
'requested_date_to'
:
(
dateTo
),
};
final
res
=
await
post
(
data
,
LeaveApplicationListUrl
,
{});
if
(
res
!=
null
)
{
print
(
data
);
debugPrint
(
res
.
body
);
return
leaveApplicationLIstResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
debugPrint
(
"Null Response"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
'hello bev=bug
$e
'
);
return
null
;
}
}
static
Future
<
leaveApplicationDetailsResponse
?>
leaveApplicationDetailAPI
(
session
,
empId
,
leaveRequestId
,
)
async
{
try
{
Map
<
String
,
String
>
data
=
{
'session_id'
:
(
session
).
toString
(),
'emp_id'
:
(
empId
).
toString
(),
'leave_request_id'
:
(
leaveRequestId
),
};
final
res
=
await
post
(
data
,
LeaveApplicationDetailsUrl
,
{});
if
(
res
!=
null
)
{
print
(
data
);
debugPrint
(
res
.
body
);
return
leaveApplicationDetailsResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
debugPrint
(
"Null Response"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
'hello bev=bug
$e
'
);
return
null
;
}
}
//add leave request
static
Future
<
CommonResponse
?>
leaveRequestAddAPI
(
session
,
empId
,
fromDate
,
fromTime
,
toDate
,
toTime
,
leaveType
,
reason
)
async
{
try
{
Map
<
String
,
String
>
data
=
{
'session_id'
:
(
session
).
toString
(),
'emp_id'
:
(
empId
).
toString
(),
'from_date'
:
(
fromDate
).
toString
(),
'from_time'
:
(
fromTime
).
toString
(),
'to_date'
:
(
toDate
).
toString
(),
'to_time'
:
(
toTime
).
toString
(),
'leave_type'
:
(
leaveType
).
toString
(),
'reason'
:
(
reason
).
toString
(),
};
final
res
=
await
post
(
data
,
LeaveRequestAdditionUrl
,
{});
if
(
res
!=
null
)
{
print
(
data
);
debugPrint
(
res
.
body
);
return
CommonResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
debugPrint
(
"Null Response"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
'hello bev=bug
$e
'
);
return
null
;
}
}
// static Future<CommonResponse?> TpcIssueListApprovalAPI(
// static Future<CommonResponse?> TpcIssueListApprovalAPI(
// empId,
// empId,
...
...
lib/services/api_names.dart
View file @
f6fbe101
...
@@ -180,6 +180,7 @@ const crmDashboardQuotationsUrl = "${baseUrl_test}crm_dashboard_quotations_list"
...
@@ -180,6 +180,7 @@ const crmDashboardQuotationsUrl = "${baseUrl_test}crm_dashboard_quotations_list"
///HRM
///HRM
//Attendance
//Attendance
const
HrmAccessiblePagesUrl
=
"
${baseUrl_test}
hrm_accessible_pages"
;
const
AttendanceRequestListUrl
=
"
${baseUrl_test}
attendance_request_list"
;
const
AttendanceRequestListUrl
=
"
${baseUrl_test}
attendance_request_list"
;
const
AttendanceRequestDetailsUrl
=
"
${baseUrl_test}
attendance_request_details"
;
const
AttendanceRequestDetailsUrl
=
"
${baseUrl_test}
attendance_request_details"
;
const
AddAttendanceRequestUrl
=
"
${baseUrl_test}
add_attendance_request"
;
const
AddAttendanceRequestUrl
=
"
${baseUrl_test}
add_attendance_request"
;
...
@@ -188,6 +189,12 @@ const RewardListUrl ="${baseUrl_test}hrm_emp_self_rewards";
...
@@ -188,6 +189,12 @@ const RewardListUrl ="${baseUrl_test}hrm_emp_self_rewards";
// Tour Expenses hrm_emp_self_rewards
// Tour Expenses hrm_emp_self_rewards
const
TourExpensesListUrl
=
"
${baseUrl_test}
tour_bill_list"
;
const
TourExpensesListUrl
=
"
${baseUrl_test}
tour_bill_list"
;
const
TourExpensesDetailsUrl
=
"
${baseUrl_test}
tour_bill_details"
;
const
TourExpensesDetailsUrl
=
"
${baseUrl_test}
tour_bill_details"
;
const
TourExpensesAddViewUrl
=
"
${baseUrl_test}
add_tour_bill_view"
;
const
AddTourExpensesUrl
=
"
${baseUrl_test}
add_tour_bill"
;
//leave applications
const
LeaveApplicationListUrl
=
"
${baseUrl_test}
leave_request_list"
;
const
LeaveApplicationDetailsUrl
=
"
${baseUrl_test}
leave_request_details"
;
const
LeaveRequestAdditionUrl
=
"
${baseUrl_test}
add_leave_request"
;
...
...
lib/services/api_post_request.dart
View file @
f6fbe101
...
@@ -181,6 +181,76 @@ Future<String?> postImageNew(
...
@@ -181,6 +181,76 @@ Future<String?> postImageNew(
return
null
;
return
null
;
}
}
}
}
//travel_image
//hotel_image
//other_image
Future
<
String
?>
PostMultipleImagesNew
(
Map
<
String
,
String
>
body
,
String
urlLink
,
Map
<
String
,
String
>
headers
,
List
<
http
.
MultipartFile
>
newList
,
List
<
http
.
MultipartFile
>
newList1
,
List
<
http
.
MultipartFile
>
newList2
,
)
async
{
try
{
var
req
=
http
.
MultipartRequest
(
'POST'
,
Uri
.
parse
(
urlLink
));
req
.
headers
.
addAll
(
headers
);
req
.
files
.
addAll
(
newList
);
req
.
files
.
addAll
(
newList1
);
req
.
files
.
addAll
(
newList2
);
req
.
fields
.
addAll
(
body
);
var
res
=
await
req
.
send
();
final
resBody
=
await
res
.
stream
.
bytesToString
();
if
(
res
.
statusCode
>=
200
&&
res
.
statusCode
<
300
)
{
print
(
"****
$resBody
....
$res
"
);
return
resBody
;
}
else
{
print
(
"error:
${res.reasonPhrase}
"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
e
.
toString
());
return
null
;
}
}
Future
<
String
?>
PostMultipleImagesNew2
(
Map
<
String
,
String
>
body
,
String
urlLink
,
Map
<
String
,
String
>
headers
,
List
<
http
.
MultipartFile
>
newList
,
List
<
http
.
MultipartFile
>
newList1
,
)
async
{
try
{
var
req
=
http
.
MultipartRequest
(
'POST'
,
Uri
.
parse
(
urlLink
));
req
.
headers
.
addAll
(
headers
);
req
.
files
.
addAll
(
newList
);
req
.
files
.
addAll
(
newList1
);
req
.
fields
.
addAll
(
body
);
var
res
=
await
req
.
send
();
final
resBody
=
await
res
.
stream
.
bytesToString
();
if
(
res
.
statusCode
>=
200
&&
res
.
statusCode
<
300
)
{
print
(
"****
$resBody
....
$res
"
);
return
resBody
;
}
else
{
print
(
"error:
${res.reasonPhrase}
"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
e
.
toString
());
return
null
;
}
}
Future
<
String
?>
PostMultipleImages
(
Future
<
String
?>
PostMultipleImages
(
Map
<
String
,
String
>
body
,
Map
<
String
,
String
>
body
,
...
...
macos/Flutter/GeneratedPluginRegistrant.swift
View file @
f6fbe101
...
@@ -8,6 +8,7 @@ import Foundation
...
@@ -8,6 +8,7 @@ import Foundation
import
app_settings
import
app_settings
import
connectivity_plus
import
connectivity_plus
import
device_info_plus
import
device_info_plus
import
file_picker
import
file_selector_macos
import
file_selector_macos
import
firebase_core
import
firebase_core
import
firebase_messaging
import
firebase_messaging
...
@@ -30,6 +31,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
...
@@ -30,6 +31,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AppSettingsPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"AppSettingsPlugin"
))
AppSettingsPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"AppSettingsPlugin"
))
ConnectivityPlusPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"ConnectivityPlusPlugin"
))
ConnectivityPlusPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"ConnectivityPlusPlugin"
))
DeviceInfoPlusMacosPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"DeviceInfoPlusMacosPlugin"
))
DeviceInfoPlusMacosPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"DeviceInfoPlusMacosPlugin"
))
FilePickerPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"FilePickerPlugin"
))
FileSelectorPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"FileSelectorPlugin"
))
FileSelectorPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"FileSelectorPlugin"
))
FLTFirebaseCorePlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"FLTFirebaseCorePlugin"
))
FLTFirebaseCorePlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"FLTFirebaseCorePlugin"
))
FLTFirebaseMessagingPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"FLTFirebaseMessagingPlugin"
))
FLTFirebaseMessagingPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"FLTFirebaseMessagingPlugin"
))
...
...
pubspec.lock
View file @
f6fbe101
...
@@ -465,6 +465,14 @@ packages:
...
@@ -465,6 +465,14 @@ packages:
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "7.0.1"
version: "7.0.1"
file_picker:
dependency: "direct main"
description:
name: file_picker
sha256: ab13ae8ef5580a411c458d6207b6774a6c237d77ac37011b13994879f68a8810
url: "https://pub.dev"
source: hosted
version: "8.3.7"
file_selector_linux:
file_selector_linux:
dependency: transitive
dependency: transitive
description:
description:
...
...
pubspec.yaml
View file @
f6fbe101
...
@@ -89,6 +89,7 @@ dependencies:
...
@@ -89,6 +89,7 @@ dependencies:
pinput
:
^5.0.1
pinput
:
^5.0.1
build_runner
:
^2.4.0
build_runner
:
^2.4.0
build_web_compilers
:
^4.0.4
build_web_compilers
:
^4.0.4
file_picker
:
^8.0.0
dev_dependencies
:
dev_dependencies
:
flutter_test
:
flutter_test
:
...
...
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment