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 createState() => _wellnessState(); } class _wellnessState extends State { 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 _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? 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 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 getMergedEmployeeDetails(List? gmcPolicies) { logDebug('123'); if (gmcPolicies == null || gmcPolicies.isEmpty) return []; logDebug('getMergedEmployeeDetails $gmcPolicies'); List 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 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 _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 generateFamilyMembers(List 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 } } }