This commit is contained in:
Surendiran 2026-07-06 09:55:31 +05:30
parent 74039d751c
commit 41160cbfaf
13 changed files with 2238 additions and 2127 deletions

View File

@ -19,12 +19,12 @@ if (project.hasProperty('google-services.json')) {
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '67'
flutterVersionCode = '68'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '2.0.28'
flutterVersionName = '2.0.29'
}
def keystoreProperties = new Properties()

View File

@ -0,0 +1,180 @@
import 'package:flutter/material.dart';
import 'package:html/dom.dart' as dom;
import 'package:html/parser.dart' as html_parser;
class AlignedHtmlContent extends StatelessWidget {
final String html;
final TextStyle bodyStyle;
final double markerWidth;
const AlignedHtmlContent({
super.key,
required this.html,
required this.bodyStyle,
this.markerWidth = 32,
});
@override
Widget build(BuildContext context) {
final document = html_parser.parse(html);
final body = document.body;
if (body == null) return const SizedBox.shrink();
return SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: _buildNodes(body.nodes),
),
);
}
List<Widget> _buildNodes(List<dom.Node> nodes) {
final widgets = <Widget>[];
for (final node in nodes) {
widgets.addAll(_buildNode(node));
}
return widgets;
}
List<Widget> _buildNode(dom.Node node) {
if (node is dom.Text) {
final text = _normalizeWhitespace(node.text);
if (text.isEmpty) return [];
return [Text(text, style: bodyStyle)];
}
if (node is! dom.Element) return [];
switch (node.localName) {
case 'p':
final text = _normalizeWhitespace(node.text);
if (text.isEmpty) return [];
return [
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Text(text, style: bodyStyle),
),
];
case 'ol':
return [_buildOrderedList(node, 0)];
case 'ul':
return [_buildUnorderedList(node, 0)];
case 'br':
return [const SizedBox(height: 8)];
default:
return _buildNodes(node.nodes);
}
}
Widget _buildOrderedList(dom.Element ol, double indent) {
final items = ol.children.where((element) => element.localName == 'li');
final children = <Widget>[];
var index = 0;
for (final item in items) {
index += 1;
children.add(
Padding(
padding: EdgeInsets.only(left: indent, bottom: 8),
child: _buildOrderedListItem(item, index, indent),
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: children,
);
}
Widget _buildOrderedListItem(dom.Element li, int number, double indent) {
final leadingText = _liLeadingText(li);
final nestedLists =
li.children.where((element) => element.localName == 'ol' || element.localName == 'ul');
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: markerWidth,
child: Text(
'$number.',
style: bodyStyle.copyWith(
fontFeatures: const [FontFeature.tabularFigures()],
),
),
),
Expanded(
child: Text(
leadingText,
style: bodyStyle,
),
),
],
),
for (final nested in nestedLists)
Padding(
padding: const EdgeInsets.only(top: 8),
child: nested.localName == 'ol'
? _buildOrderedList(nested, indent + markerWidth)
: _buildUnorderedList(nested, indent + markerWidth),
),
],
);
}
Widget _buildUnorderedList(dom.Element ul, double indent) {
final items = ul.children.where((element) => element.localName == 'li');
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
for (final item in items)
Padding(
padding: EdgeInsets.only(left: indent, bottom: 8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: markerWidth,
child: Text(
'',
style: bodyStyle.copyWith(
color: const Color(0xFFE26728),
fontWeight: FontWeight.w600,
),
),
),
Expanded(
child: Text(
_normalizeWhitespace(item.text),
style: bodyStyle,
),
),
],
),
),
],
);
}
String _liLeadingText(dom.Element li) {
final buffer = StringBuffer();
for (final node in li.nodes) {
if (node is dom.Text) {
buffer.write(node.text);
} else if (node is dom.Element &&
node.localName != 'ol' &&
node.localName != 'ul') {
buffer.write(node.text);
}
}
return _normalizeWhitespace(buffer.toString());
}
String _normalizeWhitespace(String value) {
return value.replaceAll(RegExp(r'\s+'), ' ').trim();
}
}

View File

