user management - remarks list

This commit is contained in:
venbaittech 2025-05-15 19:11:21 +05:30
parent 75592f9879
commit db7df6b7de
17 changed files with 978 additions and 229 deletions

View File

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:core'; import 'dart:core';
import 'package:frontend/Screens/allTrips/remarks_list.dart';
import 'package:frontend/data/models/plan.dart'; import 'package:frontend/data/models/plan.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@ -782,12 +783,14 @@ class _ListAllPlansState extends State<ListAllPlans> {
onPressed: () { onPressed: () {
showDialog( showDialog(
context: context, context: context,
builder: (context) => CommentModal( builder: (context) =>
// planId: plan.planId, CommentModalList(
planId: plan.planId.toString(), // planId: plan.planId,
layoutColorForUser: planId:
layoutColor!, plan.planId.toString(),
role: "Admin"), layoutColorForUser:
layoutColor!,
role: "Admin"),
); );
}), }),
], ],
@ -869,7 +872,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
showDialog( showDialog(
context: context, context: context,
builder: (context) => builder: (context) =>
CommentModal( CommentModalList(
// planId: plan.planId, // planId: plan.planId,
planId: plan.planId planId: plan.planId
.toString(), .toString(),

View File

@ -0,0 +1,197 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import '../../config/apiUrl.dart';
import '../../utils/auth_utils.dart';
class CommentModalList extends StatefulWidget {
final String planId;
final Color layoutColorForUser;
final String role;
const CommentModalList({
Key? key,
required this.planId,
required this.layoutColorForUser,
required this.role,
}) : super(key: key);
@override
_CommentModalListState createState() => _CommentModalListState();
}
class _CommentModalListState extends State<CommentModalList> {
late Future<List<Map<String, dynamic>>> _commentsFuture;
Future<List<Map<String, dynamic>>> fetchComments1() async {
final response = await http.get(
Uri.parse(
'$apiUrl/api/plans/getRemarksByPlanId?plan_id=${widget.planId}'),
);
if (response.statusCode == 200) {
final jsonData = json.decode(response.body);
final List<dynamic> dataList = jsonData['data'];
return dataList.cast<Map<String, dynamic>>();
} else {
throw Exception('Failed to load comments');
}
}
Future<List<Map<String, dynamic>>> fetchComments() async {
// final String apiUrldata =
// '$apiUrl/getRemarksByPlanId?plan_id=${widget.planId}&user_id=$userId';
final String apiUrldata =
'$apiUrl/api/plans/getRemarksByPlanId?plan_id=${widget.planId}';
final token = await getToken();
if (token == null) {
throw Exception('Token not found. Please log in.');
}
final response = await http.get(
Uri.parse(apiUrldata),
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
);
if (response.statusCode == 200) {
final jsonData = json.decode(response.body);
final List<dynamic> dataList = jsonData['data'];
return dataList.cast<Map<String, dynamic>>();
} else {
throw Exception('Failed to load comments');
}
}
@override
void initState() {
super.initState();
_commentsFuture = fetchComments();
}
@override
Widget build(BuildContext context) {
return AlertDialog(
backgroundColor: Colors.white,
title: Text(
'Comments',
style: GoogleFonts.poppins(color: Colors.black),
),
content: ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 500, // You can adjust this width
maxHeight:
400, // Optional: limit height to make it scrollable vertically
),
child: FutureBuilder<List<Map<String, dynamic>>>(
future: _commentsFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Text(
'No Comments For This Plan',
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
);
}
if (!snapshot.hasData || snapshot.data!.isEmpty) {
return Text(
'No comments found.',
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
);
}
final comments = snapshot.data!;
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: [
DataColumn(
label: Text(
'Name',
style:
GoogleFonts.poppins(fontSize: 11, color: Colors.black),
)),
DataColumn(
label: Text(
'Comment',
style:
GoogleFonts.poppins(fontSize: 11, color: Colors.black),
)),
DataColumn(
label: Text(
'Updated On',
style:
GoogleFonts.poppins(fontSize: 11, color: Colors.black),
)),
],
rows: comments.map((comment) {
final name = comment['created_by_name'] ?? 'Unknown';
final remark = comment['remarks'] ?? '';
final rawDateStr = comment['updated_on'];
String updatedOn = '';
if (rawDateStr != null && rawDateStr.isNotEmpty) {
try {
final parsedDate = DateTime.parse(rawDateStr);
updatedOn = DateFormat('d MMM yyyy')
.format(parsedDate); // e.g., 15 May 2025
} catch (e) {
updatedOn = rawDateStr.split(' ').first; // fallback
}
}
return DataRow(cells: [
DataCell(Text(
name,
style: GoogleFonts.poppins(
fontSize: 12,
color: Colors.black,
fontWeight: FontWeight.w500),
)),
DataCell(Text(
remark,
style: GoogleFonts.poppins(
fontSize: 12,
color: Colors.black,
fontWeight: FontWeight.w500),
)),
DataCell(Text(
updatedOn,
style: GoogleFonts.poppins(
fontSize: 12,
color: Colors.black,
fontWeight: FontWeight.w500),
)),
]);
}).toList(),
),
);
},
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('Close',
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
color: widget.layoutColorForUser)),
),
],
);
}
}

