username and upload file changes
This commit is contained in:
parent
521bd49a17
commit
45eb1d4c36
@ -8,13 +8,25 @@ import 'package:nhance_app_pwa/customAppBar/responsive.dart';
|
||||
import '../pages/postEnrollment/service/api_service.dart';
|
||||
import '../pages/service/SessionManager.dart';
|
||||
import '../pages/service/popup_helper.dart';
|
||||
class CustomAppBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
@override
|
||||
_CustomAppBarState createState() => _CustomAppBarState();
|
||||
|
||||
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
@override
|
||||
Size get preferredSize => Size.fromHeight(kToolbarHeight);
|
||||
}
|
||||
class _CustomAppBarState extends State<CustomAppBar> {
|
||||
@override
|
||||
Size get preferredSize => Size.fromHeight(kToolbarHeight);
|
||||
late ApiService apiService;
|
||||
final session = SessionManager();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
apiService = ApiService(context);
|
||||
}
|
||||
|
||||
Future<void> logout(BuildContext context) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final String? token = prefs.getString('_postToken');
|
||||
@ -28,107 +40,179 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
apiService = ApiService(context);
|
||||
final sw = MediaQuery.of(context).size.width;
|
||||
final isPoliciesPage = Uri.base.fragment == 'policies';
|
||||
return ClipRRect(
|
||||
borderRadius: Responsive.isDesktop(context) || isPoliciesPage
|
||||
? BorderRadius.zero
|
||||
: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(32.0),
|
||||
bottomRight: Radius.circular(32.0),
|
||||
return Scaffold(
|
||||
backgroundColor: Color(0xFFFFFCE5), // Set background color for AppBar
|
||||
appBar: PreferredSize(
|
||||
preferredSize: widget.preferredSize,
|
||||
child: SafeArea(
|
||||
child: Container(
|
||||
// padding: Responsive.isDesktop(context)
|
||||
// ? EdgeInsets.symmetric(horizontal: 46.0)
|
||||
// : EdgeInsets.symmetric(horizontal: 0),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: MediaQuery.of(context).size.width *
|
||||
(Responsive.isDesktop(context) ? 0.03 : 0.02),
|
||||
),
|
||||
child: AppBar(
|
||||
backgroundColor: const Color(0xFFFFFBDE),
|
||||
elevation: 0, // Set background color for AppBar
|
||||
toolbarHeight: kToolbarHeight,
|
||||
titleSpacing: 0.0,
|
||||
automaticallyImplyLeading: false,
|
||||
title: Padding(
|
||||
padding: Responsive.isDesktop(context)
|
||||
? EdgeInsets.symmetric(horizontal: 16.0)
|
||||
: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
// Logo Column
|
||||
Expanded(
|
||||
flex: Responsive.isDesktop(context) ? 3 : 9,
|
||||
child: Row(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
// Logo Column
|
||||
// Expanded(
|
||||
// // flex: Responsive.isDesktop(context) ? 1 : 9,
|
||||
// child:
|
||||
Row(
|
||||
mainAxisAlignment: Responsive.isDesktop(context)
|
||||
? MainAxisAlignment.spaceEvenly
|
||||
: MainAxisAlignment
|
||||
.start, // Adjust the alignment as needed
|
||||
: MainAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
// margin: EdgeInsets.only(
|
||||
// top: 10, bottom: 10, left: 10, right: 10),
|
||||
// width: Responsive.isDesktop(context) ? 150 : 130,
|
||||
// height: Responsive.isDesktop(context) ? 31 : 130,
|
||||
child: SvgPicture.asset(
|
||||
'assets/nhance_client_logo.svg',
|
||||
width: 150,
|
||||
margin: EdgeInsets.only(top: 10, bottom: 10),
|
||||
width: 150,
|
||||
height: 150,
|
||||
child: Image.asset(
|
||||
'assets/nhance_client_logo.png',
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
// child: Image.asset(
|
||||
// 'assets/nhance_logo.png',
|
||||
// width: 250,
|
||||
// ),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// AdaptiveNavBar Column
|
||||
if (Responsive.isDesktop(context))
|
||||
Expanded(
|
||||
flex: Responsive.isDesktop(context) ? 9 : 3,
|
||||
child: AdaptiveNavBar(
|
||||
screenWidth: sw,
|
||||
backgroundColor: const Color(0xFFFFFBDE),
|
||||
leading:
|
||||
Container(), // Set an empty container as we have the logo separately
|
||||
title: Text(''),
|
||||
navBarItems: [
|
||||
NavBarItem(
|
||||
text: "Home",
|
||||
onTap: () {
|
||||
context.push('/home');
|
||||
},
|
||||
),
|
||||
NavBarItem(
|
||||
text: "Claims",
|
||||
onTap: () {
|
||||
context.push('/claims');
|
||||
},
|
||||
),
|
||||
NavBarItem(
|
||||
text: "Help",
|
||||
onTap: () {
|
||||
context.push('/help');
|
||||
},
|
||||
),
|
||||
NavBarItem(
|
||||
text: "Wellness",
|
||||
onTap: () {
|
||||
// Wellness tab clicked → show popup
|
||||
PopupHelper.showRedirectPopup(
|
||||
context: context,
|
||||
apiService: apiService,
|
||||
empPrimaryId: session.empPrimaryId,
|
||||
);
|
||||
},
|
||||
),
|
||||
NavBarItem(
|
||||
text: "Profile",
|
||||
onTap: () {
|
||||
context.push('/profile');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
// ),
|
||||
// AdaptiveNavBar Column
|
||||
|
||||
// Expanded(
|
||||
// // flex: Responsive.isDesktop(context) ? 1 : 9,
|
||||
// child:
|
||||
if(Responsive.isDesktop(context))
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
NavBarItem(
|
||||
text: "Home",
|
||||
onTap: () {
|
||||
context.push('/home');
|
||||
},
|
||||
),
|
||||
NavBarItem(
|
||||
text: "Claims",
|
||||
onTap: () {
|
||||
context.push('/claims');
|
||||
},
|
||||
),
|
||||
NavBarItem(
|
||||
text: "Help",
|
||||
onTap: () {
|
||||
context.push('/help');
|
||||
},
|
||||
),
|
||||
NavBarItem(
|
||||
text: "Wellness",
|
||||
onTap: () {
|
||||
// context.push('/wellness');
|
||||
// Wellness tab clicked → show popup
|
||||
PopupHelper.showRedirectPopup(
|
||||
context: context,
|
||||
apiService: apiService,
|
||||
empPrimaryId: session.empPrimaryId,
|
||||
);
|
||||
},
|
||||
),
|
||||
NavBarItem(
|
||||
text: "Profile",
|
||||
onTap: () {
|
||||
context.push('/profile');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
// )
|
||||
|
||||
// Expanded(
|
||||
// flex: Responsive.isDesktop(context) ? 9 : 3,
|
||||
// child: AdaptiveNavBar(
|
||||
// screenWidth: sw,
|
||||
// backgroundColor: Color(0xFFFFFCE5),
|
||||
// leading:
|
||||
// Container(), // Set an empty container as we have the logo separately
|
||||
// title: Text(''),
|
||||
// navBarItems: [
|
||||
// // if (Responsive.isDesktop(context))
|
||||
// // if (hideInactiveStatus)
|
||||
// // NavBarItem(
|
||||
// // text: "Inactive Policy",
|
||||
// // onTap: () {
|
||||
// // Navigator.pushNamed(context, 'oldPolicy');
|
||||
// // },
|
||||
// // ),
|
||||
// // if (showBackToHR)
|
||||
// NavBarItem(
|
||||
// text: "Change Branch",
|
||||
// onTap: () async {
|
||||
// final prefs = await SharedPreferences.getInstance();
|
||||
// await prefs.remove('selected_branch');
|
||||
// await prefs.remove('decoded_token');
|
||||
// await prefs.remove('clientLogo');
|
||||
// await prefs.remove('clientName');
|
||||
// await prefs.remove('empAllowed_modules');
|
||||
// await prefs.remove('empClientBranchId');
|
||||
// await prefs.remove('empClientId');
|
||||
// await prefs.remove('empEmail');
|
||||
// await prefs.remove('empHrId');
|
||||
// await prefs.remove('empPrimaryId');
|
||||
// await prefs.remove('enrollmentAllowed_modules');
|
||||
// await prefs.remove('enrollmentClient_id');
|
||||
// await prefs.remove('enrollmentEmpClientBranchId');
|
||||
// await prefs.remove('enrollmentEmpPrimaryId');
|
||||
// await prefs.remove('enrollmentHrId');
|
||||
// await prefs.remove('token');
|
||||
// Navigator.pushNamed(context, 'branchSelection');
|
||||
// },
|
||||
// ),
|
||||
// NavBarItem(
|
||||
// text: "Logout",
|
||||
// onTap: () async {
|
||||
// logout(context);
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
class NavBarItem extends StatelessWidget {
|
||||
final String text;
|
||||
final VoidCallback? onTap;
|
||||
|
||||
const NavBarItem({
|
||||
Key? key,
|
||||
required this.text,
|
||||
this.onTap,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
onTap: onTap,
|
||||
hoverColor: const Color(0xFFF4F3E7), // subtle hover background
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
child: Text(
|
||||
text,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -41,12 +41,25 @@ class _changesPasswordState extends State<changesPassword> {
|
||||
bool _obscureNewPassword = true;
|
||||
bool _obscureConfirmPassword = true;
|
||||
late SessionManager session;
|
||||
bool hasMinLength = false;
|
||||
bool hasUpperLower = false;
|
||||
bool hasNumber = false;
|
||||
bool hasSpecialChar = false;
|
||||
bool get isPasswordValid => hasMinLength && hasUpperLower && hasNumber && hasSpecialChar;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void validatePassword(String password) {
|
||||
setState(() {
|
||||
hasMinLength = password.length >= 8;
|
||||
hasUpperLower = RegExp(r'(?=.*[A-Za-z])').hasMatch(password);
|
||||
hasNumber = RegExp(r'(?=.*\d)').hasMatch(password);
|
||||
hasSpecialChar = RegExp(r'(?=.*[@$!%*#?&])').hasMatch(password);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> resetYourPassword() async {
|
||||
final oldpassword = oldPasswordController.text.trim();
|
||||
@ -354,7 +367,7 @@ class _changesPasswordState extends State<changesPassword> {
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"Welcome to Nhance",
|
||||
"Change Password",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
@ -378,7 +391,7 @@ class _changesPasswordState extends State<changesPassword> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Login with your to review and enroll for exciting health benefits for you and your family",
|
||||
"To change your password, please fill in the fields below.",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Color(0xFF000000)),
|
||||
@ -466,70 +479,58 @@ class _changesPasswordState extends State<changesPassword> {
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
height: 55,
|
||||
margin: Responsive.isDesktop(
|
||||
context)
|
||||
? const EdgeInsets
|
||||
.symmetric(
|
||||
horizontal: 150)
|
||||
: const EdgeInsets
|
||||
.symmetric(
|
||||
horizontal: 0),
|
||||
margin: Responsive.isDesktop(context)
|
||||
? const EdgeInsets.symmetric(horizontal: 150)
|
||||
: const EdgeInsets.symmetric(horizontal: 0),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: Colors.grey),
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
10),
|
||||
border: Border.all(width: 1, color: Colors.grey),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: TextFormField(
|
||||
controller:
|
||||
newPasswordController,
|
||||
obscureText:
|
||||
_obscureNewPassword,
|
||||
textAlignVertical:
|
||||
TextAlignVertical
|
||||
.center,
|
||||
controller: newPasswordController,
|
||||
obscureText: _obscureNewPassword,
|
||||
onChanged: validatePassword,
|
||||
textAlignVertical: TextAlignVertical.center,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText:
|
||||
"New Password",
|
||||
contentPadding:
|
||||
const EdgeInsets
|
||||
.symmetric(
|
||||
horizontal: 10),
|
||||
hintText: "New Password",
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
_obscureNewPassword
|
||||
? Icons
|
||||
.visibility_off
|
||||
: Icons
|
||||
.visibility,
|
||||
_obscureNewPassword ? Icons.visibility_off : Icons.visibility,
|
||||
color: Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_obscureNewPassword =
|
||||
!_obscureNewPassword;
|
||||
_obscureNewPassword = !_obscureNewPassword;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null ||
|
||||
value.isEmpty) {
|
||||
return 'Please enter your new password';
|
||||
}
|
||||
if (value.length < 6) {
|
||||
return 'Password must be at least 6 characters';
|
||||
}
|
||||
if (!RegExp(
|
||||
r'^(?=.*[A-Z])(?=.*[0-9]).{6,}$')
|
||||
.hasMatch(value)) {
|
||||
return 'Include at least 1 uppercase letter and 1 number';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
// 🔹 VALIDATION LIST
|
||||
Padding(
|
||||
padding: Responsive.isDesktop(context)
|
||||
? const EdgeInsets.symmetric(horizontal: 150)
|
||||
: const EdgeInsets.symmetric(horizontal: 5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _buildCheckItem(hasMinLength, "Minimum 8 characters")),
|
||||
Expanded(child: _buildCheckItem(hasSpecialChar, "1 special character")),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _buildCheckItem(hasUpperLower, "1 UPPER or lower case")),
|
||||
Expanded(child: _buildCheckItem(hasNumber, "1 numerical")),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
@ -767,4 +768,28 @@ class _changesPasswordState extends State<changesPassword> {
|
||||
)),
|
||||
)));
|
||||
}
|
||||
|
||||
Widget _buildCheckItem(bool status, String text) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
status ? Icons.check : Icons.close,
|
||||
color: status ? Colors.green : Colors.red,
|
||||
size: 18,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
color: status ? Colors.green : Colors.red,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -442,9 +442,9 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
|
||||
// final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
// prefs.setString('empEmailid', widget.email);
|
||||
ToastHelper.showSuccessToast(context, 'Successfully Login');
|
||||
// checkPassword(context,session.empEmailCorporate,session.client_id,'home');
|
||||
checkPassword(context,session.empEmailCorporate,session.client_id,'home');
|
||||
// if (emp_status == 'enrolled' || emp_status == 'active') {
|
||||
context.go('/home');
|
||||
// context.go('/home');
|
||||
// Navigator.pushReplacementNamed(context, 'home');
|
||||
// } else {
|
||||
// Navigator.pushReplacementNamed(context, 'empDetails');
|
||||
@ -499,11 +499,11 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
|
||||
} else {
|
||||
if (_preToken != null && _preToken.isNotEmpty) {
|
||||
ToastHelper.showSuccessToast(context, 'Successfully Login');
|
||||
// checkPassword(context,session.enrollmentEmailCorporate,session.enrollmentClient_id,'empDetails');
|
||||
checkPassword(context,session.enrollmentEmailCorporate,session.enrollmentClient_id,'empDetails');
|
||||
// if (emp_status == 'enrolled' || emp_status == 'active') {
|
||||
// Navigator.pushReplacementNamed(context, 'home');
|
||||
// } else {
|
||||
context.go('/empDetails');
|
||||
// context.go('/empDetails');
|
||||
// Navigator.pushReplacementNamed(context, 'empDetails');
|
||||
// }
|
||||
}
|
||||
|
||||
2468
lib/pages/login.dart
2468
lib/pages/login.dart
File diff suppressed because it is too large
Load Diff
@ -960,15 +960,25 @@ class _claimsState extends State<claims> {
|
||||
print(claimStatus);
|
||||
print(claimsDepartmentName);
|
||||
|
||||
|
||||
|
||||
final Map<String, Color> statusColors = {
|
||||
'Received': Colors.blueGrey, // New / Received
|
||||
'Under Process': Colors.orangeAccent, // Work in progress
|
||||
'Approved': Colors.green, // Approved
|
||||
'Settled': Colors.teal, // Completed successfully
|
||||
'Returned': Colors.deepOrange, // Sent back for correction
|
||||
'Rejected': Colors.red, // Rejected
|
||||
'Cancelled': Colors.redAccent, // Cancelled
|
||||
'Closed': Colors.grey, // Closed
|
||||
'Claim Received': Colors.blueGrey,
|
||||
'Under Process' : Colors.orangeAccent,
|
||||
'Information Required': Colors.deepOrange,
|
||||
'Approved': Colors.green,
|
||||
'Settled': Colors.teal,
|
||||
'Denial Review Awaited':Colors.redAccent,
|
||||
'Rejected': Colors.red,
|
||||
|
||||
// 'Received': Colors.blueGrey, // New / Received
|
||||
// 'Under Process': Colors.orangeAccent, // Work in progress
|
||||
// 'Approved': Colors.green, // Approved
|
||||
// 'Settled': Colors.teal, // Completed successfully
|
||||
// 'Returned': Colors.deepOrange, // Sent back for correction
|
||||
// 'Rejected': Colors.red, // Rejected
|
||||
// 'Cancelled': Colors.redAccent, // Cancelled
|
||||
// 'Closed': Colors.grey, // Closed
|
||||
};
|
||||
|
||||
// Determine the color based on the claimStatus
|
||||
|
||||
@ -601,6 +601,7 @@ class _ClaimHistoryPopupState extends State<ClaimHistoryPopup> {
|
||||
Widget _getStepTitleFromApi(String status, Map<String, dynamic> data) {
|
||||
final modifiedBy = data['modified_by'] ?? '';
|
||||
final modifiedAt = data['modified_at'] ?? '';
|
||||
final symbol = (data['modified_by'] != null && data['modified_by'] != '') ? ' - ' : '';
|
||||
final isDesktop = Responsive.isDesktop(context);
|
||||
|
||||
return RichText(
|
||||
@ -615,7 +616,7 @@ class _ClaimHistoryPopupState extends State<ClaimHistoryPopup> {
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' ($modifiedBy – $modifiedAt)',
|
||||
text: ' ($modifiedBy$symbol$modifiedAt)',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: Responsive.isDesktop(context) ? 14 : 11,
|
||||
fontWeight: FontWeight.w400,
|
||||
|
||||
@ -1053,13 +1053,23 @@ class _HomeState extends State<Home> {
|
||||
crossAxisCount: Responsive.isDesktop(context) ? 2 : 1,
|
||||
crossAxisSpacing: 20.0,
|
||||
mainAxisSpacing: 20.0,
|
||||
childAspectRatio: Responsive.isDesktop(context) ? 3.2 : 2.8),
|
||||
childAspectRatio: Responsive.isDesktop(context) ? 2.2 : 2.6),
|
||||
itemCount: data.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
var item = data[index];
|
||||
String policyHeading = item['heading'];
|
||||
String policyName = item['policy_name'];
|
||||
String si_value = item['si_value'];
|
||||
// String si_value = item['si_value'];
|
||||
String siValueStr = item['si_value'] ?? '0';
|
||||
String settledStr = item['total_settled_amount']?.toString() ?? '0';
|
||||
|
||||
double siValue = double.tryParse(siValueStr) ?? 0;
|
||||
double settled = double.tryParse(settledStr) ?? 0;
|
||||
|
||||
// Main logic
|
||||
double finalValue = (settled == 0) ? siValue : (siValue - settled);
|
||||
|
||||
print("Final Value: $finalValue");
|
||||
String policyEndDate = item['policy_end_date'];
|
||||
List<dynamic> employeePolicy = item['EmployeePolicy'];
|
||||
String memberNames = getMemberNames(employeePolicy);
|
||||
@ -1188,7 +1198,7 @@ class _HomeState extends State<Home> {
|
||||
children: [
|
||||
Text(
|
||||
formatToCroresLakhsAndThousands(
|
||||
si_value),
|
||||
siValueStr),
|
||||
textAlign: TextAlign.left,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
@ -1247,7 +1257,34 @@ class _HomeState extends State<Home> {
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 7),
|
||||
SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 12,
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
'Remaining Amount: ${finalValue}',
|
||||
textAlign: TextAlign.right,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
Responsive.isDesktop(
|
||||
context)
|
||||
? 10
|
||||
: 10,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xFF747474),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// SizedBox(height: 7),
|
||||
],
|
||||
))),
|
||||
],
|
||||
|
||||
@ -24,6 +24,8 @@ import 'package:file_picker/file_picker.dart';
|
||||
import '../service/SessionManager.dart';
|
||||
import '../service/TokenService.dart';
|
||||
import '../service/popup_helper.dart';
|
||||
import 'package:pdf/widgets.dart' as pw;
|
||||
import 'package:printing/printing.dart';
|
||||
|
||||
class planclaimsform extends StatefulWidget {
|
||||
final Map<String, dynamic>? details;
|
||||
@ -634,29 +636,73 @@ class _planclaimsformState extends State<planclaimsform> {
|
||||
}
|
||||
|
||||
// ✅ NEW VALIDATION: At least one PDF must be uploaded
|
||||
bool hasPdf = uploadedFiles.any((uf) {
|
||||
final ext = uf.file.extension?.toLowerCase() ?? '';
|
||||
return ext == 'pdf';
|
||||
});
|
||||
|
||||
if (!hasPdf) {
|
||||
ToastHelper.showErrorToast(context, 'Please upload at least one PDF document');
|
||||
setState(() => isLoading = false);
|
||||
return;
|
||||
}
|
||||
// bool hasPdf = uploadedFiles.any((uf) {
|
||||
// final ext = uf.file.extension?.toLowerCase() ?? '';
|
||||
// return ext == 'pdf';
|
||||
// });
|
||||
//
|
||||
// if (!hasPdf) {
|
||||
// ToastHelper.showErrorToast(context, 'Please upload at least one PDF document');
|
||||
// setState(() => isLoading = false);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Add files
|
||||
// for (var uf in uploadedFiles) {
|
||||
// final pf = uf.file;
|
||||
// if (pf.bytes != null) {
|
||||
// request.files.add(http.MultipartFile.fromBytes(
|
||||
// 'claim_docs[]',
|
||||
// pf.bytes!,
|
||||
// filename: pf.name,
|
||||
// ));
|
||||
// }
|
||||
// }
|
||||
|
||||
// Add files — convert images to PDF if needed
|
||||
for (var uf in uploadedFiles) {
|
||||
final pf = uf.file;
|
||||
final ext = pf.extension?.toLowerCase() ?? '';
|
||||
|
||||
if (pf.bytes != null) {
|
||||
request.files.add(http.MultipartFile.fromBytes(
|
||||
'claim_docs[]',
|
||||
pf.bytes!,
|
||||
filename: pf.name,
|
||||
));
|
||||
Uint8List fileBytes = pf.bytes!;
|
||||
|
||||
if (['jpg', 'jpeg', 'png', 'heic'].contains(ext)) {
|
||||
// ✅ Convert image → PDF
|
||||
final pdf = pw.Document();
|
||||
final image = pw.MemoryImage(fileBytes);
|
||||
|
||||
pdf.addPage(
|
||||
pw.Page(
|
||||
build: (pw.Context context) => pw.Center(
|
||||
child: pw.Image(image, fit: pw.BoxFit.contain),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
fileBytes = await pdf.save(); // converted PDF bytes
|
||||
|
||||
// replace file name with .pdf extension
|
||||
final pdfFileName = pf.name.replaceAll(RegExp(r'\.\w+$'), '.pdf');
|
||||
|
||||
print('📄 Converted image ${pf.name} → PDF ($pdfFileName)');
|
||||
request.files.add(http.MultipartFile.fromBytes(
|
||||
'claim_docs[]',
|
||||
fileBytes,
|
||||
filename: pdfFileName,
|
||||
));
|
||||
} else {
|
||||
// ✅ Already a PDF
|
||||
request.files.add(http.MultipartFile.fromBytes(
|
||||
'claim_docs[]',
|
||||
fileBytes,
|
||||
filename: pf.name,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ✅ Combine all names into a JSON array string
|
||||
final claimDocNames = uploadedFiles.map((uf) => uf.label.trim()).toList();
|
||||
final encodedNames = jsonEncode(claimDocNames);
|
||||
|
||||
@ -787,10 +787,10 @@ class _profileState extends State<profile> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// ✅ Change Password Button
|
||||
// if(Responsive.isDesktop(context))
|
||||
// _buildChangePasswordButton(context),
|
||||
if(Responsive.isDesktop(context))
|
||||
_buildChangePasswordButton(context),
|
||||
|
||||
// const SizedBox(width: 10),
|
||||
const SizedBox(width: 10),
|
||||
|
||||
// ✅ Logout Button
|
||||
Responsive.isDesktop(context)
|
||||
|
||||
@ -146,6 +146,7 @@ class ApiService {
|
||||
await _initializeToken();
|
||||
}
|
||||
final url = Uri.parse('${Environment.apiUrl}getWellnessURL?emp_id=$empPrimaryId');
|
||||
// final url = Uri.parse('${Environment.apiUrl}getWellnessURL?emp_id=$empPrimaryId&client_policy_id=$client_policy_id');
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_postToken' ?? '',
|
||||
};
|
||||
|
||||
@ -41,12 +41,25 @@ class _setPasswordState extends State<setPassword> {
|
||||
bool _obscureNewPassword = true;
|
||||
bool _obscureConfirmPassword = true;
|
||||
late SessionManager session;
|
||||
bool hasMinLength = false;
|
||||
bool hasUpperLower = false;
|
||||
bool hasNumber = false;
|
||||
bool hasSpecialChar = false;
|
||||
bool get isPasswordValid => hasMinLength && hasUpperLower && hasNumber && hasSpecialChar;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void validatePassword(String password) {
|
||||
setState(() {
|
||||
hasMinLength = password.length >= 8;
|
||||
hasUpperLower = RegExp(r'(?=.*[A-Za-z])').hasMatch(password);
|
||||
hasNumber = RegExp(r'(?=.*\d)').hasMatch(password);
|
||||
hasSpecialChar = RegExp(r'(?=.*[@$!%*#?&])').hasMatch(password);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> resetYourPassword() async {
|
||||
final newPassword = newPasswordController.text.trim();
|
||||
@ -348,7 +361,7 @@ class _setPasswordState extends State<setPassword> {
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"Welcome to Nhance",
|
||||
"Set a new password",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
@ -372,7 +385,7 @@ class _setPasswordState extends State<setPassword> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Login with your to review and enroll for exciting health benefits for you and your family",
|
||||
"Create a new password. Ensure it differs from previous ones for security",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Color(0xFF000000)),
|
||||
@ -391,70 +404,58 @@ class _setPasswordState extends State<setPassword> {
|
||||
// 🔹 Password Field
|
||||
Container(
|
||||
height: 55,
|
||||
margin: Responsive.isDesktop(
|
||||
context)
|
||||
? const EdgeInsets
|
||||
.symmetric(
|
||||
horizontal: 150)
|
||||
: const EdgeInsets
|
||||
.symmetric(
|
||||
horizontal: 0),
|
||||
margin: Responsive.isDesktop(context)
|
||||
? const EdgeInsets.symmetric(horizontal: 150)
|
||||
: const EdgeInsets.symmetric(horizontal: 0),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: Colors.grey),
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
10),
|
||||
border: Border.all(width: 1, color: Colors.grey),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: TextFormField(
|
||||
controller:
|
||||
newPasswordController,
|
||||
obscureText:
|
||||
_obscureNewPassword,
|
||||
textAlignVertical:
|
||||
TextAlignVertical
|
||||
.center,
|
||||
controller: newPasswordController,
|
||||
obscureText: _obscureNewPassword,
|
||||
onChanged: validatePassword,
|
||||
textAlignVertical: TextAlignVertical.center,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText:
|
||||
"New Password",
|
||||
contentPadding:
|
||||
const EdgeInsets
|
||||
.symmetric(
|
||||
horizontal: 10),
|
||||
hintText: "New Password",
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
_obscureNewPassword
|
||||
? Icons
|
||||
.visibility_off
|
||||
: Icons
|
||||
.visibility,
|
||||
_obscureNewPassword ? Icons.visibility_off : Icons.visibility,
|
||||
color: Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_obscureNewPassword =
|
||||
!_obscureNewPassword;
|
||||
_obscureNewPassword = !_obscureNewPassword;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null ||
|
||||
value.isEmpty) {
|
||||
return 'Please enter your new password';
|
||||
}
|
||||
if (value.length < 6) {
|
||||
return 'Password must be at least 6 characters';
|
||||
}
|
||||
if (!RegExp(
|
||||
r'^(?=.*[A-Z])(?=.*[0-9]).{6,}$')
|
||||
.hasMatch(value)) {
|
||||
return 'Include at least 1 uppercase letter and 1 number';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
// 🔹 VALIDATION LIST
|
||||
Padding(
|
||||
padding: Responsive.isDesktop(context)
|
||||
? const EdgeInsets.symmetric(horizontal: 150)
|
||||
: const EdgeInsets.symmetric(horizontal: 5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _buildCheckItem(hasMinLength, "Minimum 8 characters")),
|
||||
Expanded(child: _buildCheckItem(hasSpecialChar, "1 special character")),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _buildCheckItem(hasUpperLower, "1 UPPER or lower case")),
|
||||
Expanded(child: _buildCheckItem(hasNumber, "1 numerical")),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
@ -561,7 +562,7 @@ class _setPasswordState extends State<setPassword> {
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
"Reset Password",
|
||||
"Update Password",
|
||||
style: GoogleFonts
|
||||
.poppins(
|
||||
color: Color(
|
||||
@ -692,4 +693,28 @@ class _setPasswordState extends State<setPassword> {
|
||||
)),
|
||||
)));
|
||||
}
|
||||
|
||||
Widget _buildCheckItem(bool status, String text) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
status ? Icons.check : Icons.close,
|
||||
color: status ? Colors.green : Colors.red,
|
||||
size: 18,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
color: status ? Colors.green : Colors.red,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||
#include <printing/printing_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
@ -17,6 +18,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
|
||||
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) printing_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "PrintingPlugin");
|
||||
printing_plugin_register_with_registrar(printing_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
file_selector_linux
|
||||
flutter_secure_storage_linux
|
||||
printing
|
||||
url_launcher_linux
|
||||
)
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ import google_sign_in_ios
|
||||
import local_auth_darwin
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import printing
|
||||
import shared_preferences_foundation
|
||||
import sqflite_darwin
|
||||
import url_launcher_macos
|
||||
@ -28,6 +29,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin"))
|
||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
PrintingPlugin.register(with: registry.registrar(forPlugin: "PrintingPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
|
||||
@ -67,6 +67,7 @@ dependencies:
|
||||
universal_html: ^2.2.4
|
||||
go_router: ^16.2.2
|
||||
flutter_secure_storage: ^9.2.4
|
||||
printing: ^5.14.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include <flutter_inappwebview_windows/flutter_inappwebview_windows_plugin_c_api.h>
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
#include <local_auth_windows/local_auth_plugin.h>
|
||||
#include <printing/printing_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
@ -21,6 +22,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||
LocalAuthPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("LocalAuthPlugin"));
|
||||
PrintingPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("PrintingPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_inappwebview_windows
|
||||
flutter_secure_storage_windows
|
||||
local_auth_windows
|
||||
printing
|
||||
url_launcher_windows
|
||||
)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user