post_enrollment_app/lib/pages/postEnrollment/wellness.dart
2026-04-08 09:11:24 +05:30

560 lines
21 KiB
Dart
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.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 '../../customAppBar/responsive.dart';
import '../../customAppBar/tabs.dart';
import '../../customAppBar/toastHelper.dart';
import '../service/SessionManager.dart';
import '../service/TokenService.dart';
import 'package:nhance_app_pwa/logger.dart';
class wellness extends StatefulWidget {
const wellness({Key? key}) : super(key: key);
@override
State<wellness> createState() => _wellnessState();
}
class _wellnessState extends State<wellness> {
late ApiService apiService;
bool isLoadingGif = false;
dynamic wellnessURL;
dynamic wellnessMessage;
dynamic empCodeString;
dynamic empName;
dynamic empPrimaryId;
dynamic client_id;
dynamic client_branch_id;
dynamic mobileNo;
dynamic policyList;
dynamic employeeDetailsList;
dynamic emailId;
final session = SessionManager();
@override
void initState() {
super.initState();
apiService = ApiService(context);
// getWellnessLink();
_loadToken();
}
@override
void dispose() {
super.dispose();
}
Future<void> _loadToken() async {
logDebug('_loadToken');
final String? token = await TokenService.getPostToken();
if (token != null && token.isNotEmpty) {
// Decode the JWT token received from the API response
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
logDebug(decodedToken);
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;
emailId = session.empEmailCorporate;
logDebug(client_id);
// getAdvertisementSliderImage();
getActiveAndInactivePolicyDetails('Active');
}
}
Future<void> getActiveAndInactivePolicyDetails(String status) async {
logDebug(getActiveAndInactivePolicyDetails);
if (client_id == null || empCodeString == null) {
return;
}
setState(() {
isLoadingGif = true;
});
logDebug('check 1');
final response = await apiService.getActiveAndInactivePolicyDetails(
client_id!, empCodeString!, status, client_branch_id, mobileNo,emailId);
logDebug('check 1');
if (response['status'] == 'success') {
policyList = response['data'];
logDebug('policyList $policyList');
// -------------------------------------------
// 1⃣ CHECK FOR GMC OR GMC-PARENT
// -------------------------------------------
final gmcPolicies = policyList.where((item) {
final type = (item['policy_type'] ?? '').toString();
return type == 'GMC' || type == 'GMC - Parents';
}).toList();
logDebug('gmcPolicies $gmcPolicies');
if (gmcPolicies.isNotEmpty) {
final mergedEmployeeDetails = getMergedEmployeeDetails(gmcPolicies);
logDebug("🟢 Merged Employee Details: $mergedEmployeeDetails");
setState(() {
employeeDetailsList = mergedEmployeeDetails;
});
logDebug('mergedEmployeeDetails $employeeDetailsList');
setState(() => isLoadingGif = false);
// continue your logic here…
return;
}
// -------------------------------------------
// 2⃣ IF NO GMC, CHECK FOR GPA
// -------------------------------------------
final gpaPolicies = policyList.where((item) {
final type = (item['policy_type'] ?? '').toString();
return type == 'GPA';
}).toList();
if (gpaPolicies.isNotEmpty) {
logDebug("🟠 GPA FOUND — calling Wellness API directly");
final firstPolicy = gpaPolicies[0];
final empID = firstPolicy['EmployeePolicy'][0]['employee_id'];
final clientPolicyId = firstPolicy['client_policy_id'];
logDebug("EMPLOYEE ID: $empID");
logDebug("CLIENT POLICY ID: $clientPolicyId");
setState(() => isLoadingGif = false);
await getWellnessLink(empID, clientPolicyId);
return;
}
// -------------------------------------------
// 3⃣ NO GMC, NO GPA
// -------------------------------------------
logDebug("❌ No valid policy found");
ToastHelper.showErrorToast(context, "No valid policies found.");
setState(() => isLoadingGif = false);
} else {
setState(() {
isLoadingGif = false;
});
logDebug('API request failed with status: ${response['status']}');
}
}
List<dynamic> getMergedEmployeeDetails(List<dynamic>? gmcPolicies) {
logDebug('123');
if (gmcPolicies == null || gmcPolicies.isEmpty) return [];
logDebug('getMergedEmployeeDetails $gmcPolicies');
List<dynamic> finalList = [];
for (var policy in gmcPolicies) {
final details = policy['EmployeePolicy'];
final clientPolicyId = policy['client_policy_id'];
if (details != null) {
if (details is List) {
// Add client_policy_id to each employee
for (var emp in details) {
finalList.add({
...emp, // existing employee fields
"client_policy_id": clientPolicyId
});
}
} else if (details is Map) {
// Single employee object
finalList.add({
...details,
"client_policy_id": clientPolicyId
});
}
}
}
return finalList;
}
Future<void> getWellnessLink(employee_id,client_policy_id) async {
final response = await apiService.getWellnessLink(employee_id,client_policy_id);
logDebug('check 1');
if (response['status'] == 'success') {
wellnessURL = response['data'];
logDebug('✅ Link: $wellnessURL');
openInWebView(context,wellnessURL);
// await _launchURL(wellnessURL); // Only launch if status is success
} else if (response['status'] == 'failed') {
wellnessMessage = response['message'];
logDebug('❌ Error: $wellnessMessage');
ToastHelper.showErrorToast(context, wellnessMessage);
} else {
ToastHelper.showErrorToast(context, '⚠️ Unknown response format');
logDebug('⚠️ Unknown response format');
}
}
Future<void> _launchURL(String url, BuildContext context) async {
logDebug('url $url');
try {
final Uri uri = Uri.parse(url);
await launchUrl(uri, mode: LaunchMode.externalApplication);
} catch (e) {
logDebug('Could not launch URL: $e');
}
}
void openInWebView(BuildContext context, String url) {
if (kIsWeb) {
// 🌐 Open in new browser tab (web)
_launchURL(url,context);
} else {
// 📱 Open in platform WebView
context.push('/wellnessWebView', extra: wellnessURL);
}
}
@override
Widget build(BuildContext context) {
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) {
if (didPop) return;
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(10),
color: Colors.white,
child: Column(children: [
Container(
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(
'Wellness',
textAlign: TextAlign.start,
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFF000000),
),
),
Text(
'Select your family member to avail the wellness benefits.',
textAlign: TextAlign.start,
style: GoogleFonts.poppins(
fontSize:
11, // Adjust the font size as needed
fontWeight: FontWeight.w400,
color: Color(0xFF000000),
),
),
],
),
],
),
),
),
],
),
// Add more rows as needed
],
),
),
SizedBox(height: 15),
if (employeeDetailsList != null && employeeDetailsList.length > 0)
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: generateFamilyMembers(employeeDetailsList),
),
),
SizedBox(height: Responsive.isDesktop(context) ? 40 : 70),
]),
)),
if (isLoadingGif)
Container(
color: Color(0x98FFFCE5), // Semi-transparent background
child: Center(
child: // Your GIF loader widget
Image.asset(
height: 60,
width: 60,
'assets/nhance-loader.gif'), // Adjust path to your GIF loader
),
),
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
),
)
);
}
List<Widget> generateFamilyMembers(List<dynamic> data) {
return [
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
var item = data[index];
// String claimsName = item['user_name'];
String gender = item['gender'] ?? '';
String dob = item['dob'] ?? '';
String name = item['name'] ?? '';
String relationship = item['relationship'] ?? '';
String employee_id = item['employee_id'] ?? '';
String client_policy_id = item['client_policy_id'] ?? '';
logDebug('${name} - ${employee_id}--${client_policy_id}');
return GestureDetector(
onTap: () {
getWellnessLink(employee_id,client_policy_id);
},
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
),
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 5),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 8,
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 (gender == 'M')
SvgPicture.string(
SvgService.getSvg('personMale'),
width: 25,
height: 25,
)
else if (gender == 'F')
SvgPicture.string(
SvgService.getSvg('personFemale'),
width: 25,
height: 25,
),
const SizedBox(width: 6),
// Name text
Text(
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(dob!) ?? '-'}",
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 14 : 12,
color: const Color(0xFF606060),
fontWeight: FontWeight.w300,
),
),
],
)
),
),
Expanded(
flex: 4,
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: Text(
relationship!,
textAlign: TextAlign.end,
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context)
? 16
: 14,
color: Color(0xFF404040),
fontWeight: FontWeight.w400,
),
),
),
),
],
),
),
),
),
);
},
),
];
}
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
}
}
}