View File

@ -18,6 +18,7 @@ import '../../utils/pagination.dart';
import '../../utils/travelAgent_remarks.dart'; import '../../utils/travelAgent_remarks.dart';
import '../../widgets/custom_popup.dart'; import '../../widgets/custom_popup.dart';
import '../../widgets/popup_listPlan_action.dart'; import '../../widgets/popup_listPlan_action.dart';
import '../allTrips/remarks_list.dart';
class ApprovalList extends StatefulWidget { class ApprovalList extends StatefulWidget {
const ApprovalList({super.key}); const ApprovalList({super.key});
@ -756,12 +757,14 @@ class _ApprovalListState extends State<ApprovalList> {
onPressed: () { onPressed: () {
showDialog( showDialog(
context: context, context: context,
builder: (context) => CommentModal( builder: (context) =>
// planId: plan.planId, CommentModalList(
planId: plan.planId.toString(), // planId: plan.planId,
layoutColorForUser: planId:
layoutColor!, plan.planId.toString(),
role: "Approver"), layoutColorForUser:
layoutColor!,
role: "Approver"),
); );
}), }),
], ],
@ -946,12 +949,14 @@ class _ApprovalListState extends State<ApprovalList> {
onPressed: () { onPressed: () {
showDialog( showDialog(
context: context, context: context,
builder: (context) => CommentModal( builder: (context) =>
// planId: plan.planId, CommentModalList(
planId: plan.planId.toString(), // planId: plan.planId,
layoutColorForUser: planId:
layoutColor!, plan.planId.toString(),
role: "Approver"), layoutColorForUser:
layoutColor!,
role: "Approver"),
); );
}), }),
], ],

View File

