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/pages/postEnrollment/service/api_service.dart'; import '../../customAppBar/customAppBar.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 AddPolicyScreen extends StatefulWidget { const AddPolicyScreen({super.key}); @override State createState() => _AddPolicyScreenState(); } class _AddPolicyScreenState extends State { final _formKey = GlobalKey(); bool isLoading = false; dynamic _token; final session = SessionManager(); late ApiService apiService; dynamic empCodeString; dynamic empPrimaryId; dynamic client_id; dynamic mobileNo; dynamic client_branch_id; dynamic decodedToken; // Form controllers final TextEditingController policyNoController = TextEditingController(); final TextEditingController expDateController = TextEditingController(); String? selectedPolicyType; String? selectedInsurer; List> policyTypeData = []; List> insurerData = []; @override void initState() { super.initState(); apiService = ApiService(context); _loadToken(); } Future _loadToken() async { final String? token = await TokenService.getPostToken(); if (token != null && token.isNotEmpty) { setState(() => _token = token); decodedToken = Jwt.parseJwt(token); mobileNo = session.mobileNo; client_branch_id = session.empClientBranchId; empCodeString = session.empCodeString; empPrimaryId = session.empPrimaryId; client_id = session.client_id; getPolicyTypeAndInsurerMaster(); } } Future pickExpiryDate() async { DateTime today = DateTime.now(); DateTime? picked = await showDatePicker( context: context, initialDate: today.add(const Duration(days: 1)), // default tomorrow firstDate: DateTime(today.year, today.month, today.day), // no past lastDate: DateTime(2100), ); if (picked != null) { expDateController.text = DateFormat("dd MMM yyyy").format(picked); setState(() {}); } } Future getPolicyTypeAndInsurerMaster() async { setState(() => isLoading = true); try { final response = await apiService.fetchPolicyTypeAndInsurer(); if (response['status'] == 'success') { policyTypeData = List>.from(response['data']['policy_type']); insurerData = List>.from(response['data']['insurer']); setState(() => isLoading = false); } else { throw Exception('Failed to fetch master data'); } } catch (error) { logDebug('Error fetching list: $error'); } } Future submitForm() async { try { if (_formKey.currentState!.validate()) { setState(() => isLoading = true); Map formData = { 'emp_id': empPrimaryId, 'policy_type_id': selectedPolicyType, 'insurer_id': selectedInsurer, 'policy_no': policyNoController.text, 'policy_end_date': expDateController.text, 'policy_start_date': '', }; final response = await apiService.sendRetailPolicyDetails(formData); if (response['status'] == 'success') { ToastHelper.showSuccessToast(context, response['message']); selectedPolicyType = null; selectedInsurer = null; policyNoController.clear(); expDateController.clear(); context.go('/home'); } } } catch (e) { logDebug('Submit error: $e'); } finally { if (mounted) { setState(() => isLoading = false); } } } // ------------------------------------------------------ // WIDGETS // ------------------------------------------------------ Widget dropdownFieldMap({ required String? value, required String hint, required List> items, required String validatorMsg, bool isMandatory = true, required Function(String?) onChanged, required String labelKey, required String valueKey, }) { return DropdownButtonFormField( value: value, decoration: inputDecoration(hint), items: items.map((item) { return DropdownMenuItem( value: item[valueKey].toString(), // send ID child: Text(item[labelKey].toString()), // show name ); }).toList(), validator: (value) { if (!isMandatory) return null; return value == null ? validatorMsg : null; }, onChanged: onChanged, ); } TextStyle labelStyle() => GoogleFonts.poppins( fontSize: 13, fontWeight: FontWeight.w500, color: Colors.black87, ); InputDecoration inputDecoration(String hint, {Widget? suffix}) { return InputDecoration( suffixIcon: suffix, hintText: hint, contentPadding: const EdgeInsets.all(14), border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), ), ); } @override Widget build(BuildContext context) { return PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) { if (didPop) return; context.go('/home'); }, 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, vertical: MediaQuery.of(context).size.height * 0.05, ) : const EdgeInsets.all(10), color: Colors.white, child: Column(children: [ Card( elevation: 5, color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15)), child: Padding( padding: const EdgeInsets.all(15), child: Column( children: [ Row( children: [ InkWell( onTap: () => context.go('/home'), child: const Icon(Icons.chevron_left, size: 30), ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Add Your Insurance Policy", style: GoogleFonts.poppins( fontSize: 16, fontWeight: FontWeight.w600, )), const SizedBox(height: 2), Text( 'Add and manage all your insurance policies taken anywhere for value added services and renewal reminders', maxLines: 3, overflow: TextOverflow.ellipsis, style: GoogleFonts.poppins(fontSize: 12), ), ], ), ) ], ), const SizedBox(height: 20), /// FORM Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Type of Policy", style: labelStyle()), const SizedBox(height: 5), dropdownFieldMap( value: selectedPolicyType, hint: "Select policy type", items: policyTypeData, validatorMsg: "Please select a policy type", labelKey: "policy_type", valueKey: "policy_type_id", onChanged: (val) => setState(() => selectedPolicyType = val), ), const SizedBox(height: 20), Text("Insurer", style: labelStyle()), const SizedBox(height: 5), dropdownFieldMap( value: selectedInsurer, hint: "Select insurer", items: insurerData, validatorMsg: "Please select an insurer", labelKey: "insurer_name", valueKey: "insurer_id", onChanged: (val) => setState(() => selectedInsurer = val), ), const SizedBox(height: 20), Text("Policy Number", style: labelStyle()), const SizedBox(height: 5), TextFormField( controller: policyNoController, decoration: inputDecoration("Enter policy number"), validator: (value) => null, // NOT MANDATORY ), const SizedBox(height: 20), Text("Expiry Date", style: labelStyle()), const SizedBox(height: 5), GestureDetector( onTap: pickExpiryDate, child: AbsorbPointer( child: TextFormField( controller: expDateController, decoration: inputDecoration( "Select expiry date", suffix: const Icon(Icons.calendar_month), ), validator: (value) => value == null || value.isEmpty ? "Expiry date required" : null, ), ), ), const SizedBox(height: 30), SizedBox( width: double.infinity, height: 50, child: ElevatedButton( onPressed: submitForm, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFE26828), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), child: Text( "Save Policy", style: GoogleFonts.poppins( fontSize: 16, color: Colors.white, fontWeight: FontWeight.w600, ), ), ), ), ], ), ), ], ), ), ), const SizedBox(height: 60), ]), ), ), if (isLoading) Container( color: Colors.white70, child: Center( child: Image.asset( 'assets/nhance-loader.gif', height: 60, width: 60, ), ), ), if (Responsive.isDesktop(context)) Align( alignment: Alignment.bottomCenter, child: SizedBox( width: double.infinity, child: CustomFooter())), ]), bottomNavigationBar: Responsive.isDesktop(context) ? null : CustomBottomNavigationBar( 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, onTabChanged: (index) { if (index == 0) context.go('/home'); if (index == 1) context.go('/claims'); if (index == 2) context.go('/faqs'); if (index == 3) context.go('/profile'); if (index == 4) {context.push('/help'); } }, ), ), ); } }