@ -2,9 +2,10 @@ import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:open_filex/open_filex.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
import 'android_download_helper.dart';
import 'download_result.dart';
@ -31,7 +32,7 @@ Future<DownloadResult> downloadEcardImpl({
Map<String, String>? headers,
}) async {
if (Platform.isIOS) {
return _downloadAndShareOnIos(
return _downloadOnIos(
url: url,
fileName: fileName,
headers: headers,
@ -98,51 +99,47 @@ Future<DownloadResult> downloadEcardImpl({
}
}
Future<DownloadResult> _downloadAndShareOnIos({
Future<DownloadResult> _downloadOnIos({
required String url,
required String fileName,
Map<String, String>? headers,
}) async {
try {
final safeFileName = _sanitizeFileName(fileName);
final tempDir = await getTemporaryDirectory();
final filePath = '${tempDir.path}/$safeFileName';
final documentsDir = await getApplicationDocumentsDirectory();
final downloadDir = Directory('${documentsDir.path}/ecards');
if (!await downloadDir.exists()) {
await downloadDir.create(recursive: true);
}
final filePath = '${downloadDir.path}/$safeFileName';
final file = File(filePath);
if (await file.exists()) {
await file.delete();
}
await _dio.download(
url,
filePath,
options: Options(
headers: headers,
responseType: ResponseType.bytes,
),
deleteOnError: true,
);
final response = await http.get(Uri.parse(url), headers: headers);
if (response.statusCode != 200) {
return DownloadResult.failure(
'Download failed (${response.statusCode})',
);
}
await file.writeAsBytes(response.bodyBytes, flush: true);
if (!await file.exists() || await file.length() == 0) {
return DownloadResult.failure('Download failed');
}
await SharePlus.instance.share(
ShareParams(
files: [XFile(filePath)],
text: 'Save eCard to Files',
subject: safeFileName,
),
);
try {
await OpenFilex.open(filePath);
} catch (_) {
// File is saved even if the preview cannot be opened.
}
return DownloadResult.success(
message: 'Choose "Save to Files" to store eCard',
savedPath: filePath,
message: 'E-Card downloaded',
);
} on DioException catch (e) {
final hasStatusCode = e.response?.statusCode != null;
final message = hasStatusCode
? 'Download failed (${e.response!.statusCode})'
: 'Download failed';
return DownloadResult.failure(message);
} catch (_) {
return DownloadResult.failure('Download failed');
}

View File

@ -1,7 +1,6 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:jwt_decode/jwt_decode.dart';
@ -20,6 +19,7 @@ import 'package:video_player/video_player.dart';
import '../service/multi_video_player.dart';
import '../service/popup_helper.dart';
import '../helpers/aligned_html_content.dart';
import 'package:nhance_app_pwa/logger.dart';
class claimprocess extends StatefulWidget {
@ -173,6 +173,101 @@ import 'package:nhance_app_pwa/logger.dart';
ThemeData _buildPageTheme(BuildContext context) {
final isDesktop = Responsive.isDesktop(context);
final baseTheme = Theme.of(context);
return baseTheme.copyWith(
textTheme: GoogleFonts.poppinsTextTheme(baseTheme.textTheme).copyWith(
titleLarge: GoogleFonts.poppins(
fontSize: isDesktop ? 18 : 16,
fontWeight: FontWeight.w600,
color: const Color(0xFF000000),
),
titleMedium: GoogleFonts.poppins(
fontSize: isDesktop ? 18 : 16,
fontWeight: FontWeight.w500,
color: const Color(0xFF000000),
),
bodyLarge: GoogleFonts.poppins(
fontSize: isDesktop ? 16 : 14,
fontWeight: FontWeight.w400,
color: const Color(0xFF000000),
height: 1.5,
),
labelLarge: GoogleFonts.poppins(
fontSize: isDesktop ? 18 : 14,
fontWeight: FontWeight.w500,
color: const Color(0xFF593AFF),
),
labelMedium: GoogleFonts.poppins(
fontSize: isDesktop ? 18 : 14,
fontWeight: FontWeight.w400,
color: const Color(0xFF636363),
),
),
);
}
Widget _buildHtmlContent(BuildContext context, String html) {
final bodyStyle = Theme.of(context).textTheme.bodyLarge ??
GoogleFonts.poppins(fontSize: 14, color: const Color(0xFF000000));
return AlignedHtmlContent(
html: html,
bodyStyle: bodyStyle,
markerWidth: Responsive.isDesktop(context) ? 36 : 32,
);
}
Widget _buildTabLabel({
required BuildContext context,
required String label,
required bool selected,
required VoidCallback onTap,
}) {
final isDesktop = Responsive.isDesktop(context);
final horizontalPadding = isDesktop ? 80.0 : 16.0;
final verticalPadding = isDesktop ? 12.0 : 10.0;
return GestureDetector(
onTap: onTap,
child: selected
? Material(
elevation: 5,
borderRadius: BorderRadius.circular(10),
color: Colors.white,
child: TextButton(
onPressed: onTap,
style: TextButton.styleFrom(
padding: EdgeInsets.symmetric(
horizontal: horizontalPadding,
vertical: verticalPadding,
),
),
child: Text(
label,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.labelLarge,
),
),
)
: Container(
width: double.infinity,
alignment: Alignment.center,
padding: EdgeInsets.symmetric(
horizontal: horizontalPadding,
vertical: verticalPadding,
),
child: Text(
label,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.labelMedium,
),
),
);
}
@override
Widget build(BuildContext context) {
return PopScope(
@ -185,7 +280,9 @@ import 'package:nhance_app_pwa/logger.dart';
child: Scaffold(
backgroundColor: Colors.white,
appBar: CustomAppBar(),
body: Stack(
body: Theme(
data: _buildPageTheme(context),
child: Stack(
children: [
SingleChildScrollView(
child: Container(
@ -194,16 +291,17 @@ import 'package:nhance_app_pwa/logger.dart';
horizontal: MediaQuery.of(context).size.width * 0.2,
vertical: MediaQuery.of(context).size.height * 0.03,
)
: EdgeInsets.all(10),
: const EdgeInsets.fromLTRB(16, 8, 16, 24),
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(vertical: 15, horizontal: 25)
: EdgeInsets.all(0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
@ -238,11 +336,9 @@ import 'package:nhance_app_pwa/logger.dart';
Text(
'Claim Process',
textAlign: TextAlign.start,
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFF000000),
),
style: Theme.of(context)
.textTheme
.titleLarge,
),
],
),
@ -269,165 +365,24 @@ import 'package:nhance_app_pwa/logger.dart';
),
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(vertical: 15, horizontal: 25)
: EdgeInsets.all(10),
: const EdgeInsets.all(8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 12,
child: Container(
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Expanded(
flex: 6,
child: GestureDetector(
onTap: () {
setState(() {
isActive = true;
});
},
child: isActive
? Material(
elevation: 5,
borderRadius:
BorderRadius.circular(
10),
color: Colors.white,
child: TextButton(
onPressed: () {},
style:
TextButton.styleFrom(
padding: EdgeInsets
.symmetric(
horizontal: Responsive
.isDesktop(
context)
? 80
: 40,
vertical: Responsive
.isDesktop(
context)
? 12
: 7,
),
),
child: Text(
cashLessSectionName ??
'',
textAlign:
TextAlign.center,
style:
GoogleFonts.poppins(
fontSize: Responsive
.isDesktop(
context)
? 18
: 14,
fontWeight:
FontWeight.w500,
color:
Color(0xFF593AFF),
),
),
),
)
: Text(
cashLessSectionName ?? '',
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(
context)
? 18
: 14,
fontWeight:
FontWeight.w400,
color: Color(0xFF636363),
),
),
),
),
Expanded(
flex: 6,
child: GestureDetector(
onTap: () {
setState(() {
isActive = false;
});
},
child: !isActive
? Material(
elevation: 5,
borderRadius:
BorderRadius.circular(
10),
color: Colors.white,
child: TextButton(
onPressed: () {},
style:
TextButton.styleFrom(
padding: EdgeInsets
.symmetric(
horizontal: Responsive
.isDesktop(
context)
? 80
: 20,
vertical: Responsive
.isDesktop(
context)
? 12
: 7,
),
),
child: Text(
reimbursementSectionName ??
'',
textAlign:
TextAlign.center,
style:
GoogleFonts.poppins(
fontSize: Responsive
.isDesktop(
context)
? 18
: 14,
fontWeight:
FontWeight.w500,
color:
Color(0xFF593AFF),
),
),
),
)
: Text(
reimbursementSectionName ??
'',
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(
context)
? 18
: 14,
fontWeight:
FontWeight.w400,
color: Color(0xFF636363),
),
),
),
),
],
),
],
),
child: _buildTabLabel(
context: context,
label: cashLessSectionName ?? '',
selected: isActive,
onTap: () => setState(() => isActive = true),
),
),
const SizedBox(width: 8),
Expanded(
child: _buildTabLabel(
context: context,
label: reimbursementSectionName ?? '',
selected: !isActive,
onTap: () => setState(() => isActive = false),
),
),
],
@ -440,42 +395,31 @@ import 'package:nhance_app_pwa/logger.dart';
borderRadius: BorderRadius.circular(5),
),
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(
? const EdgeInsets.symmetric(
vertical: 10, horizontal: 10)
: EdgeInsets.all(10),
: EdgeInsets.zero,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (cashLessContentHtml != null)
Padding(
padding:
EdgeInsets.only(bottom: 10, left: 0),
const EdgeInsets.only(bottom: 16),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
cashLessHeading ?? '',
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context)
? 18
: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
),
textAlign: TextAlign.start,
style: Theme.of(context)
.textTheme
.titleMedium,
),
// SizedBox(height: 5),
Html(
data: cashLessContentHtml!,
style: {
"li": Style(
fontFamily: GoogleFonts.poppins().fontFamily,
fontSize: FontSize(16),
color: const Color(0xFF000000),
margin: Margins.only(bottom: 5),
),
},
const SizedBox(height: 8),
_buildHtmlContent(
context,
cashLessContentHtml!,
),
]
)
@ -483,33 +427,23 @@ import 'package:nhance_app_pwa/logger.dart';
if (cashLessNotesHtml != null)
Padding(
padding:
EdgeInsets.only(bottom: 10, left: 0),
const EdgeInsets.only(bottom: 10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'Notes',
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context)
? 18
: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
),
textAlign: TextAlign.start,
style: Theme.of(context)
.textTheme
.titleMedium,
),
const SizedBox(height: 8),
_buildHtmlContent(
context,
cashLessNotesHtml!,
),
// SizedBox(height: 5),
Html(
data: cashLessNotesHtml!,
style: {
"li": Style(
fontFamily: GoogleFonts.poppins().fontFamily,
fontSize: FontSize(15),
color: const Color(0xFF000000),
),
},
),
],
),
)
@ -521,34 +455,31 @@ import 'package:nhance_app_pwa/logger.dart';
borderRadius: BorderRadius.circular(5),
),
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(
? const EdgeInsets.symmetric(
vertical: 10, horizontal: 10)
: EdgeInsets.all(10),
: EdgeInsets.zero,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (reimbursementContentHtml != null)
Padding(
padding:
EdgeInsets.only(bottom: 10, left: 0),
const EdgeInsets.only(bottom: 16),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
reimbursementHeading ?? '',
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context)
? 18
: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
),
textAlign: TextAlign.start,
style: Theme.of(context)
.textTheme
.titleMedium,
),
// SizedBox(height: 5),
Html(
data: reimbursementContentHtml!,
const SizedBox(height: 8),
_buildHtmlContent(
context,
reimbursementContentHtml!,
),
]
)
@ -557,25 +488,22 @@ import 'package:nhance_app_pwa/logger.dart';
if (reimbursementNotesHtml != null)
Padding(
padding:
EdgeInsets.only(bottom: 10, left: 0),
const EdgeInsets.only(bottom: 10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'Notes',
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context)
? 18
: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
),
textAlign: TextAlign.start,
style: Theme.of(context)
.textTheme
.titleMedium,
),
// SizedBox(height: 5),
Html(
data: reimbursementNotesHtml!,
const SizedBox(height: 8),
_buildHtmlContent(
context,
reimbursementNotesHtml!,
),
]
)
@ -609,6 +537,7 @@ import 'package:nhance_app_pwa/logger.dart';
),
],
),
),
// floatingActionButton: Responsive.isDesktop(context)
// ? null
// : FloatingActionButton(