@ -13,13 +13,15 @@ class AccomodationScreen extends StatefulWidget {
final Function(Map<String, dynamic>) onSaveAccomadation; final Function(Map<String, dynamic>) onSaveAccomadation;
final Map<String, dynamic>? selectedItem; final Map<String, dynamic>? selectedItem;
final String? loginUser; final String? loginUser;
final String? tripType;
AccomodationScreen( AccomodationScreen(
{required this.onClose, {required this.onClose,
required this.onSaveAccomadation, required this.onSaveAccomadation,
required this.selectedItem, required this.selectedItem,
required this.loginUser, required this.loginUser,
required this.flightData}); required this.flightData,
this.tripType});
@override @override
_AccomodationScreenState createState() => _AccomodationScreenState(); _AccomodationScreenState createState() => _AccomodationScreenState();
@ -293,7 +295,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
} }
Future<void> loadCountryList() async { Future<void> loadCountryList() async {
final result = await apiService.fetchFlightsCountryList(); final result = await apiService.fetchFlightsCountryList(widget.tripType);
print("ResultCountry : $result"); print("ResultCountry : $result");

View File

@ -84,6 +84,8 @@ class _FlightScreenState extends State<FlightScreen> {
void initState() { void initState() {
super.initState(); super.initState();
print("TripType - ${widget.tripType}");
// _initializeRows(); // _initializeRows();
// List<dynamic> purposeList = widget.apiData?['flight_trip_type'] ?? []; // List<dynamic> purposeList = widget.apiData?['flight_trip_type'] ?? [];
// selectedTripType ??= purposeList.isNotEmpty ? purposeList.first['dropdown_value'] : null; // selectedTripType ??= purposeList.isNotEmpty ? purposeList.first['dropdown_value'] : null;
@ -206,7 +208,7 @@ class _FlightScreenState extends State<FlightScreen> {
isCountryLoading = true; isCountryLoading = true;
}); });
final result = await apiService.fetchFlightsCountryList(); final result = await apiService.fetchFlightsCountryList(widget.tripType);
print("ResultCountry : $result"); print("ResultCountry : $result");

View File

@ -15,6 +15,7 @@ class TrainScreen extends StatefulWidget {
final Function(bool) onClose; final Function(bool) onClose;
final Map<String, dynamic>? selectedItem; final Map<String, dynamic>? selectedItem;
final String? loginUser; final String? loginUser;
final String? tripType;
TrainScreen( TrainScreen(
{required this.onClose, {required this.onClose,
@ -22,7 +23,8 @@ class TrainScreen extends StatefulWidget {
required this.onSavetrain, required this.onSavetrain,
required this.selectedItem, required this.selectedItem,
required this.loginUser, required this.loginUser,
this.apiDataForClass}); this.apiDataForClass,
this.tripType});
@override @override
_TrainScreenState createState() => _TrainScreenState(); _TrainScreenState createState() => _TrainScreenState();

View File

@ -43,7 +43,7 @@ class _FlightListWidgetState extends State<FlightListWidget> {
} }
Future<void> loadCountryList() async { Future<void> loadCountryList() async {
final result = await apiService.fetchFlightsCountryList(); final result = await apiService.fetchFlightsCountryList(widget.tripType);
print("ResultCountry : $result"); print("ResultCountry : $result");

View File

@ -616,6 +616,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
apiDataForClass: widget.apiDataForClass, apiDataForClass: widget.apiDataForClass,
loginUser: widget.loginUser, loginUser: widget.loginUser,
onSavetrain: (data) => handleItineraryUpdate("Train", data), onSavetrain: (data) => handleItineraryUpdate("Train", data),
tripType: widget.tripType,
selectedItem: selectedItem); selectedItem: selectedItem);
break; break;
case "Taxi": case "Taxi":

View File

@ -18,6 +18,7 @@ import '../../utils/pagination.dart';
import '../../utils/travelAgent_remarks.dart'; import '../../utils/travelAgent_remarks.dart';
import '../../widgets/custom_popup.dart'; import '../../widgets/custom_popup.dart';
import '../../widgets/popup_listPlan_action.dart'; import '../../widgets/popup_listPlan_action.dart';
import '../allTrips/remarks_list.dart';
class ListPlans extends StatefulWidget { class ListPlans extends StatefulWidget {
const ListPlans({super.key}); const ListPlans({super.key});
@ -822,12 +823,14 @@ class _ListPlansState extends State<ListPlans> {
onPressed: () { onPressed: () {
showDialog( showDialog(
context: context, context: context,
builder: (context) => CommentModal( builder: (context) =>
// planId: plan.planId, CommentModalList(
planId: plan.planId.toString(), // planId: plan.planId,
layoutColorForUser: planId:
layoutColor!, plan.planId.toString(),
role: "User"), layoutColorForUser:
layoutColor!,
role: "User"),
); );
}), }),
], ],
@ -942,12 +945,14 @@ class _ListPlansState extends State<ListPlans> {
onPressed: () { onPressed: () {
showDialog( showDialog(
context: context, context: context,
builder: (context) => CommentModal( builder: (context) =>
// planId: plan.planId, CommentModalList(
planId: plan.planId.toString(), // planId: plan.planId,
layoutColorForUser: planId:
layoutColor!, plan.planId.toString(),
role: "User"), layoutColorForUser:
layoutColor!,
role: "User"),
); );
}), }),
], ],

