userManagement changes ,profile highlighter

This commit is contained in:
venbaittech 2025-05-19 11:21:20 +05:30
parent 53f2c4d5b5
commit b55b908f42
13 changed files with 842 additions and 539 deletions

View File

@ -403,7 +403,7 @@ class _ApprovalListState extends State<ApprovalList> {
), ),
if (isDesktop) if (isDesktop)
SizedBox( SizedBox(
width: MediaQuery.of(context).size.width * 0.19, width: MediaQuery.of(context).size.width * 0.23,
), ),
if (isDesktop) if (isDesktop)

View File

@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:frontend/config/apiUrl.dart'; import 'package:frontend/config/apiUrl.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -258,7 +259,8 @@ class _LoginWidgetState extends State<LoginWidget> {
return Container( return Container(
// color: Color(0xFF114D8B), // color: Color(0xFF114D8B),
color: Color(0xFFf5f5f5), color: Color(0xFFf5f5f5),
padding: const EdgeInsets.all(20),
padding: const EdgeInsets.all(10),
child: Row( child: Row(
children: [ children: [
if (widget.isDesktop) if (widget.isDesktop)
@ -266,42 +268,67 @@ class _LoginWidgetState extends State<LoginWidget> {
flex: 2, flex: 2,
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( // image: DecorationImage(
image: AssetImage( // image: AssetImage(
'assets/images/login/login_travel.png', // 'assets/images/login/login_travel.png',
), // ),
// // fit: BoxFit.fill
// fit: BoxFit.fill
// fit: BoxFit.contain // fit: BoxFit.contain
// fit: BoxFit.cover, // or BoxFit.contain, BoxFit.fill, etc. // // fit: BoxFit.cover, // or BoxFit.contain, BoxFit.fill, etc.
), // ),
color: Colors.white, color: Color(0xFFE6F0FA),
// color: Color(0xFFF0F7FF),
// color: Colors.white,
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topRight: Radius.circular(25), // Rounded top-left corner topRight: Radius.circular(250), // Rounded top-left corner
bottomRight: bottomRight:
Radius.circular(25), // Rounded bottom-left corner Radius.circular(250), // Rounded bottom-left corner
), ),
), ),
child: Padding( // child: Padding(
padding: const EdgeInsets.only( // padding: const EdgeInsets.only(
left: 0, // left: 0,
), // ),
child: Align( // child: Align(
alignment: Alignment.topLeft, // alignment: Alignment.topLeft,
child: Image.asset( // child: Image.asset(
// 'assets/images/login/logoNew.jpg',
// width: 200, // Optional: control size
// height: 100,
// fit: BoxFit.contain,
// )),
// ),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(
'assets/images/login/logoNew.jpg', 'assets/images/login/logoNew.jpg',
width: 200, // Optional: control size width: 200, // Optional: control size
height: 100, height: 100,
fit: BoxFit.contain, fit: BoxFit.contain,
),
Expanded(
child: Container(
child: Align(
// alignment: Alignment.bottomRight,
child: Image.asset(
'assets/images/login/login_travel.png',
// width: 200, // Optional: control size
// height: 100,
fit: BoxFit.contain,
)), )),
), ),
)
],
),
), ),
), ),
Expanded( Expanded(
flex: 1, flex: 1,
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, // color: Colors.white,
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(25), // Rounded top-left corner topLeft: Radius.circular(25), // Rounded top-left corner
bottomLeft: Radius.circular(25), // Rounded bottom-left corner bottomLeft: Radius.circular(25), // Rounded bottom-left corner
@ -329,20 +356,18 @@ class _LoginWidgetState extends State<LoginWidget> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Text( Text(
"Sign In", "Sign In",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 26, fontSize: 18,
fontFamily: "Nunito", fontWeight: FontWeight.w500,
fontWeight: FontWeight.w600,
color: Color(0xFF212121)), color: Color(0xFF212121)),
), ),
const SizedBox(height: 2), const SizedBox(height: 2),
const Text( Text(
"Welcome To TravelSpends", "Welcome To TravelSpends",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 11, fontSize: 11,
fontFamily: "Nunito",
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Color(0xFF212121)), color: Color(0xFF212121)),
), ),
@ -353,10 +378,8 @@ class _LoginWidgetState extends State<LoginWidget> {
_buildLabel("Email Address"), _buildLabel("Email Address"),
TextFormField( TextFormField(
controller: _emailController, controller: _emailController,
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Archivo", fontWeight: FontWeight.w600, fontSize: 11),
fontWeight: FontWeight.w600,
fontSize: 11),
decoration: decoration:
_inputDecoration("Enter your email address").copyWith( _inputDecoration("Enter your email address").copyWith(
prefixIcon: Icon( prefixIcon: Icon(
@ -374,10 +397,8 @@ class _LoginWidgetState extends State<LoginWidget> {
_buildLabel("Password"), _buildLabel("Password"),
TextFormField( TextFormField(
controller: _passwordController, controller: _passwordController,
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Archivo", fontWeight: FontWeight.w600, fontSize: 11),
fontWeight: FontWeight.w600,
fontSize: 11),
obscureText: _obscureText, obscureText: _obscureText,
decoration: _inputDecoration("Enter your password").copyWith( decoration: _inputDecoration("Enter your password").copyWith(
prefixIcon: Icon( prefixIcon: Icon(
@ -422,10 +443,8 @@ class _LoginWidgetState extends State<LoginWidget> {
children: [ children: [
Text( Text(
"Sign In", "Sign In",
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Nunito", fontWeight: FontWeight.w800, fontSize: 15),
fontWeight: FontWeight.w800,
fontSize: 15),
), ),
SizedBox( SizedBox(
width: 3, width: 3,
@ -445,10 +464,8 @@ class _LoginWidgetState extends State<LoginWidget> {
_buildLabel("Email Address"), _buildLabel("Email Address"),
TextFormField( TextFormField(
controller: _emailController, controller: _emailController,
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Archivo", fontWeight: FontWeight.w600, fontSize: 11),
fontWeight: FontWeight.w600,
fontSize: 11),
decoration: decoration:
_inputDecoration("Enter your email address").copyWith( _inputDecoration("Enter your email address").copyWith(
prefixIcon: Icon( prefixIcon: Icon(
@ -481,10 +498,8 @@ class _LoginWidgetState extends State<LoginWidget> {
children: [ children: [
Text( Text(
"Submit", "Submit",
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Nunito", fontWeight: FontWeight.w800, fontSize: 15),
fontWeight: FontWeight.w800,
fontSize: 15),
), ),
SizedBox( SizedBox(
width: 3, width: 3,
@ -505,10 +520,8 @@ class _LoginWidgetState extends State<LoginWidget> {
TextFormField( TextFormField(
controller: _emailController, controller: _emailController,
readOnly: true, readOnly: true,
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Archivo", fontWeight: FontWeight.w600, fontSize: 11),
fontWeight: FontWeight.w600,
fontSize: 11),
decoration: decoration:
_inputDecoration("Enter your email address").copyWith( _inputDecoration("Enter your email address").copyWith(
prefixIcon: Icon( prefixIcon: Icon(
@ -523,10 +536,8 @@ class _LoginWidgetState extends State<LoginWidget> {
_buildLabel("OTP"), _buildLabel("OTP"),
TextFormField( TextFormField(
controller: _otpController, controller: _otpController,
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Archivo", fontWeight: FontWeight.w600, fontSize: 11),
fontWeight: FontWeight.w600,
fontSize: 11),
decoration: _inputDecoration("Enter your OTP").copyWith( decoration: _inputDecoration("Enter your OTP").copyWith(
prefixIcon: Icon( prefixIcon: Icon(
Icons.email_outlined, Icons.email_outlined,
@ -540,10 +551,8 @@ class _LoginWidgetState extends State<LoginWidget> {
_buildLabel("New Password"), _buildLabel("New Password"),
TextFormField( TextFormField(
controller: _newPasswordController, controller: _newPasswordController,
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Archivo", fontWeight: FontWeight.w600, fontSize: 11),
fontWeight: FontWeight.w600,
fontSize: 11),
obscureText: _obscureText, obscureText: _obscureText,
decoration: decoration:
_inputDecoration("Enter your new password").copyWith( _inputDecoration("Enter your new password").copyWith(
@ -569,10 +578,8 @@ class _LoginWidgetState extends State<LoginWidget> {
_buildLabel("Confirm Password"), _buildLabel("Confirm Password"),
TextFormField( TextFormField(
controller: _confirmPasswordController, controller: _confirmPasswordController,
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Archivo", fontWeight: FontWeight.w600, fontSize: 11),
fontWeight: FontWeight.w600,
fontSize: 11),
obscureText: _obscureText, obscureText: _obscureText,
decoration: decoration:
_inputDecoration("Enter your confirm password").copyWith( _inputDecoration("Enter your confirm password").copyWith(
@ -630,10 +637,8 @@ class _LoginWidgetState extends State<LoginWidget> {
children: [ children: [
Text( Text(
"Submit", "Submit",
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Nunito", fontWeight: FontWeight.w800, fontSize: 15),
fontWeight: FontWeight.w800,
fontSize: 15),
), ),
SizedBox( SizedBox(
width: 3, width: 3,
@ -663,10 +668,10 @@ class _LoginWidgetState extends State<LoginWidget> {
}, },
child: Text( child: Text(
"Forgot Password", "Forgot Password",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 11, fontSize: 11,
fontWeight: FontWeight.w300, fontWeight: FontWeight.w300,
fontFamily: "Nunito",
color: Color(0xFF212121), // Text color color: Color(0xFF212121), // Text color
decoration: decoration:
TextDecoration.underline, // Underline the text TextDecoration.underline, // Underline the text
@ -686,10 +691,10 @@ class _LoginWidgetState extends State<LoginWidget> {
}, },
child: Text( child: Text(
"Back to Login", "Back to Login",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 11, fontSize: 11,
fontWeight: FontWeight.w300, fontWeight: FontWeight.w300,
fontFamily: "Nunito",
color: Color(0xFF212121), // Text color color: Color(0xFF212121), // Text color
decoration: decoration:
TextDecoration.underline, // Underline the text TextDecoration.underline, // Underline the text
@ -726,10 +731,8 @@ class _LoginWidgetState extends State<LoginWidget> {
children: [ children: [
Text( Text(
"Sign In With Microsoft", "Sign In With Microsoft",
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Nunito", fontWeight: FontWeight.w500, fontSize: 14),
fontWeight: FontWeight.w500,
fontSize: 15),
), ),
SizedBox( SizedBox(
width: 3, width: 3,
@ -785,10 +788,9 @@ class _LoginWidgetState extends State<LoginWidget> {
padding: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.only(bottom: 8),
child: Text( child: Text(
text, text,
style: const TextStyle( style: GoogleFonts.poppins(
fontSize: 11, fontSize: 12,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w600,
fontFamily: "Nunito",
color: Color(0xFF212121)), color: Color(0xFF212121)),
), ),
), ),
@ -803,7 +805,7 @@ class _LoginWidgetState extends State<LoginWidget> {
contentPadding: EdgeInsets.symmetric(vertical: 1.0, horizontal: 0.0), contentPadding: EdgeInsets.symmetric(vertical: 1.0, horizontal: 0.0),
filled: true, filled: true,
fillColor: Colors.white, fillColor: Colors.white,
labelStyle: TextStyle(fontSize: 11, color: Colors.grey), labelStyle: GoogleFonts.poppins(fontSize: 11, color: Colors.grey),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(18), borderRadius: BorderRadius.circular(18),
borderSide: BorderSide( borderSide: BorderSide(

View File

@ -8,6 +8,7 @@ import 'package:frontend/Screens/organization/mailSettings.dart';
import 'package:frontend/Screens/organization/themeColor.dart'; import 'package:frontend/Screens/organization/themeColor.dart';
import 'package:frontend/utils/auth_utils.dart'; import 'package:frontend/utils/auth_utils.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:responsive_builder/responsive_builder.dart'; import 'package:responsive_builder/responsive_builder.dart';
@ -415,7 +416,7 @@ class _groupState extends State<Group> {
children: [ children: [
Text( Text(
"Create Group", "Create Group",
style: TextStyle(fontSize: 18), style: GoogleFonts.poppins(fontSize: 18),
), ),
// Container( // Container(
// color: Color(0xFFE9EBF6), // color: Color(0xFFE9EBF6),

View File

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import '../../config/apiUrl.dart'; import '../../config/apiUrl.dart';
@ -224,7 +225,7 @@ class _MailSettingState extends State<MailSetting> {
children: [ children: [
Text( Text(
"Sender Email", "Sender Email",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFF575A74)), color: Color(0xFF575A74)),
@ -254,11 +255,11 @@ class _MailSettingState extends State<MailSetting> {
"Invalid email format"; "Invalid email format";
} }
}, },
style: TextStyle(fontSize: 12), style: GoogleFonts.poppins(fontSize: 12),
decoration: InputDecoration( decoration: InputDecoration(
labelText: "sender email", labelText: "sender email",
labelStyle: labelStyle: GoogleFonts.poppins(
TextStyle(fontSize: 12, color: Colors.grey), fontSize: 12, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16), contentPadding: EdgeInsets.symmetric(vertical: 16),
@ -315,7 +316,7 @@ class _MailSettingState extends State<MailSetting> {
children: [ children: [
Text( Text(
"Test Mail", "Test Mail",
style: TextStyle( style: GoogleFonts.poppins(
color: Color(0xFF114D8B), fontWeight: FontWeight.w600), color: Color(0xFF114D8B), fontWeight: FontWeight.w600),
), ),
], ],
@ -340,7 +341,7 @@ class _MailSettingState extends State<MailSetting> {
children: [ children: [
Text( Text(
"User Name", "User Name",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFF575A74)), color: Color(0xFF575A74)),
@ -360,10 +361,11 @@ class _MailSettingState extends State<MailSetting> {
onChanged: (value) { onChanged: (value) {
_clearError("mail_user_name"); _clearError("mail_user_name");
}, },
style: TextStyle(fontSize: 12), style: GoogleFonts.poppins(fontSize: 12),
decoration: InputDecoration( decoration: InputDecoration(
labelText: "user name", labelText: "user name",
labelStyle: TextStyle(fontSize: 12, color: Colors.grey), labelStyle:
GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16), contentPadding: EdgeInsets.symmetric(vertical: 16),
@ -385,7 +387,7 @@ class _MailSettingState extends State<MailSetting> {
children: [ children: [
Text( Text(
"Password", "Password",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFF575A74)), color: Color(0xFF575A74)),
@ -409,7 +411,8 @@ class _MailSettingState extends State<MailSetting> {
style: TextStyle(fontSize: 12), style: TextStyle(fontSize: 12),
decoration: InputDecoration( decoration: InputDecoration(
labelText: "password", labelText: "password",
labelStyle: TextStyle(fontSize: 12, color: Colors.grey), labelStyle:
GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16), contentPadding: EdgeInsets.symmetric(vertical: 16),
@ -449,7 +452,7 @@ class _MailSettingState extends State<MailSetting> {
children: [ children: [
Text( Text(
"Host", "Host",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFF575A74)), color: Color(0xFF575A74)),
@ -469,10 +472,11 @@ class _MailSettingState extends State<MailSetting> {
onChanged: (value) { onChanged: (value) {
_clearError("mail_host"); _clearError("mail_host");
}, },
style: TextStyle(fontSize: 12), style: GoogleFonts.poppins(fontSize: 12),
decoration: InputDecoration( decoration: InputDecoration(
labelText: "host", labelText: "host",
labelStyle: TextStyle(fontSize: 12, color: Colors.grey), labelStyle:
GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16), contentPadding: EdgeInsets.symmetric(vertical: 16),
@ -494,7 +498,7 @@ class _MailSettingState extends State<MailSetting> {
children: [ children: [
Text( Text(
"Port", "Port",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFF575A74)), color: Color(0xFF575A74)),
@ -514,10 +518,11 @@ class _MailSettingState extends State<MailSetting> {
onChanged: (value) { onChanged: (value) {
_clearError("mail_port"); _clearError("mail_port");
}, },
style: TextStyle(fontSize: 12), style: GoogleFonts.poppins(fontSize: 12),
decoration: InputDecoration( decoration: InputDecoration(
labelText: "port", labelText: "port",
labelStyle: TextStyle(fontSize: 12, color: Colors.grey), labelStyle:
GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16), contentPadding: EdgeInsets.symmetric(vertical: 16),
@ -544,7 +549,7 @@ class _MailSettingState extends State<MailSetting> {
children: [ children: [
Text( Text(
"Enter Your Mail Id", "Enter Your Mail Id",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFF575A74)), color: Color(0xFF575A74)),
@ -573,10 +578,11 @@ class _MailSettingState extends State<MailSetting> {
errorMessages["to_mail"] = "Invalid email format"; errorMessages["to_mail"] = "Invalid email format";
} }
}, },
style: TextStyle(fontSize: 12), style: GoogleFonts.poppins(fontSize: 12),
decoration: InputDecoration( decoration: InputDecoration(
labelText: "To mail", labelText: "To mail",
labelStyle: TextStyle(fontSize: 12, color: Colors.grey), labelStyle:
GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16), contentPadding: EdgeInsets.symmetric(vertical: 16),
@ -616,7 +622,7 @@ class _MailSettingState extends State<MailSetting> {
}, },
child: Text( child: Text(
"Test Email", "Test Email",
style: TextStyle(fontSize: 12), style: GoogleFonts.poppins(fontSize: 12),
)) ))
], ],
), ),

View File

@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:frontend/Screens/organization/mailSettings.dart'; import 'package:frontend/Screens/organization/mailSettings.dart';
import 'package:frontend/Screens/organization/themeColor.dart'; import 'package:frontend/Screens/organization/themeColor.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart'; import 'package:http_parser/http_parser.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
@ -444,7 +445,8 @@ class _OrgSetUpState extends State<OrgSetUp> {
child: Column( child: Column(
children: [ children: [
Container( Container(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.only(
left: 20, right: 20, bottom: 20, top: 5),
// height: MediaQuery.of(context).size.height * 0.8, // height: MediaQuery.of(context).size.height * 0.8,
color: Colors.white, color: Colors.white,
child: Column( child: Column(
@ -460,8 +462,8 @@ class _OrgSetUpState extends State<OrgSetUp> {
selectedOrg != null && selectedOrg!.isNotEmpty selectedOrg != null && selectedOrg!.isNotEmpty
? "Update Organization" ? "Update Organization"
: "Create Organization", : "Create Organization",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 15, fontWeight: FontWeight.w800), fontSize: 15, fontWeight: FontWeight.w500),
), ),
], ],
), ),
@ -472,12 +474,11 @@ class _OrgSetUpState extends State<OrgSetUp> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Padding( Padding(
padding: EdgeInsets.only(top: 1.0), padding: const EdgeInsets.only(top: 1.0),
child: Text( child: Text(
"Name:", "Name:",
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Archivo",
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFF212121)), color: Color(0xFF212121)),
@ -487,14 +488,15 @@ class _OrgSetUpState extends State<OrgSetUp> {
Expanded( Expanded(
child: TextFormField( child: TextFormField(
controller: _orgNameController, controller: _orgNameController,
style: TextStyle(
style: GoogleFonts.poppins(
fontSize: 16, fontSize: 16,
color: Color(0xFF114D8B), color: Color(0xFF114D8B),
), ),
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Enter Organization Name", hintText: "Enter Organization Name",
hintStyle: hintStyle: GoogleFonts.poppins(
TextStyle(fontSize: 14, color: Colors.grey), fontSize: 14, color: Colors.grey),
floatingLabelBehavior: floatingLabelBehavior:
FloatingLabelBehavior.never, FloatingLabelBehavior.never,
border: InputBorder.none, border: InputBorder.none,
@ -543,8 +545,90 @@ class _OrgSetUpState extends State<OrgSetUp> {
], ],
), ),
), ),
SizedBox( SizedBox(
height: 5, height: 10,
),
Text(
"Services",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFF212121)),
),
SizedBox(
height: 10,
),
Container(
decoration: BoxDecoration(
border: Border.all(color: Color(0xFFF4F4FB)),
borderRadius: BorderRadius.circular(1),
// color: bodyColor,
// color: Color(0xFFF5F5F5),
color: Colors.white),
padding:
EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 5),
child: isDesktop
? Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// mainAxisSize: MainAxisSize.min,
children: _buildOptions(),
)
: Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: _buildOptions(),
),
),
),
),
SizedBox(
height: 15,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Choose Theme",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFF212121)),
),
Container(
decoration: BoxDecoration(
// border: Border.all(color: Color(0xFFF4F4FB)),
borderRadius: BorderRadius.circular(1),
// color: Color(0xFFF4F4FB),
),
padding: EdgeInsets.only(
left: 5, right: 5, top: 15, bottom: 5),
child: layoutColor != null && bodyColor != null
? ColorThemePickerWidget(
initialLayoutColor: layoutColor,
initialBodyColor: bodyColor,
onLayoutColorSelected:
(Color selectedLayoutColor) {
setState(() {
layoutColor = selectedLayoutColor;
});
},
onBodyColorSelected: (Color selectedBodyColor) {
setState(() {
bodyColor = selectedBodyColor;
});
},
)
: CircularProgressIndicator(),
),
],
),
SizedBox(
height: 15,
), ),
Container( Container(
color: Colors.white, color: Colors.white,
@ -555,8 +639,7 @@ class _OrgSetUpState extends State<OrgSetUp> {
children: [ children: [
Text( Text(
"Mail Settings", "Mail Settings",
style: TextStyle( style: GoogleFonts.poppins(
fontFamily: "Archivo",
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFF212121)), color: Color(0xFF212121)),
@ -615,89 +698,6 @@ class _OrgSetUpState extends State<OrgSetUp> {
)) ))
], ],
)), )),
SizedBox(
height: 15,
),
Text(
"Services",
style: TextStyle(
fontFamily: "Archivo",
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFF212121)),
),
SizedBox(
height: 10,
),
Container(
decoration: BoxDecoration(
border: Border.all(color: Color(0xFFF4F4FB)),
borderRadius: BorderRadius.circular(1),
// color: bodyColor,
// color: Color(0xFFF5F5F5),
color: Colors.white),
padding:
EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 5),
child: isDesktop
? Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// mainAxisSize: MainAxisSize.min,
children: _buildOptions(),
)
: Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: _buildOptions(),
),
),
),
),
SizedBox(
height: 15,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Choose Theme",
style: TextStyle(
fontFamily: "Archivo",
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFF212121)),
),
Container(
decoration: BoxDecoration(
// border: Border.all(color: Color(0xFFF4F4FB)),
borderRadius: BorderRadius.circular(1),
// color: Color(0xFFF4F4FB),
),
padding: EdgeInsets.only(
left: 5, right: 5, top: 15, bottom: 5),
child: layoutColor != null && bodyColor != null
? ColorThemePickerWidget(
initialLayoutColor: layoutColor,
initialBodyColor: bodyColor,
onLayoutColorSelected:
(Color selectedLayoutColor) {
setState(() {
layoutColor = selectedLayoutColor;
});
},
onBodyColorSelected: (Color selectedBodyColor) {
setState(() {
bodyColor = selectedBodyColor;
});
},
)
: CircularProgressIndicator(),
),
],
),
// isDesktop // isDesktop
// ? Row( // ? Row(
// mainAxisAlignment: MainAxisAlignment.end, // mainAxisAlignment: MainAxisAlignment.end,
@ -775,21 +775,19 @@ class _OrgSetUpState extends State<OrgSetUp> {
color: color:
isSelected == name ? Color(0xFF114D8B) : Color(0xFF475569)), isSelected == name ? Color(0xFF114D8B) : Color(0xFF475569)),
SizedBox(width: 5), SizedBox(width: 2),
SizedBox(width: 5),
Text( Text(
name, name,
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 13, fontSize: 12,
color: isSelected == name ? Color(0xFF114D8B) : Color(0xFF475569), color: isSelected == name ? Color(0xFF114D8B) : Color(0xFF475569),
fontFamily: "Archivo",
fontWeight: fontWeight:
isSelected == name ? FontWeight.bold : FontWeight.w500), isSelected == name ? FontWeight.bold : FontWeight.w500),
// fontWeight: selectedListOption == title ? FontWeight.bold : FontWeight.normal,)), // fontWeight: selectedListOption == title ? FontWeight.bold : FontWeight.normal,)),
), ),
SizedBox(width: 5), SizedBox(width: 2),
// if (selectedListOption == title && widget.isViewMode == false) // if (selectedListOption == title && widget.isViewMode == false)
Container( Container(
height: 15, height: 15,
@ -849,7 +847,10 @@ class _OrgSetUpState extends State<OrgSetUp> {
onPressed: () { onPressed: () {
context.go('/listPlan'); context.go('/listPlan');
}, },
child: Text("Cancel")), child: Text(
"Cancel",
style: GoogleFonts.poppins(fontSize: 12),
)),
SizedBox( SizedBox(
width: 20, width: 20,
), ),
@ -871,7 +872,10 @@ class _OrgSetUpState extends State<OrgSetUp> {
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
), ),
onPressed: handleSubmit, // Disable when in view mode onPressed: handleSubmit, // Disable when in view mode
child: Text("Submit"), child: Text(
"Submit",
style: GoogleFonts.poppins(fontSize: 12),
),
), ),
) )
]; ];

View File

@ -379,7 +379,10 @@ class _ListPlansState extends State<ListPlans> {
], ],
), ),
Spacer(), // Spacer(),
SizedBox(
width: MediaQuery.of(context).size.width * 0.23,
),
if (isDesktop) if (isDesktop)
Container( Container(
width: MediaQuery.of(context).size.width * 0.2, width: MediaQuery.of(context).size.width * 0.2,
@ -773,7 +776,8 @@ class _ListPlansState extends State<ListPlans> {
context); // Close popup manually context); // Close popup manually
ApiService.viewPlan( ApiService.viewPlan(
context, plan.planId, context, plan.planId,
isViewMode: true); isViewMode: true,
isMyTrips: true);
}, },
), ),
IconButton( IconButton(
@ -785,7 +789,8 @@ class _ListPlansState extends State<ListPlans> {
Navigator.pop(context); Navigator.pop(context);
ApiService.viewPlan( ApiService.viewPlan(
context, plan.planId, context, plan.planId,
isViewMode: false); isViewMode: false,
isMyTrips: true);
}, },
), ),
IconButton( IconButton(

View File

@ -70,6 +70,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
late List<dynamic>? apiRoleData; late List<dynamic>? apiRoleData;
late List<dynamic>? apiUserData; late List<dynamic>? apiUserData;
Map<String, dynamic>? apiselectedUser; Map<String, dynamic>? apiselectedUser;
List<Map<String, dynamic>> selectedServiceIds = [];
late List<dynamic> userList; late List<dynamic> userList;
late Future<List<dynamic>> futureUsers; late Future<List<dynamic>> futureUsers;
@ -146,7 +147,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
"address": controllers["address"]?.text, "address": controllers["address"]?.text,
"gender": selectedGender, "gender": selectedGender,
// "gender": personalDetailsKey.currentState?.selectedGender, // "gender": personalDetailsKey.currentState?.selectedGender,
"agent_supported_service_ids": selectedServiceIds,
"postal_code": controllers["postalCode"]?.text, "postal_code": controllers["postalCode"]?.text,
"country_code": selectedCountry, "country_code": selectedCountry,
"employee_code": controllers["employeeCode"]?.text, "employee_code": controllers["employeeCode"]?.text,
@ -270,6 +271,27 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
selectedThirdApprover = selectedThirdApprover =
apiselectedUser?["third_approver"]?.toString() ?? ""; apiselectedUser?["third_approver"]?.toString() ?? "";
} }
try {
final raw = apiselectedUser!["agent_supported_service_ids"];
// Fix the invalid JSON (dangerous if the format changes)
final fixedJson = raw.replaceAllMapped(
RegExp(r'(\w+):'), // matches `service_id:`
(match) => '"${match.group(1)}":',
);
List<dynamic> decodedList = jsonDecode(fixedJson);
selectedServiceIds = decodedList.map<Map<String, dynamic>>((item) {
final map = Map<String, dynamic>.from(item);
return {
"service_id": map['service_id'].toString(),
};
}).toList();
} catch (e) {
print("❌ Error decoding fixed agent_supported_service_ids: $e");
selectedServiceIds = [];
}
print("Updated selectedGender: $selectedGender"); // Debugging print("Updated selectedGender: $selectedGender"); // Debugging
@ -932,6 +954,13 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
selectedRole = role; selectedRole = role;
}); });
}, },
onServiceIdsChanged: (List<Map<String, dynamic>> updatedList) {
setState(() {
selectedServiceIds = updatedList;
});
},
initialSelectedServices: selectedServiceIds,
); );
case "office": case "office":
return OfficeDetails( return OfficeDetails(
@ -991,6 +1020,11 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
selectedCountry: selectedCountry, selectedCountry: selectedCountry,
apiselectedUser: isapiselectedUser, apiselectedUser: isapiselectedUser,
onUserTypeChanged: handleUserTypeChange, onUserTypeChanged: handleUserTypeChange,
onServiceIdsChanged: (List<Map<String, dynamic>> updatedList) {
setState(() {
selectedServiceIds = updatedList;
});
},
); );
} }
} }

View File

@ -20,10 +20,13 @@ class PersonalDetails extends StatefulWidget {
final bool isViewMode; final bool isViewMode;
final bool apiselectedUser; final bool apiselectedUser;
final Function(List<Map<String, dynamic>>)? onServiceIdsChanged;
final ValueChanged<String?>? onGenderChanged; final ValueChanged<String?>? onGenderChanged;
final ValueChanged<String?>? onCountryChanged; final ValueChanged<String?>? onCountryChanged;
final ValueChanged<String?>? onRoleChanged; final ValueChanged<String?>? onRoleChanged;
final void Function(bool)? onUserTypeChanged; final void Function(bool)? onUserTypeChanged;
final List<Map<String, dynamic>>? initialSelectedServices;
final String? selectedGender; final String? selectedGender;
final String? selectedCountry; final String? selectedCountry;
@ -35,7 +38,9 @@ class PersonalDetails extends StatefulWidget {
this.selectedGender, this.selectedGender,
this.selectedCountry, this.selectedCountry,
this.selectedRole, this.selectedRole,
this.onServiceIdsChanged,
required this.personalDetailsKey, required this.personalDetailsKey,
this.initialSelectedServices,
required this.controllers, required this.controllers,
required this.errorMessages, required this.errorMessages,
required this.isDesktop, required this.isDesktop,
@ -131,6 +136,10 @@ class PersonalDetailsState extends State<PersonalDetails> {
selectedRole = widget.selectedRole; selectedRole = widget.selectedRole;
fetchRoles(); fetchRoles();
fetchCountries(); fetchCountries();
selectedServiceIds =
List<Map<String, dynamic>>.from(widget.initialSelectedServices ?? []);
print("selectedServiceIdsAPI - $selectedServiceIds");
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
loadAllServices(); loadAllServices();
@ -199,13 +208,22 @@ class PersonalDetailsState extends State<PersonalDetails> {
services = []; services = [];
} }
if (selectedServiceIds.isEmpty && services.isNotEmpty) {
selectedServiceIds = services.map<Map<String, dynamic>>((item) { selectedServiceIds = services.map<Map<String, dynamic>>((item) {
// force cast or copy to a regular map
final map = Map<String, dynamic>.from(item); final map = Map<String, dynamic>.from(item);
return { return {
"service_id": map['service_id'].toString(), "service_id": map['service_id'].toString(),
}; };
}).toList(); }).toList();
}
// selectedServiceIds = services.map<Map<String, dynamic>>((item) {
// // force cast or copy to a regular map
// final map = Map<String, dynamic>.from(item);
// return {
// "service_id": map['service_id'].toString(),
// };
// }).toList();
}); });
// orgId = await getOrgId(); // orgId = await getOrgId();
@ -351,6 +369,9 @@ class PersonalDetailsState extends State<PersonalDetails> {
} else { } else {
selectedServiceIds.add({"service_id": serviceId}); selectedServiceIds.add({"service_id": serviceId});
} }
// Call the parent's callback
widget.onServiceIdsChanged!(selectedServiceIds);
}); });
}, },
child: Row(children: [ child: Row(children: [
@ -755,7 +776,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
setState(() { setState(() {
_selectedDateOfBirth = pickedDate; _selectedDateOfBirth = pickedDate;
widget.controllers["dob"]?.text = widget.controllers["dob"]?.text =
DateFormat('yyyy-MM-dd').format(pickedDate); DateFormat('dd-MM-yyyy').format(pickedDate);
}); });
} }
} }

View File

@ -50,6 +50,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
html.File? passportFile; html.File? passportFile;
late List<bool> isExpandedList; late List<bool> isExpandedList;
int? expandedIndex; int? expandedIndex;
bool isCountryLoading = true;
late final userId; late final userId;
String? selectedFileNames; String? selectedFileNames;
@ -79,6 +80,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
Map<String, String> countryMap = {}; Map<String, String> countryMap = {};
late List<dynamic>? apiCountryData; late List<dynamic>? apiCountryData;
late List<dynamic>? apiAirlineCountryData;
Map<String, dynamic>? apiData; Map<String, dynamic>? apiData;
final Map<String, TextEditingController> controllers = {}; final Map<String, TextEditingController> controllers = {};
@ -86,7 +88,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
"Passport Details", "Passport Details",
// "Local ID Details", // "Local ID Details",
"Visa Details", "Visa Details",
"Frequent Flier Information", "Frequent Flyer Information",
"Hotel Loyalty Membership", "Hotel Loyalty Membership",
"Preferences Domestic", "Preferences Domestic",
"Preferences International", "Preferences International",
@ -94,6 +96,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
"Forex Details" "Forex Details"
]; ];
//To Create Controllers
List<String> dataHeader = [ List<String> dataHeader = [
"Fname", "Fname",
"Lname", "Lname",
@ -111,6 +114,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
"forex_card_num", "forex_card_num",
"full_name_as_id", "full_name_as_id",
"local_id_num", "local_id_num",
"forex_expiry_date"
]; ];
@override @override
@ -120,11 +124,13 @@ class TravellerDetailsState extends State<TravellerDetails> {
// userId = getUserId(); // userId = getUserId();
apiCountryData = null; apiCountryData = null;
apiAirlineCountryData = [];
apiData = null; apiData = null;
for (var field in dataHeader) { for (var field in dataHeader) {
controllers[field] = TextEditingController(); controllers[field] = TextEditingController();
} }
fetchCountries(); fetchCountries();
loadCountryList();
fetchApiData(); fetchApiData();
// Delay adding the row until after the first frame // Delay adding the row until after the first frame
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
@ -170,7 +176,8 @@ class TravellerDetailsState extends State<TravellerDetails> {
frequentFlierEntries.add({ frequentFlierEntries.add({
"local_id": localId, "local_id": localId,
"id": null, // to be set when backend responds "id": null, // to be set when backend responds
"controller_airline": TextEditingController(), // "controller_airline": null,
"airline": null,
"controller_flier_number": TextEditingController(), "controller_flier_number": TextEditingController(),
"is_active": "1" "is_active": "1"
}); });
@ -196,7 +203,6 @@ class TravellerDetailsState extends State<TravellerDetails> {
"visa_type_id": null, "visa_type_id": null,
"controller_valid_from": TextEditingController(), "controller_valid_from": TextEditingController(),
"controller_valid_upto": TextEditingController(), "controller_valid_upto": TextEditingController(),
"is_active": "1" "is_active": "1"
}); });
setState(() {}); setState(() {});
@ -240,12 +246,13 @@ class TravellerDetailsState extends State<TravellerDetails> {
"date_of_expiry": controllers["dateOfExpiry"]?.text, "date_of_expiry": controllers["dateOfExpiry"]?.text,
"d_meal_preference": controllers["d_meal_pref"]?.text, "d_meal_preference": controllers["d_meal_pref"]?.text,
"d_seat_preference": selectedDomesticSeat, "d_seat_preference": selectedDomesticSeat,
// "d_additonalInfo": controllers["d_additonal_Info"]?.text, "d_additonalInfo": controllers["d_additonal_Info"]?.text,
"i_meal_preference": controllers["i_meal_pref"]?.text, "i_meal_preference": controllers["i_meal_pref"]?.text,
"i_seat_preference": selectedIntenationalSeat, "i_seat_preference": selectedIntenationalSeat,
// "i_additonalInfo": controllers["i_additonal_Info"]?.text, "i_additonalInfo": controllers["i_additonal_Info"]?.text,
"emergency_contact_number": controllers["emergency_contact"]?.text, "emergency_contact_number": controllers["emergency_contact"]?.text,
"forex_pre_paid_card_number": controllers["forex_card_num"]?.text, "forex_pre_paid_card_number": controllers["forex_card_num"]?.text,
"forex_expiry_date": controllers["forex_expiry_date"]?.text,
// "frequent_flier_information": [], // "frequent_flier_information": [],
"frequent_flier_information": frequentFlierList, "frequent_flier_information": frequentFlierList,
"hotel_membership": hotelMembershipList, "hotel_membership": hotelMembershipList,
@ -270,14 +277,33 @@ class TravellerDetailsState extends State<TravellerDetails> {
}).toList(); }).toList();
} }
// List<Map<String, dynamic>> get frequentFlierList {
// return frequentFlierEntries
// // .where((entry) => entry["is_active"] != "0") // Only active entries
// .map((entry) {
// return {
// "id": entry["id"],
// "airline": entry["airline"],
// "frequent_flier_number": entry["controller_flier_number"].text,
// "created_by": null,
// "updated_by": null,
// "is_active": entry["is_active"] ?? "1",
// };
// }).toList();
// }
List<Map<String, dynamic>> get frequentFlierList { List<Map<String, dynamic>> get frequentFlierList {
return frequentFlierEntries return frequentFlierEntries.map((entry) {
// .where((entry) => entry["is_active"] != "0") // Only active entries final frequent_flier_number = entry["controller_flier_number"];
.map((entry) {
print("frequent_flier_number- $frequent_flier_number");
return { return {
"id": entry["id"], "id": entry["id"],
"airline": entry["controller_airline"].text, "airline": entry["airline"], // string value
"frequent_flier_number": entry["controller_flier_number"].text, "frequent_flier_number": frequent_flier_number is TextEditingController
? frequent_flier_number.text
: "",
"created_by": null, "created_by": null,
"updated_by": null, "updated_by": null,
"is_active": entry["is_active"] ?? "1", "is_active": entry["is_active"] ?? "1",
@ -346,10 +372,14 @@ class TravellerDetailsState extends State<TravellerDetails> {
controllers["d_meal_pref"]?.text = controllers["d_meal_pref"]?.text =
widget.travelDetails?["d_meal_preference"] ?? ""; widget.travelDetails?["d_meal_preference"] ?? "";
controllers["i_meal_pref"]?.text = controllers["i_meal_pref"]?.text =
widget.travelDetails?["i_meal_preference"] ?? ""; widget.travelDetails?["i_meal_preference"] ?? "";
controllers["d_additonal_Info"]?.text =
widget.travelDetails?["d_additonalInfo"] ?? "";
controllers["i_additonal_Info"]?.text =
widget.travelDetails?["i_additonalInfo"] ?? "";
selectedIntenationalSeat = selectedIntenationalSeat =
widget.travelDetails?["i_seat_preference"] ?? ""; widget.travelDetails?["i_seat_preference"] ?? "";
selectedDomesticSeat = widget.travelDetails?["d_seat_preference"] ?? ""; selectedDomesticSeat = widget.travelDetails?["d_seat_preference"] ?? "";
@ -359,6 +389,8 @@ class TravellerDetailsState extends State<TravellerDetails> {
controllers["forex_card_num"]?.text = controllers["forex_card_num"]?.text =
widget.travelDetails?["forex_pre_paid_card_number"] ?? ""; widget.travelDetails?["forex_pre_paid_card_number"] ?? "";
controllers["forex_expiry_date"]?.text =
widget.travelDetails?["forex_expiry_date"] ?? "";
String? apiDocPath = widget.travelDetails?["passport_document"]; String? apiDocPath = widget.travelDetails?["passport_document"];
if (apiDocPath != null && apiDocPath.isNotEmpty) { if (apiDocPath != null && apiDocPath.isNotEmpty) {
@ -402,38 +434,6 @@ class TravellerDetailsState extends State<TravellerDetails> {
} }
//---------------------------------------------------- //----------------------------------------------------
// 🚨 Frequent Flier Logic (pre-fill for edit)
for (var entry in frequentFlierEntries) {
entry["controller_airline"].dispose();
entry["controller_flier_number"].dispose();
}
frequentFlierEntries.clear();
final frequentFlierList =
widget.travelDetails?['frequent_flier_information'];
if (frequentFlierList != null && frequentFlierList is List) {
for (var item in frequentFlierList) {
if (item["is_active"]?.toString() == "0") continue;
final localId = _rowFlierCounter++;
frequentFlierEntries.add({
"local_id": localId,
"id": item["id"],
"controller_airline":
TextEditingController(text: item["airline"] ?? ""),
"controller_flier_number": TextEditingController(
text: item["frequent_flier_number"] ?? ""),
});
}
if (frequentFlierEntries.isEmpty) {
addFrequentFlierEntry();
}
}
//----------------------------------------------------
// 🚨 Visa Logic (pre-fill for edit) // 🚨 Visa Logic (pre-fill for edit)
for (var entry in visaEntries) { for (var entry in visaEntries) {
entry["controller_valid_from"]?.dispose(); entry["controller_valid_from"]?.dispose();
@ -463,6 +463,40 @@ class TravellerDetailsState extends State<TravellerDetails> {
addVisaEntry(); addVisaEntry();
} }
} }
// ----------------------------------------------------
// 🚨 Frequent Flier Logic (pre-fill for edit)
for (var entry in frequentFlierEntries) {
// entry["controller_airline"].dispose();
entry["controller_flier_number"].dispose();
}
frequentFlierEntries.clear();
final frequentFlierList =
widget.travelDetails?['frequent_flier_information'];
if (frequentFlierList != null && frequentFlierList is List) {
for (var item in frequentFlierList) {
if (item["is_active"]?.toString() == "0") continue;
final localId = _rowFlierCounter++;
final airlineCode = item["airline"];
frequentFlierEntries.add({
"local_id": localId,
"id": item["id"],
"airline": airlineCode ?? "",
"controller_flier_number": TextEditingController(
text: item["frequent_flier_number"] ?? ""),
});
}
if (frequentFlierEntries.isEmpty) {
addFrequentFlierEntry();
}
}
//----------------------------------------------------
setState(() {}); setState(() {});
} }
@ -479,6 +513,35 @@ class TravellerDetailsState extends State<TravellerDetails> {
} }
} }
Future<void> loadCountryList() async {
final newTripType = "2";
final result = await apiService.fetchFlightsCountryList(newTripType);
print("resultFlight: $result ");
setState(() {
apiAirlineCountryData = result;
});
// print("ResultCountry : $result");
//
// // Create a map: Country_Code -> "City, Airport"
// Map<String, String> tempCountryMap = {};
//
// for (var country in result) {
// String city = country['City'] ?? '';
// String airport = country['Airport'] ?? '';
// String displayName = '${country['City']} - ${country['Airport']}';
//
// tempCountryMap[country['Code']] = displayName;
// }
//
// setState(() {
// countryMap = tempCountryMap; // Update the map
// isCountryLoading = false;
// });
}
Future<void> fetchApiData() async { Future<void> fetchApiData() async {
try { try {
final data = await apiService.fetchMasterDropdown(); final data = await apiService.fetchMasterDropdown();
@ -605,7 +668,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
case "Visa Details": case "Visa Details":
return _buildVisaDetails(widget.isDesktop); return _buildVisaDetails(widget.isDesktop);
case "Frequent Flier Information": case "Frequent Flyer Information":
return _buildFrequentFlierInfo(widget.isDesktop); return _buildFrequentFlierInfo(widget.isDesktop);
case "Hotel Loyalty Membership": case "Hotel Loyalty Membership":
@ -960,7 +1023,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
setState(() { setState(() {
_selectedDateOfIssue = pickedDate; _selectedDateOfIssue = pickedDate;
controllers["dateOfIssue"]?.text = controllers["dateOfIssue"]?.text =
DateFormat('yyyy-MM-dd').format(pickedDate); DateFormat('dd-MM-yyyy').format(pickedDate);
}); });
} }
} }
@ -1038,7 +1101,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
setState(() { setState(() {
_selectedDateOfExpiry = pickedDate; _selectedDateOfExpiry = pickedDate;
controllers["dateOfExpiry"]?.text = controllers["dateOfExpiry"]?.text =
DateFormat('yyyy-MM-dd').format(pickedDate); DateFormat('dd-MM-yyyy').format(pickedDate);
// controllers["dateOfExpiry"]?.text = // controllers["dateOfExpiry"]?.text =
// DateFormat('dd-MM-yyyy').format(pickedDate); // DateFormat('dd-MM-yyyy').format(pickedDate);
@ -1497,8 +1560,8 @@ class TravellerDetailsState extends State<TravellerDetails> {
buildDomesticSeatType(), buildDomesticSeatType(),
SizedBox(width: 15), SizedBox(width: 15),
buildDomesticMealPref(), buildDomesticMealPref(),
// SizedBox(width: 15), SizedBox(width: 15),
// buildDomesticAddtnlPref(), buildDomesticAddtnlPref(),
], ],
) )
: Column( : Column(
@ -1507,9 +1570,9 @@ class TravellerDetailsState extends State<TravellerDetails> {
buildDomesticSeatType(), buildDomesticSeatType(),
SizedBox(height: 8), SizedBox(height: 8),
buildDomesticMealPref(), buildDomesticMealPref(),
// SizedBox(height: 8), // Vertical space SizedBox(height: 8), // Vertical space
//
// buildDomesticAddtnlPref(), buildDomesticAddtnlPref(),
], ],
), ),
); );
@ -1702,8 +1765,8 @@ class TravellerDetailsState extends State<TravellerDetails> {
buildInternationalSeatType(), buildInternationalSeatType(),
SizedBox(width: 15), SizedBox(width: 15),
buildInternationalMealPref(), buildInternationalMealPref(),
// SizedBox(width: 15), SizedBox(width: 15),
// buildInternationalAddtnlPref(), buildInternationalAddtnlPref(),
], ],
) )
: Column( : Column(
@ -1712,9 +1775,9 @@ class TravellerDetailsState extends State<TravellerDetails> {
buildInternationalSeatType(), buildInternationalSeatType(),
SizedBox(height: 8), SizedBox(height: 8),
buildInternationalMealPref(), buildInternationalMealPref(),
// SizedBox(height: 8), // Vertical space SizedBox(height: 8), // Vertical space
//
// buildInternationalAddtnlPref(), buildInternationalAddtnlPref(),
], ],
), ),
); );
@ -1947,11 +2010,34 @@ class TravellerDetailsState extends State<TravellerDetails> {
SizedBox( SizedBox(
height: 10, height: 10,
), ),
buildForexCardNumber(), _buildForexDetailDataRow1(isDesktop),
], ],
); );
} }
Widget _buildForexDetailDataRow1(bool isDesktop) {
return Container(
color: Colors.white,
child: widget.isDesktop
? Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildForexCardNumber(),
SizedBox(width: 15),
buildForexExpiryDate(),
],
)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildForexCardNumber(),
SizedBox(height: 8),
buildForexExpiryDate()
],
),
);
}
Widget buildForexCardNumber() { Widget buildForexCardNumber() {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -1989,6 +2075,79 @@ class TravellerDetailsState extends State<TravellerDetails> {
); );
} }
Widget buildForexExpiryDate() {
DateTime? _selectedExpiryDate;
Future<void> _selectExpiryDate(BuildContext context) async {
DateTime now = DateTime.now();
DateTime today = DateTime(now.year, now.month, now.day);
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate:
_selectedExpiryDate != null && _selectedExpiryDate!.isAfter(today)
? _selectedExpiryDate!
: today,
firstDate: DateTime(1900),
lastDate: DateTime(2100),
);
if (pickedDate != null && pickedDate != _selectedExpiryDate) {
setState(() {
_selectedExpiryDate = pickedDate;
// controllers["forex_expiry_date"]?.text =
// DateFormat('yyyy-MM-dd').format(pickedDate);
controllers["forex_expiry_date"]?.text =
DateFormat('dd-MM-yyyy').format(pickedDate);
});
}
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Forex Expiry Date",
style: GoogleFonts.poppins(
fontSize: 12, fontWeight: FontWeight.w400, color: Colors.black),
),
SizedBox(height: 5),
CustomTextFieldUserTravellerWrapper(
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 40,
child: GestureDetector(
onTap: widget.isViewMode
? null
: () async {
await _selectExpiryDate(context);
},
child: AbsorbPointer(
child: TextField(
controller: controllers["forex_expiry_date"],
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
decoration: InputDecoration(
labelText: "Select Date",
labelStyle: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16),
suffixIcon: Icon(Icons.calendar_today,
size: 16, color: Color(0xFF8B8FB2)),
),
),
),
),
),
),
],
);
}
//-------------------------Frequent Flier Information ------------------------------- //-------------------------Frequent Flier Information -------------------------------
Widget _buildFrequentFlierInfo(bool isDesktop) { Widget _buildFrequentFlierInfo(bool isDesktop) {
@ -2056,6 +2215,50 @@ class TravellerDetailsState extends State<TravellerDetails> {
} }
Widget buildAirline(Map<String, dynamic> entry) { Widget buildAirline(Map<String, dynamic> entry) {
late Map<String, String> countryMap; // Mapping country_code -> country_name
late List<String> countryCodes; // List of country codes
// countryList = [];
bool hasAirlineCountryData =
apiAirlineCountryData == null || apiAirlineCountryData!.isEmpty;
countryList = apiAirlineCountryData!;
print("TestcountryList2 - $countryList");
countryMap = {
for (var country in countryList)
country['Code'] as String: '${country['City']} - ${country['Airport']}'
};
countryCodes = countryMap.keys.toList();
// setState(() {
// countryMap = tempCountryMap; // Update the map
// isCountryLoading = false;
// });
// Map country codes to country names
// countryMap = {
//
//
// for (var item in countryList)
// item['country_code'] as String: item['country_name'] as String
// };
// Extract only country codes for processing
//--------------------------
// String? selectedCountry = entry['airline'];
String? selectedCode = entry['airline'];
String? selectedText =
selectedCode != null ? countryMap[selectedCode] : null;
print("selectedCode: $selectedCode");
print("selectedText: $selectedText");
print(
"items.contains(selectedText): ${countryMap.values.contains(selectedText)}");
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -2067,30 +2270,105 @@ class TravellerDetailsState extends State<TravellerDetails> {
SizedBox(height: 5), SizedBox(height: 5),
CustomTextFieldUserTravellerWrapper( CustomTextFieldUserTravellerWrapper(
width: widget.isDesktop width: widget.isDesktop
? MediaQuery.of(context).size.width * 0.15 ? MediaQuery.of(context).size.width * 0.17
: null, : null,
isFocused: false, isFocused: false,
isDesktop: widget.isDesktop, isDesktop: widget.isDesktop,
child: SizedBox( child: SizedBox(
height: 40, height: 40,
child: TextField( child: hasAirlineCountryData
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), ? CircularProgressIndicator()
controller: entry["controller_airline"], : DropdownSearch<String>(
enabled: !widget.isViewMode, // selectedItem: countryMap[selectedCountry],
onChanged: (value) { // selectedItem: entry['airline'] != null
_clearError("first_name"); // ? countryMap[entry['airline']]
}, // : null,
// selectedItem: countryMap.containsKey(entry['airline'])
// ? countryMap[entry['airline']]
// : null,
// selectedItem: countryMap[selectedCode],
// selectedItem: countryMap.containsKey(selectedCode)
// ? countryMap[selectedCode]
// : null,
selectedItem: (entry["airline"] != null &&
countryMap.containsKey(entry["airline"]))
? countryMap[entry["airline"]]
: null,
popupProps: PopupProps.menu(
showSearchBox: true, // Enables search functionality
searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
labelText: "Airline", hintText: "Search Country...",
labelStyle: contentPadding: EdgeInsets.symmetric(horizontal: 10),
GoogleFonts.poppins(fontSize: 12, color: Colors.grey), ),
floatingLabelBehavior: FloatingLabelBehavior.never, ),
),
items: countryMap.values.toList(),
dropdownDecoratorProps: DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration(
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16), contentPadding: EdgeInsets.symmetric(
horizontal: 1,
), ),
), ),
), ),
dropdownBuilder: (context, selectedItem) => Align(
// Center-align selected item
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select Country",
style: TextStyle(fontSize: 12),
), ),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
// selectedCountry = countryMap.entries
// .firstWhere((entry) => entry.value == newValue)
// .key;
final selectedCode = countryMap.entries
.firstWhere((entry) => entry.value == newValue)
.key;
entry['airline'] = selectedCode;
// final selectedCode = countryMap.entries
// .firstWhere((entry) => entry.value == newValue)
// .key;
// entry['airline'] = selectedCode;
});
},
),
),
),
// CustomTextFieldUserTravellerWrapper(
// width: widget.isDesktop
// ? MediaQuery.of(context).size.width * 0.15
// : null,
// isFocused: false,
// isDesktop: widget.isDesktop,
// child: SizedBox(
// height: 40,
// child: TextField(
// style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
// controller: entry["controller_airline"],
// enabled: !widget.isViewMode,
// onChanged: (value) {
// _clearError("first_name");
// },
// decoration: InputDecoration(
// labelText: "Airline",
// labelStyle:
// GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
// floatingLabelBehavior: FloatingLabelBehavior.never,
// border: InputBorder.none,
// contentPadding: EdgeInsets.symmetric(vertical: 16),
// ),
// ),
// ),
// ),
], ],
); );
} }
@ -2102,7 +2380,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"Frequent Flier Information", "Frequent Flyer Information",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontWeight: FontWeight.w400, color: Colors.black), fontSize: 12, fontWeight: FontWeight.w400, color: Colors.black),
), ),
@ -2120,7 +2398,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
_clearError("first_name"); _clearError("first_name");
}, },
decoration: InputDecoration( decoration: InputDecoration(
labelText: "Frequent Flier Information", labelText: "Frequent Flyer Information",
labelStyle: labelStyle:
GoogleFonts.poppins(fontSize: 12, color: Colors.grey), GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
@ -2145,7 +2423,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
size: 30, size: 30,
), ),
onPressed: () => addFrequentFlierEntry(), onPressed: () => addFrequentFlierEntry(),
tooltip: "Frequent Flier Information", tooltip: "Frequent Flyer Information",
), ),
); );
} }
@ -2397,6 +2675,8 @@ class TravellerDetailsState extends State<TravellerDetails> {
// countryList = []; // countryList = [];
countryList = apiCountryData ?? []; countryList = apiCountryData ?? [];
print("TestcountryList1 - $countryList");
// Map country codes to country names // Map country codes to country names
countryMap = { countryMap = {
for (var item in countryList) for (var item in countryList)
@ -2593,7 +2873,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
// _dateController.text = DateFormat('yyyy-MM-dd').format(pickedDate); // _dateController.text = DateFormat('yyyy-MM-dd').format(pickedDate);
entry["controller_valid_from"].text = entry["controller_valid_from"].text =
DateFormat('yyyy-MM-dd').format(pickedDate); DateFormat('dd-MM-yyyy').format(pickedDate);
}); });
} }
} }
@ -2673,7 +2953,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
// _dateController.text = DateFormat('yyyy-MM-dd').format(pickedDate); // _dateController.text = DateFormat('yyyy-MM-dd').format(pickedDate);
entry["controller_valid_upto"].text = entry["controller_valid_upto"].text =
DateFormat('yyyy-MM-dd').format(pickedDate); DateFormat('dd-MM-yyyy').format(pickedDate);
}); });
} }
} }

