1459 lines
66 KiB
Dart
Executable File
1459 lines
66 KiB
Dart
Executable File
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:jwt_decode/jwt_decode.dart';
|
|
import 'package:nhance_app_pwa/customAppBar/customAppBar.dart';
|
|
import 'package:nhance_app_pwa/pages/postEnrollment/service/api_service.dart';
|
|
import 'package:nhance_app_pwa/pages/postEnrollment/service/svg_service.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
import '../../customAppBar/customFooter.dart';
|
|
import '../helpers/custom_download_snackbar.dart';
|
|
import '../helpers/ecard_download_service.dart';
|
|
import '../helpers/ecard_download_notification_service.dart';
|
|
import '../../customAppBar/responsive.dart';
|
|
import '../../customAppBar/tabs.dart';
|
|
import '../../customAppBar/toastHelper.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
|
|
import '../service/SessionManager.dart';
|
|
import '../service/TokenService.dart';
|
|
import '../service/popup_helper.dart';
|
|
|
|
import 'package:nhance_app_pwa/logger.dart';
|
|
|
|
class policies extends StatefulWidget {
|
|
final Map<String, dynamic>? arguments;
|
|
const policies({super.key, this.arguments});
|
|
|
|
@override
|
|
State<policies> createState() => _policiesState();
|
|
}
|
|
|
|
class _policiesState extends State<policies> {
|
|
late ApiService apiService;
|
|
final EcardDownloadService _ecardDownloadService = const EcardDownloadService();
|
|
final session = SessionManager();
|
|
int _currentIndex = 0;
|
|
bool isActive = true;
|
|
dynamic _token;
|
|
dynamic empCodeString;
|
|
dynamic empPrimaryId;
|
|
dynamic empName;
|
|
dynamic mobileNo;
|
|
dynamic client_branch_id;
|
|
dynamic client_id;
|
|
dynamic policyList;
|
|
dynamic policyDataIsEmpty = 1;
|
|
dynamic policyHeading;
|
|
dynamic policyName;
|
|
dynamic EmployeePolicy;
|
|
List<Map<String, String>> employeeDetails = [];
|
|
dynamic argumentsData;
|
|
bool ECardHide = true;
|
|
bool _isExpanded = false;
|
|
bool _isDownloadingEcard = false;
|
|
|
|
void _onTabChanged(int index) {
|
|
setState(() {
|
|
_currentIndex = index;
|
|
});
|
|
}
|
|
|
|
void _toggleExpansion() {
|
|
setState(() {
|
|
_isExpanded = !_isExpanded;
|
|
});
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
apiService = ApiService(context); // Initialize ApiService here
|
|
_loadToken();
|
|
EcardDownloadNotificationService.ensureInitialized();
|
|
if (!kIsWeb) {
|
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
|
await _ecardDownloadService.ensureStorageAccess();
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
}
|
|
|
|
Future<void> _loadToken() async {
|
|
logDebug('_loadToken');
|
|
final String? token = await TokenService.getPostToken();
|
|
_token = token;
|
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
if (token != null && token.isNotEmpty) {
|
|
// Decode the JWT token received from the API response
|
|
mobileNo = session.mobileNo;
|
|
client_branch_id = session.empClientBranchId;
|
|
empCodeString = session.empCodeString;
|
|
empName = session.gpaEmpName;
|
|
logDebug(empCodeString); // Check if emp_code is correct
|
|
empPrimaryId = session.empPrimaryId;
|
|
client_id = session.client_id;
|
|
}
|
|
}
|
|
|
|
Future<void> getEcardDownload(id) async {
|
|
if (_isDownloadingEcard) return;
|
|
if (!mounted) return;
|
|
setState(() => _isDownloadingEcard = true);
|
|
|
|
try {
|
|
final clientPolicyID = widget.arguments?['client_policy_id'];
|
|
final policyNo = widget.arguments?['policy_no'];
|
|
final eCarDParams = {
|
|
'id': id,
|
|
'emp_code': empCodeString,
|
|
'client_policy_id': clientPolicyID,
|
|
'policy_no': policyNo,
|
|
};
|
|
final response = await apiService.getEcardRequest(eCarDParams);
|
|
if (!mounted) return;
|
|
|
|
final data = response['data'];
|
|
if (data is! Map) {
|
|
ToastHelper.showErrorToast(context, 'Unable to download E-Card');
|
|
return;
|
|
}
|
|
|
|
final ecardDownloadUrl = data['eCardDownload'];
|
|
final message = data['message']?.toString();
|
|
if (ecardDownloadUrl == null || ecardDownloadUrl.toString().isEmpty) {
|
|
logDebug('❌ Error: $message');
|
|
ToastHelper.showErrorToast(
|
|
context,
|
|
message ?? 'E-Card is not available',
|
|
);
|
|
return;
|
|
}
|
|
|
|
final url = ecardDownloadUrl.toString();
|
|
logDebug('✅ E-Card URL: $url');
|
|
final safePolicyNo = policyNo?.toString().replaceAll(RegExp(r'[^\w\-.]'), '_');
|
|
final fileName = safePolicyNo == null || safePolicyNo.isEmpty
|
|
? 'ecard.pdf'
|
|
: 'ecard_$safePolicyNo.pdf';
|
|
|
|
if (!kIsWeb) {
|
|
CustomDownloadSnackbar.show(
|
|
context,
|
|
message: 'Downloading eCard...',
|
|
);
|
|
}
|
|
|
|
final result = await _ecardDownloadService.downloadEcard(
|
|
url: url,
|
|
fileName: fileName,
|
|
headers: {
|
|
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
|
if (_token != null && _token.toString().isNotEmpty)
|
|
'Authorization': 'Bearer ${_token.toString()}',
|
|
},
|
|
);
|
|
if (!mounted) return;
|
|
|
|
if (result.success) {
|
|
if (kIsWeb) {
|
|
ToastHelper.showSuccessToast(
|
|
context,
|
|
result.message ?? 'E-Card downloaded',
|
|
);
|
|
} else {
|
|
CustomDownloadSnackbar.show(
|
|
context,
|
|
message: result.message ?? 'eCard downloaded successfully',
|
|
);
|
|
if (result.savedPath != null && result.savedPath!.isNotEmpty) {
|
|
await EcardDownloadNotificationService.showDownloadCompleted(
|
|
filePath: result.savedPath!,
|
|
fileName: fileName,
|
|
);
|
|
}
|
|
}
|
|
} else {
|
|
if (kIsWeb) {
|
|
ToastHelper.showErrorToast(
|
|
context,
|
|
result.message ?? 'Could not download E-Card',
|
|
);
|
|
} else {
|
|
CustomDownloadSnackbar.show(
|
|
context,
|
|
message: result.message ?? 'Download failed',
|
|
);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
logDebug('E-Card download error: $e');
|
|
if (mounted) {
|
|
ToastHelper.showErrorToast(
|
|
context,
|
|
'Unable to download E-Card. Please try again.',
|
|
);
|
|
}
|
|
} finally {
|
|
if (mounted) setState(() => _isDownloadingEcard = false);
|
|
}
|
|
}
|
|
|
|
String convertDateFormat(String date) {
|
|
// Define input and output date formats
|
|
DateFormat inputFormat = DateFormat('dd-MMM-yyyy');
|
|
DateFormat outputFormat = DateFormat('d MMM yyyy');
|
|
|
|
// Parse the input date string
|
|
DateTime parsedDate = inputFormat.parse(date);
|
|
|
|
// Format the parsed date to the desired output format
|
|
String formattedDate = outputFormat.format(parsedDate);
|
|
|
|
return formattedDate;
|
|
}
|
|
|
|
String formatDob(String dob) {
|
|
try {
|
|
final date = DateTime.parse(dob); // input format: yyyy-MM-dd
|
|
return DateFormat("d MMM yyyy").format(date); // output: 18 Jul 1988
|
|
} catch (e) {
|
|
return dob; // fallback in case of error
|
|
}
|
|
}
|
|
|
|
Future<void> _openUrl(String url) async {
|
|
final uri = Uri.tryParse(url);
|
|
if (uri == null) {
|
|
logDebug('Could not launch URL');
|
|
return;
|
|
}
|
|
if (await canLaunchUrl(uri)) {
|
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
|
} else {
|
|
logDebug('Could not launch URL');
|
|
}
|
|
}
|
|
|
|
DateTime _parseDob(String dob) {
|
|
try {
|
|
// Expected format: dd-MM-yyyy
|
|
final parts = dob.split('-');
|
|
if (parts.length == 3) {
|
|
return DateTime(
|
|
int.parse(parts[2]),
|
|
int.parse(parts[1]),
|
|
int.parse(parts[0]),
|
|
);
|
|
}
|
|
} catch (_) {}
|
|
return DateTime(1900); // fallback
|
|
}
|
|
|
|
List<Map<String, dynamic>> sortEmployeeDetails(
|
|
List<Map<String, dynamic>> list) {
|
|
|
|
int priority(String r) {
|
|
final rel = r.toLowerCase();
|
|
|
|
if (rel == 'self') return 1;
|
|
if (rel == 'spouse') return 2;
|
|
if (rel == 'son' || rel == 'daughter' || rel == 'child') return 3;
|
|
if (rel == 'father') return 4;
|
|
if (rel == 'mother') return 5;
|
|
if (rel == 'father in law') return 6;
|
|
if (rel == 'mother in law') return 7;
|
|
|
|
return 99;
|
|
}
|
|
|
|
DateTime parseDob(String dob) {
|
|
final parts = dob.split(' ');
|
|
final day = int.parse(parts[0]);
|
|
final monthMap = {
|
|
'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4,
|
|
'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8,
|
|
'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12,
|
|
};
|
|
final month = monthMap[parts[1]]!;
|
|
final year = int.parse(parts[2]);
|
|
return DateTime(year, month, day);
|
|
}
|
|
|
|
list.sort((a, b) {
|
|
final p1 = priority(a['relationship']);
|
|
final p2 = priority(b['relationship']);
|
|
|
|
// main relationship order
|
|
if (p1 != p2) return p1.compareTo(p2);
|
|
|
|
// ONLY children → oldest first
|
|
if (p1 == 3) {
|
|
final d1 = parseDobSafe(a['dob']);
|
|
final d2 = parseDobSafe(b['dob']);
|
|
return d1.compareTo(d2); // older first
|
|
}
|
|
|
|
return 0;
|
|
});
|
|
|
|
|
|
return list;
|
|
}
|
|
|
|
DateTime parseDobSafe(String dob) {
|
|
try {
|
|
// Case 1: yyyy-MM-dd → 2015-05-05
|
|
if (dob.contains('-') && dob.length == 10) {
|
|
return DateTime.parse(dob);
|
|
}
|
|
|
|
// Case 2: d MMM yyyy → 1 Feb 1996
|
|
final parts = dob.split(' ');
|
|
final day = int.parse(parts[0]);
|
|
final monthMap = {
|
|
'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4,
|
|
'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8,
|
|
'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12,
|
|
};
|
|
final month = monthMap[parts[1]]!;
|
|
final year = int.parse(parts[2]);
|
|
|
|
return DateTime(year, month, day);
|
|
} catch (e) {
|
|
// fallback → push invalid dates to bottom
|
|
return DateTime(3000);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// dynamic arguments = ModalRoute.of(context)!.settings.arguments;
|
|
final arguments = widget.arguments;
|
|
logDebug('arguments');
|
|
logDebug(arguments);
|
|
if (arguments != null && arguments is Map<String, dynamic>) {
|
|
argumentsData = arguments;
|
|
if (argumentsData.containsKey('EmployeePolicy') &&
|
|
argumentsData['EmployeePolicy'] is List) {
|
|
// Clear the employeeDetails list to remove previous data
|
|
employeeDetails.clear();
|
|
// Iterate over each employee in the 'EmployeePolicy' list
|
|
argumentsData['EmployeePolicy'].forEach((employee) {
|
|
// Extract name and relationship and add to employeeDetails array
|
|
String name = employee['name'];
|
|
String relationship = employee['relationship'];
|
|
String dob = employee['dob'];
|
|
String gender = employee['gender'];
|
|
String id = employee['id'];
|
|
employeeDetails.add({'id':id,'name': name, 'relationship': relationship,'dob':dob,'gender':gender});
|
|
});
|
|
}
|
|
setState(() {
|
|
if(argumentsData['policy_type'] == 'GMC' || argumentsData['policy_type'] == 'GMC - Parents' || argumentsData['policy_type'] == 'GMC - Topup' || argumentsData['policy_type'] == 'GMC - Topup(Parents)'){
|
|
ECardHide = true;
|
|
} else {
|
|
ECardHide = false;
|
|
}
|
|
});
|
|
|
|
sortEmployeeDetails(employeeDetails);
|
|
logDebug('employeeDetails');
|
|
logDebug(employeeDetails);
|
|
}
|
|
return PopScope(
|
|
canPop: false,
|
|
onPopInvokedWithResult: (didPop, result) {
|
|
if (didPop) return;
|
|
// context.go('/home');
|
|
context.pop();
|
|
},
|
|
child: Scaffold(
|
|
backgroundColor: Colors.white,
|
|
appBar: CustomAppBar(),
|
|
body: Stack(children: [
|
|
SingleChildScrollView(
|
|
child: Container(
|
|
padding: Responsive.isDesktop(context)
|
|
? EdgeInsets.symmetric(
|
|
horizontal: MediaQuery.of(context).size.width *
|
|
0.2, // 30% of screen width as horizontal padding
|
|
vertical: MediaQuery.of(context).size.height *
|
|
0.03, // 5% of screen height as vertical padding
|
|
)
|
|
: EdgeInsets.all(0),
|
|
color:
|
|
Responsive.isDesktop(context) ? Colors.white : Color(0xFFFFFCE5),
|
|
child: Column(children: [
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color:
|
|
Color(0xFFFFFCE5), // Set background color for the container
|
|
borderRadius: BorderRadius.circular(
|
|
10), // Set border radius for the container
|
|
),
|
|
padding: Responsive.isDesktop(context)
|
|
? EdgeInsets.only(top: 20, bottom: 20, left: 25, right: 25)
|
|
: EdgeInsets.only(top: 10, bottom: 10, left: 10, right: 10),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
Expanded(
|
|
flex: 1,
|
|
child: InkWell(
|
|
onTap: () {
|
|
// context.go('/home');
|
|
context.pop();
|
|
},
|
|
child: Icon(
|
|
Icons
|
|
.chevron_left, // Replace with your desired icon
|
|
color: Color(0xFF000000),
|
|
size: 30,
|
|
),
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 11,
|
|
child: Row(
|
|
mainAxisAlignment: Responsive.isDesktop(context)
|
|
? MainAxisAlignment.start
|
|
: MainAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
argumentsData['policy_name'] ?? '',
|
|
textAlign: TextAlign.start,
|
|
style: GoogleFonts.poppins(
|
|
fontSize:
|
|
Responsive.isDesktop(context) ? 20 : 16,
|
|
fontWeight: FontWeight.w600,
|
|
color: Color(0xFF000000),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
)
|
|
],
|
|
),
|
|
SizedBox(
|
|
height: Responsive.isDesktop(context)
|
|
? 20
|
|
: 20), // Space between rows
|
|
Column(
|
|
children: [
|
|
Responsive.isDesktop(context)
|
|
? buildDesktopLayout(context)
|
|
: buildMobileLayout(context)
|
|
],
|
|
),
|
|
SizedBox(
|
|
height: Responsive.isDesktop(context)
|
|
? 40
|
|
: 30), // Space between rows
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
if(ECardHide)
|
|
Expanded(
|
|
flex: Responsive.isDesktop(context) ? 4 : 6,
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
setState(() {});
|
|
},
|
|
child: Material(
|
|
elevation: 0,
|
|
borderRadius: BorderRadius.circular(5),
|
|
color: Color(0xFFFFF8BF),
|
|
child: SizedBox(
|
|
width: Responsive.isDesktop(context)
|
|
? 200
|
|
: 180,
|
|
child: TextButton(
|
|
onPressed: _isDownloadingEcard
|
|
? null
|
|
: () {
|
|
getEcardDownload(empPrimaryId);
|
|
// if (argumentsData['eCardDownload'] !=
|
|
// null) {
|
|
// _launchURL(
|
|
// argumentsData['eCardDownload']);
|
|
// } else {
|
|
// ToastHelper.showInfoToast(
|
|
// context, 'Not Generated');
|
|
// }
|
|
},
|
|
style: TextButton.styleFrom(
|
|
padding: EdgeInsets.only(
|
|
top: 5,
|
|
bottom: 5,
|
|
left: 15,
|
|
right: 15),
|
|
// primary: Color(0xFF000000),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
SvgPicture.string(
|
|
SvgService.getSvg('ECard'),
|
|
width: 25,
|
|
height: 25,
|
|
),
|
|
SizedBox(
|
|
width:
|
|
8), // Adjust space between icon and text
|
|
Text(
|
|
'E-Card',
|
|
style: GoogleFonts.poppins(
|
|
fontSize: Responsive.isDesktop(
|
|
context)
|
|
? 16
|
|
: 12,
|
|
fontWeight: FontWeight.w600,
|
|
color: Color(0xFF000000),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
))),
|
|
)),
|
|
// if (Responsive.isDesktop(context))
|
|
// Expanded(flex: 4, child: Container()),
|
|
// if(argumentsData['policy_type'] != 'OPD')
|
|
Expanded(
|
|
flex: Responsive.isDesktop(context) ? 4 : 6,
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
child: GestureDetector(
|
|
onTap: () {},
|
|
child: Material(
|
|
elevation: 0,
|
|
borderRadius: BorderRadius.circular(5),
|
|
color: Color(0xFFFFF8BF),
|
|
child: SizedBox(
|
|
width: Responsive.isDesktop(context)
|
|
? 200
|
|
: 180,
|
|
child: TextButton(
|
|
onPressed: () {
|
|
context.push('/claims');
|
|
},
|
|
style: TextButton.styleFrom(
|
|
padding:
|
|
Responsive.isDesktop(context)
|
|
? EdgeInsets.only(
|
|
top: 5,
|
|
bottom: 5,
|
|
left: 15,
|
|
right: 15)
|
|
: EdgeInsets.only(
|
|
top: 3,
|
|
bottom: 3,
|
|
left: 10,
|
|
right: 10)
|
|
// primary: Color(0xFF000000),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
SvgPicture.string(
|
|
SvgService.getSvg('fileaclaims'),
|
|
width: 25,
|
|
height: 25,
|
|
),
|
|
SizedBox(
|
|
width:
|
|
8), // Adjust space between icon and text
|
|
Text(
|
|
'Initiate a Claim',
|
|
style: GoogleFonts.poppins(
|
|
fontSize: Responsive.isDesktop(
|
|
context)
|
|
? 16
|
|
: 12,
|
|
fontWeight: FontWeight.w600,
|
|
color: Color(0xFF000000),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
))),
|
|
)),
|
|
],
|
|
),
|
|
SizedBox(height: Responsive.isDesktop(context) ? 30 : 20),
|
|
// Add more rows as needed
|
|
],
|
|
),
|
|
),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white, // Set background color for the container
|
|
borderRadius: BorderRadius.only(
|
|
topLeft: Radius.circular(40.0),
|
|
topRight: Radius.circular(40.0),
|
|
), // Set border radius for the container
|
|
),
|
|
padding: Responsive.isDesktop(context)
|
|
? EdgeInsets.only(top: 15, bottom: 15, left: 0, right: 0)
|
|
: EdgeInsets.only(top: 20, bottom: 10, left: 10, right: 10),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Card(
|
|
elevation: 0,
|
|
shape: RoundedRectangleBorder(
|
|
side: BorderSide(
|
|
color: Color(0xFFD9D9D9), // Set the border color here
|
|
width: 1.0, // Set the border width here
|
|
),
|
|
borderRadius: BorderRadius.circular(
|
|
8.0), // Set the border radius here
|
|
),
|
|
child: Column(children: [
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Color(
|
|
0xFFECF2FF), // Set background color for the container
|
|
borderRadius: BorderRadius.only(
|
|
topLeft: Radius.circular(10),
|
|
topRight: Radius.circular(
|
|
10)), // Set border radius for the container
|
|
),
|
|
padding: Responsive.isDesktop(context)
|
|
? EdgeInsets.only(
|
|
top: 15, bottom: 15, left: 15, right: 15)
|
|
: EdgeInsets.only(
|
|
top: 20, bottom: 20, left: 10, right: 10),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Expanded(
|
|
flex: 12,
|
|
child: Container(
|
|
alignment: Alignment.centerLeft,
|
|
child: Column(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.start,
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Insured Members',
|
|
textAlign: TextAlign.start,
|
|
style: GoogleFonts.poppins(
|
|
fontSize:
|
|
Responsive.isDesktop(context)
|
|
? 18
|
|
: 12,
|
|
color: Color(0xFF404040),
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
),
|
|
],
|
|
))),
|
|
],
|
|
),
|
|
),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
),
|
|
padding: Responsive.isDesktop(context)
|
|
? EdgeInsets.all(30)
|
|
: EdgeInsets.only(
|
|
top: 15, bottom: 15, left: 20, right: 20),
|
|
child: Column(
|
|
children: employeeDetails.map((detail) {
|
|
int index = employeeDetails.indexOf(detail);
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
border: Border(
|
|
bottom:
|
|
index != employeeDetails.length - 1
|
|
? BorderSide(
|
|
color: Color(0xFFD9D9D9),
|
|
width:
|
|
1.0, // Adjust the width as needed
|
|
)
|
|
: BorderSide.none,
|
|
),
|
|
),
|
|
child: Row(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.center,
|
|
children: [
|
|
Expanded(
|
|
flex: 6,
|
|
child: Container(
|
|
alignment: Alignment.centerLeft,
|
|
padding: Responsive.isDesktop(context)
|
|
? EdgeInsets.only(
|
|
top: 10,
|
|
bottom: 10,
|
|
left: 10,
|
|
right: 10)
|
|
: EdgeInsets.only(
|
|
top: 15,
|
|
bottom: 15,
|
|
left: 7,
|
|
right: 7),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
// 👇 SVG icon based on gender
|
|
if (detail['gender'] == 'M')
|
|
SvgPicture.string(
|
|
SvgService.getSvg('personMale'),
|
|
width: 25,
|
|
height: 25,
|
|
)
|
|
else if (detail['gender'] == 'F')
|
|
SvgPicture.string(
|
|
SvgService.getSvg('personFemale'),
|
|
width: 25,
|
|
height: 25,
|
|
),
|
|
|
|
const SizedBox(width: 6),
|
|
|
|
// Name text
|
|
Text(
|
|
detail['name']!,
|
|
textAlign: TextAlign.start,
|
|
style: GoogleFonts.poppins(
|
|
fontSize: Responsive.isDesktop(context) ? 16 : 14,
|
|
color: const Color(0xFF000000),
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 4),
|
|
|
|
// DOB text
|
|
Text(
|
|
"DOB: ${formatDob(detail['dob']!) ?? '-'}",
|
|
style: GoogleFonts.poppins(
|
|
fontSize: Responsive.isDesktop(context) ? 14 : 12,
|
|
color: const Color(0xFF606060),
|
|
fontWeight: FontWeight.w300,
|
|
),
|
|
),
|
|
],
|
|
)
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 6,
|
|
child: Container(
|
|
alignment: Alignment.centerRight,
|
|
padding: Responsive.isDesktop(context)
|
|
? EdgeInsets.only(
|
|
top: 10,
|
|
bottom: 10,
|
|
left: 10,
|
|
right: 10)
|
|
: EdgeInsets.only(
|
|
top: 15,
|
|
bottom: 15,
|
|
left: 7,
|
|
right: 7),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
if(ECardHide)...[
|
|
Container(
|
|
alignment: Alignment.centerRight,
|
|
child: MouseRegion(
|
|
cursor: SystemMouseCursors.click, // Web pointer
|
|
child: GestureDetector(
|
|
onTap: _isDownloadingEcard
|
|
? null
|
|
: () {
|
|
getEcardDownload(detail['id']);
|
|
},
|
|
child: Tooltip(
|
|
message: 'E-Card',
|
|
waitDuration: const Duration(milliseconds: 300),
|
|
showDuration: const Duration(seconds: 2),
|
|
child: SvgPicture.string(
|
|
SvgService.getSvg('ECard'),
|
|
width: 25,
|
|
height: 25,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 4),
|
|
],
|
|
|
|
Text(
|
|
detail['relationship']!,
|
|
textAlign: TextAlign.end,
|
|
style: GoogleFonts.poppins(
|
|
fontSize:
|
|
Responsive.isDesktop(context)
|
|
? 16
|
|
: 14,
|
|
color: Color(0xFF404040),
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
),
|
|
],
|
|
)
|
|
),
|
|
),
|
|
],
|
|
));
|
|
}).toList(),
|
|
),
|
|
)
|
|
])),
|
|
SizedBox(height: 10),
|
|
Card(
|
|
elevation: 0,
|
|
shape: RoundedRectangleBorder(
|
|
side: BorderSide(
|
|
color: Color(0xFFD9D9D9), // Set the border color here
|
|
width: 1.0, // Set the border width here
|
|
),
|
|
borderRadius: BorderRadius.circular(
|
|
8.0), // Set the border radius here
|
|
),
|
|
child: Column(children: [
|
|
InkWell(
|
|
onTap: _toggleExpansion,
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors
|
|
.white, // Set background color for the container
|
|
),
|
|
padding: Responsive.isDesktop(context)
|
|
? EdgeInsets.all(15)
|
|
: EdgeInsets.symmetric(
|
|
vertical: 20, horizontal: 10),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Expanded(
|
|
flex: 8,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
SvgPicture.string(
|
|
SvgService.getSvg('policyCoverage'),
|
|
width: 25,
|
|
height: 25,
|
|
),
|
|
SizedBox(
|
|
width:
|
|
10), // Adjust space between icon and text
|
|
Text(
|
|
'Policy coverage',
|
|
textAlign: TextAlign.center,
|
|
style: GoogleFonts.poppins(
|
|
fontSize:
|
|
Responsive.isDesktop(context)
|
|
? 18
|
|
: 12,
|
|
fontWeight: FontWeight.w400,
|
|
color: Color(0xFF404040),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 4,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
Icon(
|
|
_isExpanded ? Icons.remove : Icons.add,
|
|
color: Color(0xFFE26728),
|
|
size: 25,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
if (_isExpanded)
|
|
Builder(
|
|
builder: (context) {
|
|
final terms = argumentsData['policy_terms'];
|
|
|
|
if (terms == null || (terms is List && terms.isEmpty) || (terms is Map && terms.isEmpty)) {
|
|
// ✅ Show toast once
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
ToastHelper.showInfoToast(context, 'No policy terms available');
|
|
});
|
|
return const SizedBox(); // Don't render container
|
|
}
|
|
|
|
return Container(
|
|
decoration: const BoxDecoration(
|
|
color: Colors.white,
|
|
),
|
|
padding: Responsive.isDesktop(context)
|
|
? const EdgeInsets.all(30)
|
|
: const EdgeInsets.symmetric(vertical: 15, horizontal: 20),
|
|
child: SingleChildScrollView(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: (() {
|
|
if (terms is Map) {
|
|
// ✅ Case 1: Map<String, dynamic>
|
|
return terms.entries
|
|
.where((entry) => entry.value is String)
|
|
.toList()
|
|
.asMap()
|
|
.entries
|
|
.map<Widget>((entry) {
|
|
int index = entry.key;
|
|
MapEntry value = entry.value;
|
|
bool isLast = index == terms.length - 1;
|
|
|
|
return Container(
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
border: isLast
|
|
? null
|
|
: const Border(
|
|
bottom: BorderSide(
|
|
color: Color(0xFFD9D9D9),
|
|
width: 1.0,
|
|
),
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
|
child: Responsive.isDesktop(context)
|
|
? Row(
|
|
children: [
|
|
Expanded(
|
|
flex: 6,
|
|
child: Text(
|
|
value.key,
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w600,
|
|
color: const Color(0xFF777777),
|
|
),
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 6,
|
|
child: Text(
|
|
value.value,
|
|
textAlign: TextAlign.end,
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w400,
|
|
color: const Color(0xFF000000),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
)
|
|
: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
value.key,
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w600,
|
|
color: const Color(0xFF777777),
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
value.value,
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w400,
|
|
color: const Color(0xFF000000),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}).toList();
|
|
} else if (terms is List) {
|
|
// ✅ Case 2: List
|
|
return terms.map<Widget>((item) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 6.0),
|
|
child: Text(
|
|
item.toString(),
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w400,
|
|
color: const Color(0xFF000000),
|
|
),
|
|
),
|
|
);
|
|
}).toList();
|
|
} else {
|
|
return [const SizedBox()];
|
|
}
|
|
})(),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
|
|
|
|
])),
|
|
SizedBox(height: 10),
|
|
MouseRegion(
|
|
cursor: SystemMouseCursors.click,
|
|
child: GestureDetector(
|
|
onTap: () => {
|
|
context.push('/generalExclusionsDeductibles')
|
|
},
|
|
child: Card(
|
|
elevation: 0,
|
|
shape: RoundedRectangleBorder(
|
|
side: BorderSide(
|
|
color:
|
|
Color(0xFFD9D9D9), // Set the border color here
|
|
width: 1.0, // Set the border width here
|
|
),
|
|
borderRadius: BorderRadius.circular(
|
|
8.0), // Set the border radius here
|
|
),
|
|
child: Column(children: [
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors
|
|
.white, // Set background color for the container
|
|
),
|
|
padding: Responsive.isDesktop(context)
|
|
? EdgeInsets.only(
|
|
top: 15, bottom: 15, left: 15, right: 15)
|
|
: EdgeInsets.only(
|
|
top: 20, bottom: 20, left: 10, right: 10),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Expanded(
|
|
flex: 11,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
SvgPicture.string(
|
|
SvgService.getSvg('general'),
|
|
width: 25,
|
|
height: 25,
|
|
),
|
|
SizedBox(
|
|
width:
|
|
10), // Adjust space between icon and text
|
|
Text(
|
|
'General Exclusions & Deductibles',
|
|
textAlign: TextAlign.center,
|
|
style: GoogleFonts.poppins(
|
|
fontSize:
|
|
Responsive.isDesktop(context)
|
|
? 18
|
|
: 12,
|
|
fontWeight: FontWeight.w400,
|
|
color: Color(0xFF404040),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 1,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
Icon(
|
|
Icons
|
|
.chevron_right, // Replace with your desired icon
|
|
color: Color(0xFFE26728),
|
|
size: 20,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
]),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 10),
|
|
Card(
|
|
elevation: 0,
|
|
shape: RoundedRectangleBorder(
|
|
side: BorderSide(
|
|
color: Color(0xFFD9D9D9), // Set the border color here
|
|
width: 1.0, // Set the border width here
|
|
),
|
|
borderRadius: BorderRadius.circular(
|
|
8.0), // Set the border radius here
|
|
),
|
|
child: Column(children: [
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
// Set background color for the container
|
|
borderRadius: BorderRadius.circular(
|
|
5), // Set border radius for the container
|
|
),
|
|
padding: Responsive.isDesktop(context)
|
|
? EdgeInsets.only(
|
|
top: 15, bottom: 15, left: 25, right: 25)
|
|
: EdgeInsets.only(
|
|
top: 10, bottom: 10, left: 10, right: 10),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Expanded(
|
|
flex: 6,
|
|
child: MouseRegion(
|
|
cursor: SystemMouseCursors.click,
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
context.push('/help');
|
|
},
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
child: Column(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.center,
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.center,
|
|
children: [
|
|
SvgPicture.string(
|
|
SvgService.getSvg('needHelp'),
|
|
width: 25,
|
|
height: 25,
|
|
),
|
|
SizedBox(height: 10),
|
|
Text(
|
|
'Need Help',
|
|
textAlign: TextAlign.center,
|
|
style: GoogleFonts.poppins(
|
|
fontSize:
|
|
Responsive.isDesktop(context)
|
|
? 14
|
|
: 10,
|
|
fontWeight: FontWeight.w400,
|
|
color: Color(0xFF404040),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 6,
|
|
child: MouseRegion(
|
|
cursor: SystemMouseCursors.click,
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
context.push('/claims', extra: 0);
|
|
},
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
child: Column(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.center,
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.center,
|
|
children: [
|
|
SvgPicture.string(
|
|
SvgService.getSvg(
|
|
'cliamHistory'),
|
|
width: 25,
|
|
height: 25,
|
|
),
|
|
SizedBox(height: 10),
|
|
Text(
|
|
'Claims history',
|
|
textAlign: TextAlign.center,
|
|
style: GoogleFonts.poppins(
|
|
fontSize:
|
|
Responsive.isDesktop(
|
|
context)
|
|
? 14
|
|
: 10,
|
|
fontWeight: FontWeight.w400,
|
|
color: Color(0xFF404040),
|
|
),
|
|
),
|
|
],
|
|
))),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
])),
|
|
SizedBox(height: 10),
|
|
if (argumentsData['network_hospitals_url'] != null)
|
|
MouseRegion(
|
|
cursor: SystemMouseCursors.click,
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
final String? url =
|
|
argumentsData['network_hospitals_url'];
|
|
if (url != null && url.isNotEmpty) {
|
|
_openUrl(url);
|
|
} else {
|
|
logDebug('No URL provided');
|
|
}
|
|
},
|
|
child: Card(
|
|
elevation: 0,
|
|
shape: RoundedRectangleBorder(
|
|
side: BorderSide(
|
|
color: Color(0xFFD9D9D9),
|
|
width: 1.0,
|
|
),
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
),
|
|
padding: Responsive.isDesktop(context)
|
|
? EdgeInsets.only(
|
|
top: 15,
|
|
bottom: 15,
|
|
left: 15,
|
|
right: 15)
|
|
: EdgeInsets.only(
|
|
top: 20,
|
|
bottom: 20,
|
|
left: 10,
|
|
right: 10),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Expanded(
|
|
flex: 11,
|
|
child: Row(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.start,
|
|
children: [
|
|
SvgPicture.string(
|
|
SvgService.getSvg('cashLess'),
|
|
width: 25,
|
|
height: 25,
|
|
),
|
|
SizedBox(width: 10),
|
|
Text(
|
|
'Cashless Hospitals',
|
|
textAlign: TextAlign.center,
|
|
style: GoogleFonts.poppins(
|
|
fontSize:
|
|
Responsive.isDesktop(context)
|
|
? 18
|
|
: 12,
|
|
fontWeight: FontWeight.w400,
|
|
color: Color(0xFF404040),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 1,
|
|
child: Row(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.end,
|
|
children: [
|
|
Icon(
|
|
Icons.chevron_right,
|
|
color: Color(0xFFE26728),
|
|
size: 20,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: Responsive.isDesktop(context) ? 40 : 70),
|
|
],
|
|
),
|
|
),
|
|
]),
|
|
)),
|
|
if (Responsive.isDesktop(context))
|
|
Align(
|
|
alignment: Alignment.bottomCenter,
|
|
child: Container(
|
|
width: double.infinity, // Make the footer full width
|
|
child: CustomFooter(),
|
|
),
|
|
),
|
|
]),
|
|
// floatingActionButton: Responsive.isDesktop(context)
|
|
// ? null
|
|
// : FloatingActionButton(
|
|
// onPressed: () {
|
|
// Navigator.pushNamed(context, 'chatbot');
|
|
// },
|
|
// child: Icon(Icons.chat),
|
|
// ),
|
|
floatingActionButtonLocation: Responsive.isDesktop(context)
|
|
? null
|
|
: FloatingActionButtonLocation.miniEndFloat,
|
|
bottomNavigationBar: Responsive.isDesktop(context)
|
|
? null
|
|
: CustomBottomNavigationBar(
|
|
onTabChanged: (index) {
|
|
// Add your navigation logic here
|
|
// repositionBotman();
|
|
if (index == 0) {
|
|
context.push('/home');
|
|
} else if (index == 1) {
|
|
context.push('/claims');
|
|
} else if (index == 2) {
|
|
context.push('/faqs');
|
|
} else if (index == 3) {
|
|
context.push('/profile');
|
|
} else if (index == 4) {
|
|
context.push('/help');
|
|
}
|
|
// else if (index == 4) {
|
|
// // context.push('/wellness');
|
|
// // Wellness tab clicked → show popup
|
|
// if(!isRetailLoggedIn)
|
|
// PopupHelper.showRedirectPopup(
|
|
// context: context,
|
|
// apiService: apiService,
|
|
// empPrimaryId: session.empPrimaryId,
|
|
// );
|
|
// }
|
|
},
|
|
icons: [
|
|
Icons.home_outlined,
|
|
Icons.sticky_note_2_outlined,
|
|
Icons.question_answer_outlined,
|
|
Icons.person_outline_outlined,
|
|
Icons.headset_mic_outlined,
|
|
],
|
|
labels: ["Home", "Claims", "FAQs", "Profile","Help"],
|
|
initialIndex: 0, // Initial index of the bottom navigation bar
|
|
),
|
|
)
|
|
);
|
|
}
|
|
|
|
Widget buildDesktopLayout(BuildContext context) {
|
|
return Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
buildExpandedColumn(
|
|
context, argumentsData['sum_insured_label'], '₹ ${argumentsData['si_value']}'),
|
|
buildExpandedColumn(context, 'Policy No', argumentsData['policy_no']),
|
|
buildExpandedColumn(context, 'Policy Expiry',
|
|
convertDateFormat(argumentsData['policy_end_date'])),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget buildMobileLayout(BuildContext context) {
|
|
return Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
buildExpandedColumn(
|
|
context, 'Policy No', argumentsData['policy_no']),
|
|
// buildExpandedColumn(context, '', ''),
|
|
],
|
|
),
|
|
SizedBox(height: 20),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
buildExpandedColumn(
|
|
context, argumentsData['sum_insured_label'], '₹ ${argumentsData['si_value']}'),
|
|
buildExpandedColumn(context, 'Policy Expiry',
|
|
convertDateFormat(argumentsData['policy_end_date'])),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget buildExpandedColumn(BuildContext context, String title, String value) {
|
|
return Expanded(
|
|
flex: 3,
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Text(
|
|
title,
|
|
textAlign: TextAlign.center,
|
|
style: GoogleFonts.poppins(
|
|
fontSize: Responsive.isDesktop(context) ? 18 : 14,
|
|
fontWeight: FontWeight.w400,
|
|
color: Color(0xFF000000),
|
|
),
|
|
),
|
|
SizedBox(height: Responsive.isDesktop(context) ? 10 : 4),
|
|
Text(
|
|
value,
|
|
textAlign: TextAlign.center,
|
|
style: GoogleFonts.poppins(
|
|
fontSize: Responsive.isDesktop(context) ? 18 : 16,
|
|
fontWeight: FontWeight.w600,
|
|
color: Color(0xFF000000),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
} |