View File

@ -31,6 +31,8 @@ import '../../../widgets/custom_text_forex.dart';
import '../../../widgets/custom_user_form.dart'; import '../../../widgets/custom_user_form.dart';
import 'office_details.dart'; import 'office_details.dart';
import 'package:universal_html/html.dart' as html;
class CreateUserFormDetials extends StatefulWidget { class CreateUserFormDetials extends StatefulWidget {
@override @override
_CreateUserFormDetialsState createState() => _CreateUserFormDetialsState(); _CreateUserFormDetialsState createState() => _CreateUserFormDetialsState();
@ -44,7 +46,9 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
final GlobalKey<TravellerDetailsState> travellerDetailsKey = final GlobalKey<TravellerDetailsState> travellerDetailsKey =
GlobalKey<TravellerDetailsState>(); GlobalKey<TravellerDetailsState>();
// late List<Map<String, dynamic>?> travelDetailsData;
Map<String, dynamic>? travelDetailsData; Map<String, dynamic>? travelDetailsData;
Map<String, dynamic>? travelDetailsDataFromAPI;
late TabController _tabController; late TabController _tabController;
@ -172,6 +176,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
} }
void handleUserTypeChange(bool isTravelAgent) { void handleUserTypeChange(bool isTravelAgent) {
print("handleUserTypeChange- $isTravelAgent");
setState(() { setState(() {
setSelectesUserType = isTravelAgent; setSelectesUserType = isTravelAgent;
}); });
@ -186,6 +192,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
if (apiselectedUser != null && apiselectedUser!.isNotEmpty) { if (apiselectedUser != null && apiselectedUser!.isNotEmpty) {
isapiselectedUser = true; isapiselectedUser = true;
print("API Selected User Has Data - $apiselectedUser");
} }
controllers["Fname"]?.text = apiselectedUser?["first_name"] ?? ""; controllers["Fname"]?.text = apiselectedUser?["first_name"] ?? "";
@ -265,18 +273,17 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
print("Updated selectedGender: $selectedGender"); // Debugging print("Updated selectedGender: $selectedGender"); // Debugging
// Load passport document from API travelDetailsDataFromAPI = apiselectedUser?["travel_details"];
String? apiDocPath = apiselectedUser?["passport_document"];
if (apiDocPath != null && apiDocPath.isNotEmpty) { print("travelDetailsDataFromAPI00 - $travelDetailsDataFromAPI");
passportFileUrlFromApi = apiDocPath; // if (travelDetails != null) {
selectedFileNames = // WidgetsBinding.instance.addPostFrameCallback((_) {
apiDocPath.split('/').last; // Extract filename from path // // Safe to call updateTravel now
passportFile = null; // No local file selected yet // travellerDetailsKey.currentState?.updateTravel();
} else { // });
passportFileUrlFromApi = null; // }
selectedFileNames = null;
passportFile = null; // Optionally load other travel-related fields like meal/seat preferences, etc.
}
}); });
} else { } else {
print("API Selected User Has Data - No data available yet"); print("API Selected User Has Data - No data available yet");
@ -288,15 +295,13 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
super.initState(); super.initState();
selectedTab = "personal"; selectedTab = "personal";
WidgetsFlutterBinding.ensureInitialized(); // WidgetsFlutterBinding.ensureInitialized();
// Step 1: Set 'reloaded' flag before page unload // Step 1: Set 'reloaded' flag before page unload
html.window.onBeforeUnload.listen((event) { // html.window.onBeforeUnload.listen((event) {
html.window.localStorage['reloaded'] = 'true'; // html.window.localStorage['reloaded'] = 'true';
}); // });
// apiCountryData = extraData['apiCountryData']; // Extract apiCountryData
// futureUsers = extraData['apiUserData']; // Extract futureUsers (Future<List<dynamic>>)
apiCountryData = null; apiCountryData = null;
apiUserData = null; apiUserData = null;
// apiselectedUser = null; // apiselectedUser = null;
@ -306,12 +311,12 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
// Initialize controllers for each field // Initialize controllers for each field
WidgetsBinding.instance.addPostFrameCallback((_) async { WidgetsBinding.instance.addPostFrameCallback((_) async {
final wasReloaded = html.window.localStorage['reloaded'] == 'true'; // final wasReloaded = html.window.localStorage['reloaded'] == 'true';
//
if (wasReloaded) { // if (wasReloaded) {
html.window.localStorage.remove('reloaded'); // Clear it // html.window.localStorage.remove('reloaded'); // Clear it
context.go('/listUser'); // Navigate using go_router // context.go('/listUser'); // Navigate using go_router
} // }
final extraData = final extraData =
GoRouterState.of(context).extra as Map<String, dynamic>?; GoRouterState.of(context).extra as Map<String, dynamic>?;
@ -484,9 +489,11 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
} }
void handleNext() async { void handleNext() async {
print("USR Detail Submit"); print("USR Detail Next");
printFormData(); printFormData();
// travelDetailsData = [travellerDetailsKey.currentState?.travel_Detials];
travelDetailsData = travellerDetailsKey.currentState?.travel_Detials; travelDetailsData = travellerDetailsKey.currentState?.travel_Detials;
print("TRAVEL DETAILS FROM CHILD: $travelDetailsData"); print("TRAVEL DETAILS FROM CHILD: $travelDetailsData");
@ -528,11 +535,15 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
void handleSubmit() async { void handleSubmit() async {
print("USR Detail Submit"); print("USR Detail Submit");
printFormData(); // printFormData();
travelDetailsData = travellerDetailsKey.currentState?.travel_Detials; travelDetailsData = travellerDetailsKey.currentState?.travel_Detials;
print("TRAVEL DETAILS FROM CHILD: $travelDetailsData"); print("TRAVEL DETAILS FROM CHILD");
// print("TRAVEL DETAILS FROM CHILD: $travelDetailsData");
passportFile = travellerDetailsKey.currentState?.passportFile;
print("passportFile : $passportFile");
Map<String, dynamic> data = userDetials; Map<String, dynamic> data = userDetials;
@ -665,9 +676,21 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
} }
// Add all non-null and non-empty user data fields // Add all non-null and non-empty user data fields
// userData.forEach((key, value) {
// if (value != null && value.toString().trim().isNotEmpty) {
// request.fields[key] = value.toString();
// }
// });
userData.forEach((key, value) { userData.forEach((key, value) {
if (value != null && value.toString().trim().isNotEmpty) { if (value != null && value.toString().trim().isNotEmpty) {
request.fields[key] = value.toString(); if (key == 'travel_details' && value is Map<String, dynamic>) {
// Encode travel_details as a proper JSON string
request.fields[key] = jsonEncode(value);
print("✅ Encoded travel_details: ${request.fields[key]}");
} else {
request.fields[key] = value.toString();
}
} }
}); });
@ -801,6 +824,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
? Row( ? Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: (selectedTab == "travel" || children: (selectedTab == "travel" ||
selectedRole == "5" ||
isEditProfile ||
setSelectesUserType == true) setSelectesUserType == true)
? _buildSubmit(isDesktop, layoutColor!) ? _buildSubmit(isDesktop, layoutColor!)
: _buildNext(isDesktop, layoutColor!), : _buildNext(isDesktop, layoutColor!),
@ -808,6 +833,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
: Row( : Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: (selectedTab == "travel" || children: (selectedTab == "travel" ||
selectedRole == "5" ||
setSelectesUserType == true) setSelectesUserType == true)
? _buildSubmit(isDesktop, layoutColor!) ? _buildSubmit(isDesktop, layoutColor!)
: _buildNext(isDesktop, layoutColor!), : _buildNext(isDesktop, layoutColor!),
@ -827,16 +853,32 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Row(
apiselectedUser != null ? "Profile" : "Create New User", children: [
style: GoogleFonts.poppins( Text(
fontSize: isDesktop ? 15 : 12, apiselectedUser != null ? "Profile" : "Create New User",
fontWeight: FontWeight.w600, style: GoogleFonts.poppins(
color: Colors.black, fontSize: isDesktop ? 15 : 12,
), fontWeight: FontWeight.w600,
color: Colors.black,
),
),
if (isEditProfile)
IconButton(
icon: Icon(
Icons.edit,
color: Color(0xFF114D8B),
size: 14,
),
onPressed: () {
setState(() {
isViewMode = !isViewMode;
});
})
],
), ),
SizedBox( SizedBox(
height: 20, height: 18,
), ),
isDesktop isDesktop
? buildTabsForUser() ? buildTabsForUser()
@ -935,6 +977,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
isViewMode: isViewMode, isViewMode: isViewMode,
controllers: controllers, controllers: controllers,
errorMessages: errorMessages, errorMessages: errorMessages,
travelDetails: travelDetailsDataFromAPI, // 👈 Pass this down
passportFileUrlFromApi: passportFileUrlFromApi,
); );
default: default:
return PersonalDetails( return PersonalDetails(
@ -952,12 +996,30 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
} }
Widget buildTabsForUser() { Widget buildTabsForUser() {
final tabs = { // final tabs = {
// "personal": "Personal Details",
// "office": "Office Details",
// "travel": "Travel Details",
// };
final Map<String, String> allTabs = {
"personal": "Personal Details", "personal": "Personal Details",
"office": "Office Details", "office": "Office Details",
"travel": "Travel Details", "travel": "Travel Details",
}; };
Map<String, String> getTabs(bool setSelectesUserType) {
if (setSelectesUserType || selectedRole == "5") {
return {
"personal": "Personal Details",
};
} else {
return allTabs;
}
}
final tabs = getTabs(setSelectesUserType);
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.end, // important crossAxisAlignment: CrossAxisAlignment.end, // important
children: tabs.entries.map((entry) { children: tabs.entries.map((entry) {
@ -1042,7 +1104,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
onPressed: () { onPressed: () {
isEditProfile ? context.go('/listPlan') : context.go('/listUser'); isEditProfile ? context.go('/listPlan') : context.go('/listUser');
}, },
child: isViewMode ? Text("Back") : Text("Cancel")), child: Text("Cancel")),
SizedBox( SizedBox(
width: 20, width: 20,
), ),

View File

@ -150,6 +150,8 @@ class PersonalDetailsState extends State<PersonalDetails> {
if (response is Map<String, dynamic> && response.containsKey("role")) { if (response is Map<String, dynamic> && response.containsKey("role")) {
List<dynamic> roleList = response["role"]; // Extract the list List<dynamic> roleList = response["role"]; // Extract the list
if (!mounted) return;
setState(() { setState(() {
apiRoleData = roleList; apiRoleData = roleList;
}); });
@ -1109,7 +1111,8 @@ class PersonalDetailsState extends State<PersonalDetails> {
child: SizedBox( child: SizedBox(
height: 45, // Set appropriate height height: 45, // Set appropriate height
child: DropdownButtonFormField<String>( child: DropdownButtonFormField<String>(
value: widget.isViewMode ? null : selectedRole, // value: widget.isViewMode ? null : selectedRole,
value: selectedRole,
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
decoration: InputDecoration( decoration: InputDecoration(
border: InputBorder.none, border: InputBorder.none,
@ -1121,7 +1124,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
: (newValue) { : (newValue) {
setState(() { setState(() {
selectedRole = newValue; selectedRole = newValue;
isTravelAgent = selectedRole == "Travel Agent"; isTravelAgent = selectedRole == "5";
// Pass the result back to parent // Pass the result back to parent
widget.onUserTypeChanged?.call(isTravelAgent); widget.onUserTypeChanged?.call(isTravelAgent);
}); });

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:shared_preferences/shared_preferences.dart'; // don't forget import 'package:shared_preferences/shared_preferences.dart'; // don't forget
import '../services/apiService.dart'; import '../services/apiService.dart';
import '../utils/auth_utils.dart';
enum TabSelection { allTrips, myTrips, myApprovals } enum TabSelection { allTrips, myTrips, myApprovals }
@ -481,7 +482,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
extra: { extra: {
"selectedUser": userDetails, "selectedUser": userDetails,
"isEditProfile": true, "isEditProfile": true,
"isViewMode": true "isEditProfile": true,
"isViewMode": false,
}, },
); );
case '/logout': case '/logout':

View File

@ -489,9 +489,11 @@ class ApiService {
// Flight From - To // Flight From - To
Future<List<dynamic>> fetchFlightsCountryList() async { Future<List<dynamic>> fetchFlightsCountryList(String? tripType) async {
print("FlightTripType- $tripType");
final String apiUrldata = final String apiUrldata =
'$apiUrl/api/getAirportCodeMaster?limit=1000&offset=0'; '$apiUrl/api/getAirportCodeMaster?trip_type=$tripType';
final token = await getToken(); final token = await getToken();

View File

@ -51,6 +51,8 @@ Future<String?> getRoleUser() async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
final String? userDataString = prefs.getString('user_data'); final String? userDataString = prefs.getString('user_data');
// print("UserDataSTr - $userDataString");
if (userDataString != null) { if (userDataString != null) {
try { try {
final Map<String, dynamic> userData = jsonDecode(userDataString); final Map<String, dynamic> userData = jsonDecode(userDataString);

View File

@ -26,23 +26,35 @@ class CommentModalState extends State<CommentModal> {
Map<String, dynamic>? remarksData; Map<String, dynamic>? remarksData;
int? remarksId; int? remarksId;
dynamic userId; dynamic userId;
late final role;
bool isLoading = true; bool isLoading = true;
String? errorMessage; String? errorMessage;
bool editRemarks = false; bool editRemarks = false;
TextEditingController commentController = TextEditingController(); TextEditingController commentController = TextEditingController();
Map<String, dynamic> getData() { // Map<String, dynamic> getData() {
// final map = {
// "plan_id": int.parse(widget.planId),
// "remarks": commentController.text,
// "created_by": userId,
// "is_active": 1,
// };
//
// if (remarksId != null) {
// map["id"] = remarksId; // Add 'id' only if available
// }
//
// return map;
// }
Map<String, dynamic> getData({int isActive = 1}) {
final map = { final map = {
"plan_id": int.parse(widget.planId), "plan_id": int.parse(widget.planId),
"remarks": commentController.text, "remarks": commentController.text,
"created_by": userId, // "created_by": userId,
"is_active": 1, "is_active": isActive,
}; };
if (remarksId != null) {
map["id"] = remarksId; // Add 'id' only if available
}
return map; return map;
} }
@ -59,6 +71,10 @@ class CommentModalState extends State<CommentModal> {
throw Exception('User ID not found.'); throw Exception('User ID not found.');
} }
role = await getRoleUser();
print("Role - $role");
userId = int.tryParse(userIdString); userId = int.tryParse(userIdString);
if (userId == null) { if (userId == null) {
throw Exception('Invalid user ID format.'); throw Exception('Invalid user ID format.');
@ -85,8 +101,15 @@ class CommentModalState extends State<CommentModal> {
// final String apiUrldata = // final String apiUrldata =
// '$apiUrl/getRemarksByPlanId?plan_id=${widget.planId}&user_id=$userId'; // '$apiUrl/getRemarksByPlanId?plan_id=${widget.planId}&user_id=$userId';
final String apiUrldata = final String apiUrldata;
'$apiUrl/api/plans/getRemarksByPlanId?plan_id=${widget.planId}&user_id=$userId';
if (role == "Travel Agent") {
apiUrldata =
'$apiUrl/api/plans/getRemarksByPlanId?plan_id=${widget.planId}&user_id=$userId';
} else {
apiUrldata =
'$apiUrl/api/plans/getRemarksByPlanId?plan_id=${widget.planId}';
}
final token = await getToken(); final token = await getToken();
@ -128,8 +151,19 @@ class CommentModalState extends State<CommentModal> {
} }
} }
Future<void> postRemarksData() async { Future<void> postRemarksData({int isActive = 1}) async {
final remarksData = getData(); // final remarksData = getData();
final remarksData = getData(isActive: isActive);
print("remarksId - $remarksId");
if (remarksId != null) {
remarksData["id"] = remarksId;
remarksData["updated_by"] = userId;
} else {
remarksData["created_by"] = userId;
}
print("Remarks Data - remarksData"); print("Remarks Data - remarksData");
@ -172,12 +206,16 @@ class CommentModalState extends State<CommentModal> {
if (data['data'] != null && data['data'].isNotEmpty) { if (data['data'] != null && data['data'].isNotEmpty) {
final remarksData = data['data'][0]; // Take the first item from the list final remarksData = data['data'][0]; // Take the first item from the list
print("remarksData - $remarksData");
// Now update your local fields // Now update your local fields
commentController.text = remarksData['remarks'] ?? ''; commentController.text = remarksData['remarks'] ?? '';
// If you need to update other fields like created_by, you can do that too // If you need to update other fields like created_by, you can do that too
userId = remarksData['created_by'] ?? userId; userId = remarksData['created_by'] ?? userId;
remarksId = remarksData['id']; // remarksId = remarksData['id'];
remarksId = int.tryParse(remarksData['id'].toString());
print("remarksId1- $remarksId");
// If plan_id needs to be updated (usually it doesn't change), you can do it too // If plan_id needs to be updated (usually it doesn't change), you can do it too
// widget.planId = remarksData['plan_id'].toString(); // If widget.planId is mutable // widget.planId = remarksData['plan_id'].toString(); // If widget.planId is mutable
@ -211,12 +249,15 @@ class CommentModalState extends State<CommentModal> {
}); });
}, },
), ),
IconButton( if (widget.role == "Travel Agent")
icon: const Icon(Icons.delete, size: 20), IconButton(
onPressed: () { icon: const Icon(Icons.delete, size: 20),
// Handle delete pressed onPressed: () async {
}, await postRemarksData(
), isActive: 0); // Marks the remark as deleted
Navigator.of(context).pop();
},
),
], ],
), ),
const SizedBox(height: 10), const SizedBox(height: 10),

View File

@ -32,7 +32,7 @@ class _CustomTextFieldUserTravellerWrapperState
return Container( return Container(
width: widget.width ?? // Use custom width if provided, else default width: widget.width ?? // Use custom width if provided, else default
(widget.isDesktop (widget.isDesktop
? MediaQuery.of(context).size.width * 0.24 ? MediaQuery.of(context).size.width * 0.22
: MediaQuery.of(context).size.width * 0.8), : MediaQuery.of(context).size.width * 0.8),
padding: widget.padding, padding: widget.padding,
decoration: BoxDecoration( decoration: BoxDecoration(