View File

@ -6,7 +6,7 @@ import 'package:shared_preferences/shared_preferences.dart'; // don't forget
import '../services/apiService.dart'; import '../services/apiService.dart';
import '../utils/auth_utils.dart'; import '../utils/auth_utils.dart';
enum TabSelection { allTrips, myTrips, myApprovals } enum TabSelection { allTrips, myTrips, myApprovals, allMenu }
class CustomAppBar extends StatefulWidget implements PreferredSizeWidget { class CustomAppBar extends StatefulWidget implements PreferredSizeWidget {
final bool isDesktop; final bool isDesktop;
@ -34,7 +34,7 @@ class CustomAppBar extends StatefulWidget implements PreferredSizeWidget {
class _CustomAppBarState extends State<CustomAppBar> { class _CustomAppBarState extends State<CustomAppBar> {
final ApiService apiService = ApiService(); final ApiService apiService = ApiService();
TabSelection selectedTab = TabSelection.allTrips; late TabSelection selectedTab;
String? token; String? token;
Map<String, dynamic>? userData; Map<String, dynamic>? userData;
@ -43,14 +43,10 @@ class _CustomAppBarState extends State<CustomAppBar> {
Map<String, dynamic> profileUserDetails = {}; Map<String, dynamic> profileUserDetails = {};
Map<String, dynamic>? selectedOrg; Map<String, dynamic>? selectedOrg;
Color? layoutColor; // Color? layoutColor;
Color? layoutColor = Colors.white10;
Color? bodyColor; Color? bodyColor;
Color _myTravelRequestColor = Color(0xFF475569); // Default color
EdgeInsets _myTravelRequestPadding =
EdgeInsets.symmetric(horizontal: 8, vertical: 4);
Color _myApprovalsColor = Color(0xFF475569); // Default color
void initState() { void initState() {
super.initState(); super.initState();
// initializeData(); // initializeData();
@ -58,6 +54,12 @@ class _CustomAppBarState extends State<CustomAppBar> {
initializeData(); initializeData();
getOrganizationData(); getOrganizationData();
}); });
if (userData?["role"] == "Org Admin" ||
userData?["role"] == "Travel Admin") {
selectedTab = TabSelection.allTrips;
} else {
selectedTab = TabSelection.myTrips;
}
} }
Future<void> getProfileUser() async { Future<void> getProfileUser() async {
@ -94,17 +96,6 @@ class _CustomAppBarState extends State<CustomAppBar> {
getProfileUser(); getProfileUser();
} }
String getTabLabel(TabSelection tab) {
switch (tab) {
case TabSelection.allTrips:
return "All Trips";
case TabSelection.myTrips:
return "My Trips";
case TabSelection.myApprovals:
return "My Approvals";
}
}
Future<String?> getToken() async { Future<String?> getToken() async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
return prefs.getString("auth_token"); return prefs.getString("auth_token");
@ -174,6 +165,43 @@ class _CustomAppBarState extends State<CustomAppBar> {
} }
} }
void handleTabChange(TabSelection tab, String route) {
final currentUri =
GoRouterState.of(context).uri.toString(); // safer than `.location`
print("currentUri - $currentUri");
if (currentUri != route) {
setState(() {
selectedTab = tab;
});
context.go(route);
}
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
final location = GoRouterState.of(context).uri.toString();
print("location - $location");
setState(() {
if (location.contains('/listAllPlan') ||
location.contains('/allTrips/trips')) {
selectedTab = TabSelection.allTrips;
} else if (location.contains('/listPlan') ||
location.contains('/createPlan') ||
location.contains('/listTravelAgentPlan')) {
selectedTab = TabSelection.myTrips;
} else if (location.contains('/ApprovalList')) {
selectedTab = TabSelection.myApprovals;
} else {
selectedTab = TabSelection.allMenu;
}
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AppBar( return AppBar(
@ -216,7 +244,7 @@ class _CustomAppBarState extends State<CustomAppBar> {
) )
: const CircleAvatar( : const CircleAvatar(
radius: 20, radius: 20,
backgroundColor: Colors.white, // backgroundColor: Colors.white,
child: Icon( child: Icon(
Icons.add_a_photo, Icons.add_a_photo,
size: 10, size: 10,
@ -225,186 +253,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
), ),
), ),
SizedBox( SizedBox(
width: MediaQuery.of(context).size.width * 0.2, width: MediaQuery.of(context).size.width * 0.18,
), ),
// Container(
// width: MediaQuery.of(context).size.width * 0.35,
// // color: Colors.blueGrey,
// child: Row(
// // crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// if (userData?["role"] == "Org Admin" ||
// userData?["role"] == "Travel Admin")
// MouseRegion(
// cursor: SystemMouseCursors.click,
// onEnter: (_) {
// setState(() {
// // _myTravelRequestPadding =
// // EdgeInsets.symmetric(horizontal: 12, vertical: 78);
// // _myTravelRequestColor =
// // Color(0xFF114D8B); // Change color on hover
// });
// },
// onExit: (_) {
// setState(() {
// // _myTravelRequestPadding = EdgeInsets.symmetric(
// // horizontal: 8, vertical: 4); // Normal padding
// // _myTravelRequestColor =
// // Color(0xFF475569); // Revert color when hover ends
// });
// },
// child: InkWell(
// onTap: () {
// context.go('/listAllPlan');
// },
// child: Text(
// "All Trips",
// style: TextStyle(
// fontSize: 12,
// fontWeight: FontWeight.w600,
// // color: Color(0xFF475569),
// color: _myTravelRequestColor,
// fontFamily: "Inter",
// ),
// )),
// ),
// const SizedBox(width: 20),
// if (userDetails["role"] == "Travel Agent")
// MouseRegion(
// cursor: SystemMouseCursors.click,
// onEnter: (_) {
// setState(() {
// // _myTravelRequestPadding =
// // EdgeInsets.symmetric(horizontal: 12, vertical: 78);
// // _myTravelRequestColor =
// // Color(0xFF114D8B); // Change color on hover
// });
// },
// onExit: (_) {
// setState(() {
// // _myTravelRequestPadding = EdgeInsets.symmetric(
// // horizontal: 8, vertical: 4); // Normal padding
// // _myTravelRequestColor =
// // Color(0xFF475569); // Revert color when hover ends
// });
// },
// child: InkWell(
// onTap: () {
// context.go('/listTravelAgentPlan');
// },
// child: Text(
// "My Trips",
// style: TextStyle(
// fontSize: 12,
// fontWeight: FontWeight.w600,
// // color: Color(0xFF475569),
// color: _myTravelRequestColor,
// fontFamily: "Inter",
// ),
// )),
// ),
// if (userDetails["role"] != "Travel Agent")
// const SizedBox(width: 20),
// if (userDetails["role"] != "Travel Agent")
// MouseRegion(
// cursor: SystemMouseCursors.click,
// onEnter: (_) {
// setState(() {
// // _myTravelRequestPadding =
// // EdgeInsets.symmetric(horizontal: 12, vertical: 78);
// // _myTravelRequestColor =
// // Color(0xFF114D8B); // Change color on hover
// });
// },
// onExit: (_) {
// setState(() {
// // _myTravelRequestPadding = EdgeInsets.symmetric(
// // horizontal: 8, vertical: 4); // Normal padding
// // _myTravelRequestColor =
// // Color(0xFF475569); // Revert color when hover ends
// });
// },
// child: InkWell(
// onTap: () {
// context.go('/listPlan');
// },
// child: Text(
// "My Trips",
// style: TextStyle(
// fontSize: 12,
// fontWeight: FontWeight.w600,
// // color: Color(0xFF475569),
// color: _myTravelRequestColor,
// fontFamily: "Inter",
// ),
// )),
// ),
// const SizedBox(width: 20),
// if (userData?["role"] != "Travel Agent")
// MouseRegion(
// cursor: SystemMouseCursors.click,
// onEnter: (_) {
// setState(() {
// _myApprovalsColor =
// Color(0xFF114D8B); // Change color on hover
// });
// },
// onExit: (_) {
// setState(() {
// _myApprovalsColor = Color(
// 0xFF475569); // Revert color when hover ends
// });
// },
// child: InkWell(
// onTap: () {
// context.go('/ApprovalList');
// },
// child: Text(
// "My Approvals",
// style: TextStyle(
// fontSize: 12,
// fontWeight: FontWeight.w600,
// color: _myApprovalsColor,
// // color: Color(0xFF475569),
// fontFamily: "Inter",
// ),
// )),
// ),
// if (userData?["role"] == "Travel Agent")
// MouseRegion(
// cursor: SystemMouseCursors.click,
// onEnter: (_) {
// setState(() {
// _myApprovalsColor =
// Color(0xFF114D8B); // Change color on hover
// });
// },
// onExit: (_) {
// setState(() {
// _myApprovalsColor = Color(
// 0xFF475569); // Revert color when hover ends
// });
// },
// child: InkWell(
// onTap: () {
// context.go('/listTravelAgentPlan');
// },
// child: Text(
// "My Approvals",
// style: TextStyle(
// fontSize: 12,
// fontWeight: FontWeight.w600,
// color: _myApprovalsColor,
// // color: Color(0xFF475569),
// fontFamily: "Inter",
// ),
// )),
// ),
// ],
// ),
// ),
Container( Container(
width: MediaQuery.of(context).size.width * 0.35, width: MediaQuery.of(context).size.width * 0.35,
child: Row( child: Row(
@ -412,9 +262,14 @@ class _CustomAppBarState extends State<CustomAppBar> {
children: [ children: [
if (userData?["role"] == "Org Admin" || if (userData?["role"] == "Org Admin" ||
userData?["role"] == "Travel Admin") userData?["role"] == "Travel Admin")
buildNavItem("All Trips", _myTravelRequestColor, buildNavItem(
() => context.go('/listAllPlan'), "All Trips",
isSelected: selectedTab == "All Trips"), () => handleTabChange(
TabSelection.allTrips, '/listAllPlan'),
layoutColor!,
isSelected: selectedTab == TabSelection.allTrips,
icon: Icons.insights_outlined,
),
if (userDetails["role"] != "Travel Agent") if (userDetails["role"] != "Travel Agent")
const SizedBox(width: 20), const SizedBox(width: 20),
@ -422,17 +277,23 @@ class _CustomAppBarState extends State<CustomAppBar> {
if (userData?["role"] == "Travel Agent") if (userData?["role"] == "Travel Agent")
buildNavItem( buildNavItem(
"My Trips", "My Trips",
_myTravelRequestColor, () => handleTabChange(
() => context.go('/listTravelAgentPlan'), TabSelection.myTrips, '/listTravelAgentPlan'),
isSelected: selectedTab == "My Trips", layoutColor!,
// () => context.go('/listTravelAgentPlan'),
isSelected: selectedTab == TabSelection.myTrips,
icon: Icons.request_page_outlined,
), ),
if (userData?["role"] != "Travel Agent") // for others if (userData?["role"] != "Travel Agent") // for others
buildNavItem( buildNavItem(
"My Trips", "My Trips",
_myTravelRequestColor, () => handleTabChange(
() => context.go('/listPlan'), TabSelection.myTrips, '/listPlan'),
isSelected: selectedTab == "My Trips", layoutColor!,
// () => context.go('/listPlan'),
isSelected: selectedTab == TabSelection.myTrips,
icon: Icons.request_page_outlined,
), ),
// if (userDetails["role"] == "Travel Agent") // if (userDetails["role"] == "Travel Agent")
// buildNavItem("My Trips", _myTravelRequestColor, // buildNavItem("My Trips", _myTravelRequestColor,
@ -448,11 +309,23 @@ class _CustomAppBarState extends State<CustomAppBar> {
const SizedBox(width: 20), const SizedBox(width: 20),
if (userData?["role"] != "Travel Agent") if (userData?["role"] != "Travel Agent")
buildNavItem("My Approvals", _myApprovalsColor, () { buildNavItem(
isSelected: "My Approvals",
selectedTab == "My Approvals";
context.go('/ApprovalList'); () => handleTabChange(
}) TabSelection.myApprovals, '/ApprovalList'),
layoutColor!,
// () => context.go('/ApprovalList'),
isSelected: selectedTab == TabSelection.myApprovals,
icon: Icons.assessment_outlined,
),
// buildNavItem("My Approvals", _myApprovalsColor, () {
// isSelected:
// selectedTab == "My Approvals",
// context.go('/ApprovalList'),
// icon:Icons.insights_outlined;
// })
// if (userData?["role"] == "Travel Agent") { // if (userData?["role"] == "Travel Agent") {
// isSelected: // isSelected:
@ -466,7 +339,6 @@ class _CustomAppBarState extends State<CustomAppBar> {
], ],
), ),
), ),
Spacer(), Spacer(),
], ],
), ),
@ -664,11 +536,64 @@ PopupMenuItem<String> buildMenuItem(Map<String, dynamic> item) {
); );
} }
Widget buildNavItem(String label, Color color, VoidCallback onTap, Widget buildNavItem(String label, VoidCallback onTap, Color? layoutColor,
{bool isSelected = false}) { {bool isSelected = true, IconData? icon}) {
final effectiveColor =
isSelected ? (layoutColor ?? Colors.blue) : Colors.black;
return MouseRegion( return MouseRegion(
cursor: SystemMouseCursors.click, cursor: SystemMouseCursors.click,
child: InkWell( child: GestureDetector(
onTap: onTap,
child: Stack(
clipBehavior: Clip.none,
children: [
Row(
children: [
if (icon != null) Icon(icon, size: 16, color: effectiveColor),
if (icon != null) const SizedBox(width: 4),
Text(
label,
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
color: effectiveColor,
),
),
],
),
if (isSelected)
AnimatedPositioned(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
bottom: -20,
left: 0,
right: 0,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 300),
opacity: 1.0,
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
height: 2,
width: isSelected
? 50
: 0, // Animate width (make sure isSelected changes)
color: effectiveColor,
),
),
),
],
),
),
);
}
Widget buildNavItem1(String label, VoidCallback onTap,
{bool isSelected = true, IconData? icon}) {
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: onTap, onTap: onTap,
child: Container( child: Container(
padding: EdgeInsets.only(bottom: 2), padding: EdgeInsets.only(bottom: 2),
@ -676,22 +601,43 @@ Widget buildNavItem(String label, Color color, VoidCallback onTap,
? BoxDecoration( ? BoxDecoration(
border: Border( border: Border(
bottom: BorderSide( bottom: BorderSide(
color: color, // underline color
width: 2, // underline thickness width: 2, // underline thickness
), color: Colors.red),
), ),
) )
: null, // no underline when not selected : null, // no underline when not selected
child: Text( child: Row(
children: [
if (icon != null)
Icon(
icon,
size: 16,
color: isSelected ? Colors.red : Colors.black,
// color: Colors.red,
),
if (icon != null) SizedBox(width: 4),
Text(
label, label,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontWeight: FontWeight.w500, color: Colors.black), fontSize: 12,
// style: TextStyle( fontWeight: FontWeight.w500,
// fontSize: 12, color: isSelected ? Colors.red : Colors.black,
// fontWeight: FontWeight.w600, // color: Colors.red,
// color: color, ),
// fontFamily: "Inter", ),
// ),
// Red underline positioned below (e.g. under green line)
if (isSelected)
Positioned(
bottom: -50, // adjust this to push it below green line
left: 0,
right: 0,
child: Container(
height: 2,
color: Colors.red,
),
),
],
), ),
), ),
), ),

View File

@ -173,11 +173,11 @@ class _CustomDrawerState extends State<CustomDrawer> {
if (userData?["role"] == "Org Admin" || if (userData?["role"] == "Org Admin" ||
userData?["role"] == "Travel Admin") userData?["role"] == "Travel Admin")
_buildDrawerItem(context, Icons.request_page_outlined, _buildDrawerItem(context, Icons.insights_outlined, 'All Trips',
'All Trips', '/listAllPlan'), '/listAllPlan'),
if (userDetails["role"] == "Travel Agent") if (userDetails["role"] == "Travel Agent")
_buildDrawerItem(context, Icons.request_page_outlined, _buildDrawerItem(context, Icons.assessment_outlined,
'My Approvals', '/listTravelAgentPlan'), 'My Approvals', '/listTravelAgentPlan'),
if (userDetails["role"] != "Travel Agent") if (userDetails["role"] != "Travel Agent")

View File

@ -47,6 +47,10 @@ final GoRouter router = GoRouter(
path: '/createPlan', path: '/createPlan',
builder: (context, state) => CreatePlan(), builder: (context, state) => CreatePlan(),
), ),
GoRoute(
path: '/allTrips/trips',
builder: (context, state) => CreatePlan(),
),
GoRoute( GoRoute(
path: '/listUser', path: '/listUser',
builder: (context, state) => UserListScreen(), builder: (context, state) => UserListScreen(),

View File

@ -412,12 +412,12 @@ class ApiService {
} }
static Future<void> viewPlan(BuildContext context, String planId, static Future<void> viewPlan(BuildContext context, String planId,
{bool isViewMode = false}) async { {bool isViewMode = false, bool isMyTrips = false}) async {
try { try {
Map<String, dynamic> planData = await getViewPlan(planId); Map<String, dynamic> planData = await getViewPlan(planId);
print("ViewAAA - $planData"); print("ViewAAA - $planData");
context.go('/createPlan', context.go(isMyTrips ? '/createPlan' : '/allTrips/trips',
extra: {'planData': planData, 'isViewMode': isViewMode}); extra: {'planData': planData, 'isViewMode': isViewMode});
} catch (e) { } catch (e) {
print("Error fetching plan: $e"); print("Error fetching plan: $e");