View File

@ -967,6 +967,267 @@ class _claimsState extends State<claims> {
// ];
// }
TextStyle _registerClaimLabelStyle(BuildContext context) {
return GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 14 : 12,
fontWeight: FontWeight.w400,
color: const Color(0xFF777777),
);
}
TextStyle _registerClaimValueStyle(BuildContext context) {
return GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 16 : 14,
fontWeight: FontWeight.w600,
color: const Color(0xFF000000),
);
}
TextStyle _registerClaimInsurerValueStyle(BuildContext context) {
return GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 14 : 12,
fontWeight: FontWeight.w600,
color: const Color(0xFF000000),
);
}
TextStyle _registerClaimHeadingStyle(BuildContext context) {
return GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 18 : 16,
fontWeight: FontWeight.w600,
color: const Color(0xFF000000),
);
}
String _registerClaimFieldValue(dynamic value) {
if (value == null) return '-';
final text = value.toString().trim();
return text.isEmpty ? '-' : text;
}
String _formattedRegisterClaimSiValue(String raw) {
if (raw == '-') return raw;
return '$raw';
}
Color _policyStatusColor(String status) {
if (status.toLowerCase() == 'active') return const Color(0xFF2E7D32);
if (status.toLowerCase() == 'inactive') return const Color(0xFFC62828);
return const Color(0xFF000000);
}
Widget _buildRegisterClaimField(
BuildContext context,
String label,
String value, {
Color? valueColor,
bool alignEnd = false,
TextStyle? valueStyle,
}) {
final resolvedValueStyle =
(valueStyle ?? _registerClaimValueStyle(context))
.copyWith(color: valueColor);
return Column(
crossAxisAlignment:
alignEnd ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: [
Text(
label,
textAlign: alignEnd ? TextAlign.end : TextAlign.start,
style: _registerClaimLabelStyle(context),
),
const SizedBox(height: 4),
Text(
value,
textAlign: alignEnd ? TextAlign.end : TextAlign.start,
style: resolvedValueStyle,
),
],
);
}
Widget _buildRegisterClaimDivider() {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 12),
child: Divider(height: 1, thickness: 1, color: Color(0xFFD9D9D9)),
);
}
Widget _buildRegisterClaimCardHeader(
BuildContext context,
String heading,
) {
final isDesktop = Responsive.isDesktop(context);
return Container(
width: double.infinity,
padding: EdgeInsets.symmetric(
horizontal: isDesktop ? 20 : 16,
vertical: isDesktop ? 14 : 12,
),
decoration: const BoxDecoration(
color: Color(0xFFECF2FF),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(11),
topRight: Radius.circular(11),
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Text(
_registerClaimFieldValue(heading),
style: _registerClaimHeadingStyle(context),
),
),
const SizedBox(width: 8),
const Icon(
Icons.chevron_right,
color: Color(0xFFE26728),
size: 26,
),
],
),
);
}
Widget _buildRegisterClaimCard({
required BuildContext context,
required VoidCallback onTap,
required bool isRetail,
String? heading,
String? insurerName,
String? policyStatus,
String? siValue,
String? sumInsuredLabel,
String? insurerShortName,
String? policyType,
String? vehicleNo,
}) {
final isDesktop = Responsive.isDesktop(context);
final cardHeading = isRetail
? _registerClaimFieldValue(policyType)
: _registerClaimFieldValue(heading);
return Padding(
padding: const EdgeInsets.only(bottom: 12),
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Container(
width: double.infinity,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: const Color(0xFFD9D9D9)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildRegisterClaimCardHeader(context, cardHeading),
Padding(
padding: EdgeInsets.all(isDesktop ? 20 : 16),
child: isRetail
? _buildRetailRegisterClaimContent(
context,
insurerShortName: insurerShortName ?? '',
vehicleNo: vehicleNo ?? '',
)
: _buildNormalRegisterClaimContent(
context,
insurerName: insurerName ?? '',
policyStatus: policyStatus ?? '',
siValue: siValue ?? '',
sumInsuredLabel:
sumInsuredLabel ?? 'Sum Insured',
),
),
],
),
),
),
),
);
}
Widget _buildNormalRegisterClaimContent(
BuildContext context, {
required String insurerName,
required String policyStatus,
required String siValue,
required String sumInsuredLabel,
}) {
final isDesktop = Responsive.isDesktop(context);
final status = _registerClaimFieldValue(policyStatus);
final siLabel = _registerClaimFieldValue(sumInsuredLabel);
final formattedSi = _formattedRegisterClaimSiValue(
_registerClaimFieldValue(siValue),
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildRegisterClaimField(
context,
'Insurer',
_registerClaimFieldValue(insurerName),
valueStyle: _registerClaimInsurerValueStyle(context),
),
_buildRegisterClaimDivider(),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: _buildRegisterClaimField(
context,
'Status',
status,
valueColor: _policyStatusColor(status),
),
),
SizedBox(width: isDesktop ? 24 : 16),
Expanded(
child: _buildRegisterClaimField(
context,
siLabel,
formattedSi,
alignEnd: true,
),
),
],
),
],
);
}
Widget _buildRetailRegisterClaimContent(
BuildContext context, {
required String insurerShortName,
required String vehicleNo,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildRegisterClaimField(
context,
'Insurer',
_registerClaimFieldValue(insurerShortName),
valueStyle: _registerClaimInsurerValueStyle(context),
),
_buildRegisterClaimDivider(),
_buildRegisterClaimField(
context,
'Vehicle No',
_registerClaimFieldValue(vehicleNo),
),
],
);
}
List<Widget> generateYourPlanList(List<dynamic> data) {
return [
ListView.builder(
@ -976,140 +1237,42 @@ class _claimsState extends State<claims> {
itemBuilder: (BuildContext context, int index) {
var item = data[index];
// **CHECK IF THIS IS A RETAIL POLICY**
bool isRetail = item.containsKey('policy_transaction_id');
// ----------------------------
// NORMAL POLICY DATA (GMC/GPA)
// ----------------------------
String policyHeading = item['heading'] ?? '';
String policyName = item['policy_name'] ?? '';
String policyStatus = item['policy_status'] ?? '';
String siValue = item['si_value'] ?? '';
String sumInsuredLabel = item['sum_insured_label'] ?? '';
String sumInsuredLabel = item['sum_insured_label'] ?? 'Sum Insured';
String insurerName = item['insurer_name'] ?? '';
// ----------------------------
// RETAIL POLICY DATA
// ----------------------------
String insurerShortName = item['insurer_short_name'] ?? '';
String policyType = item['policy_type'] ?? '';
String vehicleNo = item['vehicle_no'] ?? '';
return GestureDetector(
onTap: () {
if (isRetail) {
// Retail policy click allow clicking
var details = {
"retailDetails": item,
};
context.push('/retailClaimForm', extra: details);
} else {
// Normal claim policy click
var details = {
"claimsDetails": item,
"fromClaimPage": 0,
};
context.push('/planclaimsform', extra: details);
}
},
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// LEFT SECTION
Expanded(
flex: 4,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
isRetail ? "Insurer" : "Insurer",
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 16 : 12,
color: const Color(0xFF979797)),
),
Text(
isRetail ? insurerShortName : policyName,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 18 : 11,
fontWeight: FontWeight.w600),
),
],
),
),
// CENTER (Status or Policy Type)
Expanded(
flex: 3,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
isRetail ? "Policy Type" : "Status",
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 16 : 12,
color: const Color(0xFF979797)),
),
Text(
isRetail ? policyType : policyStatus,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 18 : 11,
fontWeight: FontWeight.w600,
color: isRetail
? Colors.black
: (policyStatus == "Active"
? Colors.green
: Colors.red),
),
),
],
),
),
// RIGHT (Insured Name OR Sum Insured)
Expanded(
flex: 4,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
isRetail ? "Vehicle No" : sumInsuredLabel,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 16 : 12,
color: const Color(0xFF979797)),
),
Text(
isRetail ? vehicleNo : "$siValue",
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 18 : 11,
fontWeight: FontWeight.w600),
),
],
),
),
// ARROW
const Icon(Icons.chevron_right,
color: Color(0xFFE26728), size: 26),
],
),
),
),
),
);
return _buildRegisterClaimCard(
context: context,
isRetail: isRetail,
heading: policyHeading,
insurerName: insurerName,
policyStatus: policyStatus,
siValue: siValue,
sumInsuredLabel: sumInsuredLabel,
insurerShortName: insurerShortName,
policyType: policyType,
vehicleNo: vehicleNo,
onTap: () {
if (isRetail) {
context.push('/retailClaimForm', extra: {
'retailDetails': item,
});
} else {
context.push('/planclaimsform', extra: {
'claimsDetails': item,
'fromClaimPage': 0,
});
}
},
);
},
),
];

View File

@ -175,6 +175,186 @@ class _faqsState extends State<faqs> {
return root;
}
TextStyle _faqSectionTitleStyle(BuildContext context) {
return GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 16 : 15,
fontWeight: FontWeight.w600,
color: const Color(0xFF000000),
);
}
TextStyle _faqSubSectionTitleStyle(BuildContext context) {
return GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 15 : 14,
fontWeight: FontWeight.w500,
color: const Color(0xFF000000),
);
}
TextStyle _faqQuestionStyle(BuildContext context, {bool isOpen = false}) {
return GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 14 : 13,
fontWeight: isOpen ? FontWeight.w600 : FontWeight.w500,
color: const Color(0xFF000000),
);
}
Widget _buildFaqsHeader(BuildContext context) {
return InkWell(
onTap: () => context.pop(),
borderRadius: BorderRadius.circular(8),
child: Row(
children: [
const Icon(
Icons.chevron_left,
color: Color(0xFF000000),
size: 30,
),
const SizedBox(width: 5),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'FAQs',
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 20 : 16,
fontWeight: FontWeight.w600,
color: const Color(0xFF000000),
),
),
Text(
'Frequently Asked Questions',
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 13 : 12,
fontWeight: FontWeight.w400,
color: const Color(0xFF777777),
),
),
],
),
],
),
);
}
Widget _buildTabsContainer(BuildContext context) {
return Container(
width: double.infinity,
padding: EdgeInsets.all(Responsive.isDesktop(context) ? 12 : 10),
decoration: BoxDecoration(
color: const Color(0xFFECF2FF),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: const Color(0xFFD9D9D9)),
),
child: Responsive.isDesktop(context)
? buildTabs()
: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: buildTabs(),
),
);
}
Widget _buildFaqListCard(BuildContext context, Widget child) {
const radius = 12.0;
return Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(radius),
border: Border.all(color: const Color(0xFFD9D9D9)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.04),
blurRadius: 12,
offset: const Offset(0, 4),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(radius),
child: child,
),
);
}
BorderRadius? _faqItemBorderRadius({
required bool isFirst,
required bool isLast,
}) {
if (isFirst && isLast) {
return BorderRadius.circular(11);
}
if (isFirst) {
return const BorderRadius.vertical(top: Radius.circular(11));
}
if (isLast) {
return const BorderRadius.vertical(bottom: Radius.circular(11));
}
return null;
}
Widget _buildExpandableHeader({
required BuildContext context,
required String title,
required bool isOpen,
required VoidCallback onTap,
required TextStyle titleStyle,
double horizontalPadding = 16,
Color? backgroundColor,
bool isFirst = false,
bool isLast = false,
bool showBottomBorder = true,
}) {
final borderRadius = _faqItemBorderRadius(
isFirst: isFirst,
isLast: isLast && !isOpen,
);
return Material(
color: backgroundColor ?? Colors.white,
borderRadius: borderRadius,
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: onTap,
borderRadius: borderRadius,
child: Container(
padding: EdgeInsets.symmetric(
horizontal: horizontalPadding,
vertical: 14,
),
decoration: BoxDecoration(
color: backgroundColor,
border: showBottomBorder && !(isLast && !isOpen)
? const Border(
bottom: BorderSide(color: Color(0xFFE8E8E8)),
)
: null,
),
child: Row(
children: [
Expanded(
child: Text(
title,
style: titleStyle,
),
),
AnimatedRotation(
turns: isOpen ? 0.5 : 0,
duration: const Duration(milliseconds: 450),
curve: Curves.easeInOutCubic,
child: const Icon(
Icons.keyboard_arrow_down,
color: Color(0xFFE26728),
),
),
],
),
),
),
);
}
@override
Widget build(BuildContext context) {
return PopScope(
@ -198,107 +378,17 @@ class _faqsState extends State<faqs> {
)
: EdgeInsets.all(10),
color: Colors.white,
child: Column(children: [
Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.only(
top: 15, bottom: 15, left: 25, right: 25)
: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
flex: 12,
child: InkWell(
onTap: () {
context.pop();
},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(
Icons
.chevron_left, // Replace with your desired icon
color: Color(0xFF000000),
size: 30,
),
SizedBox(
width:
5), // Adjust space between icon and text
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'FAQs',
textAlign: TextAlign.start,
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFF000000),
),
),
Text(
'Frequently Asked Questions',
textAlign: TextAlign.start,
style: GoogleFonts.poppins(
fontSize:
12, // Adjust the font size as needed
fontWeight: FontWeight.w400,
color: Color(0xFF000000),
),
),
],
),
],
),
),
),
],
),
Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Color(0xFFEEF5FF),
// Set background color for the container
borderRadius: BorderRadius.circular(
5), // Set border radius for the container
),
padding: Responsive.isDesktop(context)
? EdgeInsets.only(
top: 10, bottom: 10, left: 25, right: 25)
: EdgeInsets.only(
top: 10, bottom: 10, left: 10, right: 10),
child: Align(
alignment: Alignment.centerLeft, // LEFT ALIGN TABS
child: Responsive.isDesktop(context)
? buildTabs() // no scroll on web
: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: buildTabs(),
),
),
),
const SizedBox(height: 20),
buildContent(),
],
),
),
// NhanceVideoWrapper(context)
],
),
),
]),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildFaqsHeader(context),
const SizedBox(height: 16),
_buildTabsContainer(context),
const SizedBox(height: 16),
_buildFaqListCard(context, buildContent()),
SizedBox(height: Responsive.isDesktop(context) ? 40 : 80),
],
),
)),
if (isLoading)
Container(
@ -381,7 +471,7 @@ class _faqsState extends State<faqs> {
children: faqTree.keys.map((tab) {
final active = selectedTab == tab;
final tabWidget = InkWell(
final tabWidget = GestureDetector(
onTap: () {
setState(() {
selectedTab = tab;
@ -390,42 +480,59 @@ class _faqsState extends State<faqs> {
openQuestionId = null;
});
},
child: Container(
alignment: Alignment.center,
padding: const EdgeInsets.symmetric(vertical: 12),
decoration: BoxDecoration(
color: active ? Colors.deepOrange : Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: active ? Colors.deepOrange : const Color(0xFFE0E0E0),
),
),
child: Text(
tab,
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
color: active ? Colors.white : Colors.deepOrange,
fontWeight: FontWeight.w600,
),
),
),
child: active
? Material(
elevation: 4,
borderRadius: BorderRadius.circular(10),
color: Colors.white,
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(
horizontal: isDesktop ? 24 : 16,
vertical: isDesktop ? 12 : 10,
),
child: Text(
tab,
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize: isDesktop ? 15 : 13,
color: const Color(0xFF000000),
fontWeight: FontWeight.w600,
),
),
),
)
: Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(
horizontal: isDesktop ? 24 : 16,
vertical: isDesktop ? 12 : 10,
),
child: Text(
tab,
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize: isDesktop ? 15 : 13,
color: const Color(0xFF636363),
fontWeight: FontWeight.w500,
),
),
),
);
/// 🔥 DESKTOP FULL WIDTH TAB
if (isDesktop) {
return Expanded(
child: Padding(
padding: const EdgeInsets.only(right: 10),
padding: const EdgeInsets.only(right: 8),
child: tabWidget,
),
);
}
/// 📱 MOBILE CONTENT WIDTH TAB
return Padding(
padding: const EdgeInsets.only(right: 8),
child: SizedBox(
width: 110,
width: 100,
child: tabWidget,
),
);
@ -443,26 +550,49 @@ class _faqsState extends State<faqs> {
// Health / Travel without hierarchy
if (node.children.isEmpty) {
final faqs = node.faqs;
return Column(
children: node.faqs.map(buildQuestion).toList(),
children: [
for (int i = 0; i < faqs.length; i++)
buildQuestion(
faqs[i],
isFirst: i == 0,
isLast: i == faqs.length - 1,
),
],
);
}
// Others Fire Insurance General
final sections = node.children;
return Column(
children: node.children.map(buildSection).toList(),
children: [
for (int i = 0; i < sections.length; i++)
buildSection(
sections[i],
isFirst: i == 0,
isLast: i == sections.length - 1,
),
],
);
}
/// ---------------- SECTION ----------------
Widget buildSection(FaqNode node) {
Widget buildSection(
FaqNode node, {
bool isFirst = false,
bool isLast = false,
}) {
final bool isOpen = openSection == node.title;
const Duration kExpandDuration = Duration(milliseconds: 450);
const Curve kExpandCurve = Curves.easeInOutCubic;
return Column(
children: [
InkWell(
_buildExpandableHeader(
context: context,
title: node.title,
isOpen: isOpen,
onTap: () {
setState(() {
openSection = isOpen ? null : node.title;
@ -470,39 +600,11 @@ class _faqsState extends State<faqs> {
openQuestionId = null;
});
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(color: Color(0xFFE0E0E0)),
),
),
child: Row(
children: [
Expanded(
child: Text(
node.title,
style: GoogleFonts.poppins(
fontSize: 15,
fontWeight: FontWeight.w600,
),
),
),
AnimatedRotation(
turns: isOpen ? 0.5 : 0,
duration: kExpandDuration,
curve: kExpandCurve,
child: const Icon(
Icons.keyboard_arrow_down,
color: Colors.deepOrange,
),
),
],
),
),
titleStyle: _faqSectionTitleStyle(context),
backgroundColor: isOpen ? const Color(0xFFECF2FF) : Colors.white,
isFirst: isFirst,
isLast: isLast,
),
/// SECTION CONTENT
AnimatedSize(
duration: kExpandDuration,
curve: kExpandCurve,
@ -510,8 +612,23 @@ class _faqsState extends State<faqs> {
? Column(
children: [
if (node.children.isNotEmpty)
...node.children.map(buildSubSection),
if (node.children.isEmpty) ...node.faqs.map(buildQuestion),
...node.children.asMap().entries.map((entry) {
final index = entry.key;
final child = entry.value;
return buildSubSection(
child,
isLast: isLast && index == node.children.length - 1,
);
}),
if (node.children.isEmpty)
...node.faqs.asMap().entries.map((entry) {
final index = entry.key;
final faq = entry.value;
return buildQuestion(
faq,
isLast: isLast && index == node.faqs.length - 1,
);
}),
],
)
: const SizedBox.shrink(),
@ -521,58 +638,43 @@ class _faqsState extends State<faqs> {
}
/// ---------------- SUB SECTION ----------------
Widget buildSubSection(FaqNode node) {
Widget buildSubSection(
FaqNode node, {
bool isLast = false,
}) {
final bool isOpen = openSubSection == node.title;
const Duration kExpandDuration = Duration(milliseconds: 450);
const Curve kExpandCurve = Curves.easeInOutCubic;
return Column(
children: [
InkWell(
_buildExpandableHeader(
context: context,
title: node.title,
isOpen: isOpen,
onTap: () {
setState(() {
openSubSection = isOpen ? null : node.title;
openQuestionId = null;
});
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(color: Color(0xFFEDEDED)),
),
),
child: Row(
children: [
Expanded(
child: Text(
node.title,
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
),
AnimatedRotation(
turns: isOpen ? 0.5 : 0,
duration: kExpandDuration,
curve: kExpandCurve,
child: const Icon(
Icons.keyboard_arrow_down,
size: 20,
color: Colors.deepOrange,
),
),
],
),
),
titleStyle: _faqSubSectionTitleStyle(context),
horizontalPadding: 20,
backgroundColor: isOpen ? const Color(0xFFF6FAFF) : Colors.white,
isLast: isLast,
),
AnimatedSize(
duration: kExpandDuration,
curve: kExpandCurve,
child: isOpen
? Column(
children: node.faqs.map(buildQuestion).toList(),
children: [
for (int i = 0; i < node.faqs.length; i++)
buildQuestion(
node.faqs[i],
isLast: isLast && i == node.faqs.length - 1,
),
],
)
: const SizedBox.shrink(),
),
@ -581,48 +683,73 @@ class _faqsState extends State<faqs> {
}
/// ---------------- QUESTION ----------------
Widget buildQuestion(FaqItem faq) {
Widget buildQuestion(
FaqItem faq, {
bool isFirst = false,
bool isLast = false,
}) {
final bool isOpen = openQuestionId == faq.id;
const Duration kExpandDuration = Duration(milliseconds: 450);
const Curve kExpandCurve = Curves.easeInOutCubic;
final borderRadius = _faqItemBorderRadius(
isFirst: isFirst,
isLast: isLast && !isOpen,
);
return Column(
children: [
InkWell(
onTap: () {
setState(() {
openQuestionId = isOpen ? null : faq.id;
});
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(color: Color(0xFFF0F0F0)),
Material(
color: Colors.white,
borderRadius: borderRadius,
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: () {
setState(() {
openQuestionId = isOpen ? null : faq.id;
});
},
borderRadius: borderRadius,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
decoration: BoxDecoration(
border: isLast && !isOpen
? null
: const Border(
bottom: BorderSide(color: Color(0xFFE8E8E8)),
),
),
),
child: Row(
children: [
Expanded(
child: Text(
faq.question,
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w400,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(top: 2),
child: Icon(
Icons.help_outline,
size: 18,
color: isOpen
? const Color(0xFFE26728)
: const Color(0xFF999999),
),
),
),
AnimatedRotation(
turns: isOpen ? 0.5 : 0,
duration: kExpandDuration,
curve: kExpandCurve,
child: const Icon(
Icons.keyboard_arrow_down,
size: 18,
color: Colors.deepOrange,
const SizedBox(width: 10),
Expanded(
child: Text(
faq.question,
style: _faqQuestionStyle(context, isOpen: isOpen),
),
),
),
],
AnimatedRotation(
turns: isOpen ? 0.5 : 0,
duration: kExpandDuration,
curve: kExpandCurve,
child: const Icon(
Icons.keyboard_arrow_down,
size: 20,
color: Color(0xFFE26728),
),
),
],
),
),
),
),
@ -633,15 +760,26 @@ class _faqsState extends State<faqs> {
? Container(
width: double.infinity,
padding: const EdgeInsets.fromLTRB(16, 12, 16, 16),
color: const Color(0xFFFAFAFA),
decoration: BoxDecoration(
color: const Color(0xFFFAFAFA),
borderRadius: isLast
? const BorderRadius.vertical(
bottom: Radius.circular(11),
)
: null,
),
child: Html(
data: faq.answer ?? '',
style: {
"body": Style(
margin: Margins.zero,
padding: HtmlPaddings.zero,
fontSize: FontSize(13),
color: Colors.black87,
fontSize: FontSize(
Responsive.isDesktop(context) ? 14 : 13,
),
fontFamily: GoogleFonts.poppins().fontFamily,
color: const Color(0xFF444444),
lineHeight: LineHeight(1.5),
),
"table": Style(
border: Border.all(color: Colors.grey.shade300),

View File

@ -162,6 +162,32 @@ class _generalExclusionsDeductiblesState
}
ThemeData _buildPageTheme(BuildContext context) {
final isDesktop = Responsive.isDesktop(context);
final baseTheme = Theme.of(context);
return baseTheme.copyWith(
textTheme: GoogleFonts.poppinsTextTheme(baseTheme.textTheme).copyWith(
titleLarge: GoogleFonts.poppins(
fontSize: isDesktop ? 18 : 16,
fontWeight: FontWeight.w600,
color: const Color(0xFF000000),
),
titleMedium: GoogleFonts.poppins(
fontSize: isDesktop ? 18 : 16,
fontWeight: FontWeight.w500,
color: const Color(0xFF000000),
),
bodyLarge: GoogleFonts.poppins(
fontSize: isDesktop ? 16 : 14,
fontWeight: FontWeight.w400,
color: const Color(0xFF000000),
height: 1.5,
),
),
);
}
@override
Widget build(BuildContext context) {
return PopScope(
@ -173,7 +199,9 @@ class _generalExclusionsDeductiblesState
child: Scaffold(
appBar: CustomAppBar(),
backgroundColor: Colors.white,
body: isLoading
body: Theme(
data: _buildPageTheme(context),
child: isLoading
? Container(
color: Color(0x98FFFCE5), // Semi-transparent background
child: Center(
@ -224,11 +252,9 @@ class _generalExclusionsDeductiblesState
Text(
'General Exclusions & Deductibles',
textAlign: TextAlign.start,
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFF000000),
),
style: Theme.of(context)
.textTheme
.titleLarge,
),
],
),
@ -238,50 +264,51 @@ class _generalExclusionsDeductiblesState
),
],
),
// Text(
// 'General Exclusions & Deductibles',
// style: GoogleFonts.poppins(
// fontSize: 18, fontWeight: FontWeight.w600),
// ),
const SizedBox(height: 20),
if (type3Content.isNotEmpty) ...[
Text(type3SectionName ?? '',
style: GoogleFonts.poppins(
fontSize: 18, fontWeight: FontWeight.w500)),
Text(
type3SectionName ?? '',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 10),
buildBulletList(type3Content),
buildBulletList(context, type3Content),
],
if (type4Content.isNotEmpty) ...[
const SizedBox(height: 20),
Text(type4Heading ?? '',
style: GoogleFonts.poppins(
fontSize: 18, fontWeight: FontWeight.w500)),
buildBulletList(type4Content),
Text(
type4Heading ?? '',
style: Theme.of(context).textTheme.titleMedium,
),
buildBulletList(context, type4Content),
],
if (type5Content.isNotEmpty) ...[
const SizedBox(height: 20),
Text(type5Heading ?? '',
style: GoogleFonts.poppins(
fontSize: 18, fontWeight: FontWeight.w500)),
buildBulletList(type5Content),
Text(
type5Heading ?? '',
style: Theme.of(context).textTheme.titleMedium,
),
buildBulletList(context, type5Content),
],
if (type6Content.isNotEmpty) ...[
const SizedBox(height: 20),
Text(type6Heading ?? '',
style: GoogleFonts.poppins(
fontSize: 18, fontWeight: FontWeight.w500)),
buildBulletList(type6Content),
Text(
type6Heading ?? '',
style: Theme.of(context).textTheme.titleMedium,
),
buildBulletList(context, type6Content),
],
if (type7Content.isNotEmpty) ...[
const SizedBox(height: 20),
Text(type7Heading ?? '',
style: GoogleFonts.poppins(
fontSize: 18, fontWeight: FontWeight.w500)),
buildBulletList(type7Content),
Text(
type7Heading ?? '',
style: Theme.of(context).textTheme.titleMedium,
),
buildBulletList(context, type7Content),
],
],
),
),
),
bottomNavigationBar: Responsive.isDesktop(context)
? SizedBox(
@ -310,9 +337,12 @@ class _generalExclusionsDeductiblesState
));
}
Widget buildBulletList(List<String> items) {
Widget buildBulletList(BuildContext context, List<String> items) {
if (items.isEmpty) return const SizedBox.shrink();
final bodyStyle = Theme.of(context).textTheme.bodyLarge;
final bulletSize = bodyStyle?.fontSize ?? 14;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: items.map((text) {
@ -321,14 +351,14 @@ class _generalExclusionsDeductiblesState
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.only(top: 2),
Padding(
padding: const EdgeInsets.only(top: 2),
child: Text(
"",
style: TextStyle(
fontSize: 18,
'',
style: bodyStyle?.copyWith(
fontSize: bulletSize + 2,
fontWeight: FontWeight.w600,
color: Color(0xFFE26728),
color: const Color(0xFFE26728),
),
),
),
@ -336,11 +366,7 @@ class _generalExclusionsDeductiblesState
Expanded(
child: Text(
text,
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Color(0xFF000000),
),
style: bodyStyle,
),
),
],

File diff suppressed because it is too large Load Diff

View File

@ -407,7 +407,7 @@ class _planclaimsformState extends State<planclaimsform> {
void loadClaimTypes(int? serviceId) {
if (serviceId == null) return;
String key = serviceId.toString();
String key = serviceId == 72 ? '1' : serviceId.toString();
if (claimTypeMap.containsKey(key)) {
Map<String, dynamic> types =

View File

@ -407,7 +407,7 @@ class _policiesState extends State<policies> {
? 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,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
@ -450,154 +450,11 @@ class _policiesState extends State<policies> {
],
),
SizedBox(
height: Responsive.isDesktop(context)
? 20
: 20), // Space between rows
Column(
children: [
Responsive.isDesktop(context)
? buildDesktopLayout(context)
: buildMobileLayout(context)
],
),
height: Responsive.isDesktop(context) ? 20 : 16),
_buildPolicyDetailsSection(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),
),
),
],
),
),
))),
)),
],
),
height: Responsive.isDesktop(context) ? 32 : 24),
_buildPolicyActionButtons(context),
SizedBox(height: Responsive.isDesktop(context) ? 30 : 20),
// Add more rows as needed
],
@ -1385,75 +1242,279 @@ class _policiesState extends State<policies> {
);
}
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'])),
],
TextStyle _policyLabelStyle(BuildContext context) {
return GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 14 : 13,
fontWeight: FontWeight.w400,
color: const Color(0xFF777777),
);
}
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'])),
],
),
],
TextStyle _policyValueStyle(BuildContext context) {
return GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 18 : 15,
fontWeight: FontWeight.w600,
color: const Color(0xFF000000),
);
}
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),
),
),
],
),
String _policyFieldValue(dynamic value) {
final text = value?.toString().trim() ?? '';
return text.isEmpty ? '-' : text;
}
String _formattedPolicyExpiry() {
final raw = argumentsData['policy_end_date']?.toString() ?? '';
if (raw.isEmpty) return '-';
try {
return convertDateFormat(raw);
} catch (_) {
return raw;
}
}
String _formattedSiValue() {
final raw = _policyFieldValue(argumentsData['si_value']);
if (raw == '-') return raw;
return '$raw';
}
Widget _buildPolicyDetailField(
BuildContext context,
String label,
String value,
) {
return SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
textAlign: TextAlign.start,
style: _policyLabelStyle(context),
),
SizedBox(height: Responsive.isDesktop(context) ? 8 : 6),
Text(
value,
textAlign: TextAlign.start,
softWrap: true,
style: _policyValueStyle(context),
),
],
),
);
}
Widget _buildPolicyDetailDivider() {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 14),
child: Divider(
height: 1,
thickness: 1,
color: Color(0xFFD9D9D9),
),
);
}
Widget _buildPolicyDetailsCard(BuildContext context, Widget child) {
return Container(
width: double.infinity,
padding: EdgeInsets.all(Responsive.isDesktop(context) ? 24 : 16),
decoration: BoxDecoration(
color: const Color(0xFFFFFCE5),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: const Color(0xFFD9D9D9)),
),
child: child,
);
}
Widget _buildPolicyDetailsSection(BuildContext context) {
final isDesktop = Responsive.isDesktop(context);
final siLabel =
_policyFieldValue(argumentsData['sum_insured_label'] ?? 'Sum Insured');
if (isDesktop) {
return _buildPolicyDetailsCard(
context,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: _buildPolicyDetailField(
context,
'Policy No',
_policyFieldValue(argumentsData['policy_no']),
),
),
const SizedBox(width: 24),
Expanded(
child: _buildPolicyDetailField(
context,
siLabel,
_formattedSiValue(),
),
),
const SizedBox(width: 24),
Expanded(
child: _buildPolicyDetailField(
context,
'Policy Expiry',
_formattedPolicyExpiry(),
),
),
],
),
),
_buildPolicyDetailDivider(),
_buildPolicyDetailField(
context,
'Insurer',
_policyFieldValue(argumentsData['insurer_name']),
),
],
),
);
}
return _buildPolicyDetailsCard(
context,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildPolicyDetailField(
context,
'Policy No',
_policyFieldValue(argumentsData['policy_no']),
),
_buildPolicyDetailDivider(),
_buildPolicyDetailField(
context,
siLabel,
_formattedSiValue(),
),
_buildPolicyDetailDivider(),
_buildPolicyDetailField(
context,
'Policy Expiry',
_formattedPolicyExpiry(),
),
_buildPolicyDetailDivider(),
_buildPolicyDetailField(
context,
'Insurer',
_policyFieldValue(argumentsData['insurer_name']),
),
],
),
);
}
Widget _buildPolicyActionButton({
required BuildContext context,
required String label,
required String svgKey,
required VoidCallback? onPressed,
bool expanded = false,
}) {
final button = Material(
elevation: 0,
borderRadius: BorderRadius.circular(8),
color: const Color(0xFFFFF8BF),
child: SizedBox(
height: 48,
width: Responsive.isDesktop(context) ? 220 : double.infinity,
child: TextButton(
onPressed: onPressed,
style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 16),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
SvgPicture.string(
SvgService.getSvg(svgKey),
width: 24,
height: 24,
),
const SizedBox(width: 8),
Flexible(
child: Text(
label,
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 16 : 14,
fontWeight: FontWeight.w600,
color: const Color(0xFF000000),
),
),
),
],
),
),
),
);
if (expanded) {
return Expanded(child: button);
}
return button;
}
Widget _buildPolicyActionButtons(BuildContext context) {
final isDesktop = Responsive.isDesktop(context);
if (isDesktop) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (ECardHide) ...[
_buildPolicyActionButton(
context: context,
label: 'E-Card',
svgKey: 'ECard',
onPressed: _isDownloadingEcard
? null
: () => getEcardDownload(empPrimaryId),
),
const SizedBox(width: 16),
],
_buildPolicyActionButton(
context: context,
label: 'Initiate a Claim',
svgKey: 'fileaclaims',
onPressed: () => context.push('/claims'),
),
],
);
}
return Column(
children: [
_buildPolicyActionButton(
context: context,
label: 'Initiate a Claim',
svgKey: 'fileaclaims',
onPressed: () => context.push('/claims'),
),
if (ECardHide) ...[
const SizedBox(height: 12),
_buildPolicyActionButton(
context: context,
label: 'E-Card',
svgKey: 'ECard',
onPressed: _isDownloadingEcard
? null
: () => getEcardDownload(empPrimaryId),
),
],
],
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -214,7 +214,13 @@ class _changePinState extends State<changePin> {
),
);
return Scaffold(
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) {
if (didPop) return;
context.go('/profile');
},
child: Scaffold(
resizeToAvoidBottomInset: true, // IMPORTANT
bottomNavigationBar: SafeArea(
child: Container(
@ -265,22 +271,25 @@ class _changePinState extends State<changePin> {
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 12,
child: Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(
left: 16.0), // Add left margin
child: Image.asset(
'assets/nhance_app_logo.png',
width: 150,
height: 100,
),
InkWell(
onTap: () => context.go('/profile'),
borderRadius: BorderRadius.circular(8),
child: const Padding(
padding: EdgeInsets.only(left: 8, right: 4),
child: Icon(
Icons.chevron_left,
color: Color(0xFF000000),
size: 30,
),
),
),
Image.asset(
'assets/nhance_app_logo.png',
width: 150,
height: 100,
),
],
),
SizedBox(height: 10),
@ -614,6 +623,6 @@ class _changePinState extends State<changePin> {
]),
)),
]),
)));
))));
}
}

View File

@ -16,9 +16,9 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
#version: 1.2.41+98
version: 1.0.39+45
#version: 2.0.28+67
#version: 1.2.42+99
version: 1.0.41+47
#version: 2.0.29+68
environment:
sdk: '>=3.3.3 <4.0.0'
@ -74,6 +74,7 @@ dependencies:
dropdown_search: ^6.0.2
ribbon_widget: ^1.0.5
flutter_html: ^3.0.0
html: ^0.15.5
video_player: ^2.10.1
path_provider: ^2.1.5
open_filex: ^4.7.0