forex calculations

This commit is contained in:
venbaittech 2025-05-26 10:59:01 +05:30
parent c99ac679a6
commit 42f3f465d5
10 changed files with 583 additions and 281 deletions

View File

@ -369,7 +369,7 @@ class _LoginWidgetState extends State<LoginWidget> {
), ),
const SizedBox(height: 2), const SizedBox(height: 2),
Text( Text(
"Welcome To Trip Approval Tools", "Welcome To TripApprovalTool",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 11, fontSize: 11,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
@ -822,55 +822,48 @@ class _LoginWidgetState extends State<LoginWidget> {
); );
} }
Future<void> handleMS() async { Future<void> handleMS() async {
final url = '$apiUrl/auth/mslogin';
print(url);
try {
final response = await http
.get(Uri.parse(url), headers: {'Content-Type': 'application/json'});
print("inside try method");
if (response.statusCode == 200) {
final authUrl = json.decode(response.body)['auth_url'];
print("authurl - $authUrl");
if (authUrl != '') {
// final prefs = await SharedPreferences.getInstance();
// await prefs.setString('auth_token', authUrl);
print('i have auth URL');
// canLaunchUrl(authUrl);
final url = '$apiUrl/auth/mslogin'; if (kIsWeb) {
print(url); print("kIsWeb");
try { // Use web redirect (e.g., via JS interop or window.location.href)
final response = await http.get( // redirectTo(url);
Uri.parse(url),
headers: { 'Content-Type': 'application/json' }
);
print("inside try method");
if (response.statusCode == 200) {
final authUrl = json.decode(response.body)['auth_url'];
print("authurl - $authUrl");
if(authUrl != ''){
// final prefs = await SharedPreferences.getInstance();
// await prefs.setString('auth_token', authUrl);
print('i have auth URL');
// canLaunchUrl(authUrl);
if (kIsWeb) { html.window.location.href = authUrl;
print("kIsWeb"); } else {
// Use web redirect (e.g., via JS interop or window.location.href) // For mobile/desktop, open in external browser
// redirectTo(url); // launchUrl(Uri.parse(url),
// mode: LaunchMode.externalApplication);
html.window.location.href = authUrl;
} else {
// For mobile/desktop, open in external browser
// launchUrl(Uri.parse(url),
// mode: LaunchMode.externalApplication);
}
// final result = await FlutterWebAuth.authenticate(
// url: authUrl,
// callbackUrlScheme: "myapp", // Use a custom scheme you registered
// );
}else{
print('auth URL not Founded');
throw Exception('auth URL not Founded');
} }
}else{ // final result = await FlutterWebAuth.authenticate(
final errorMessage = json.decode(response.body)['message']; // url: authUrl,
print(errorMessage); // callbackUrlScheme: "myapp", // Use a custom scheme you registered
throw Exception(errorMessage); // );
} else {
print('auth URL not Founded');
throw Exception('auth URL not Founded');
} }
} else {
final errorMessage = json.decode(response.body)['message'];
print(errorMessage);
throw Exception(errorMessage);
} }
catch (e) { } catch (e) {
print("Error: $e"); print("Error: $e");
} }
} }
} }

View File

@ -25,7 +25,7 @@ class DepartmentList extends StatefulWidget {
class DepartmentListState extends State<DepartmentList> { class DepartmentListState extends State<DepartmentList> {
final GlobalKey<DepartmentListState> departmentListKey = final GlobalKey<DepartmentListState> departmentListKey =
GlobalKey<DepartmentListState>(); GlobalKey<DepartmentListState>();
final ApiService apiService = ApiService(); final ApiService apiService = ApiService();
late Future<List<dynamic>> futureDepartment; late Future<List<dynamic>> futureDepartment;
@ -97,7 +97,6 @@ class DepartmentListState extends State<DepartmentList> {
} }
Future<List<dynamic>> fetchGetDepartment() async { Future<List<dynamic>> fetchGetDepartment() async {
final String apiUrlData = '$apiUrl/api/getDepartmentList'; final String apiUrlData = '$apiUrl/api/getDepartmentList';
final String? token = await getToken(); final String? token = await getToken();
@ -142,19 +141,18 @@ class DepartmentListState extends State<DepartmentList> {
print("all before filtering: $query"); print("all before filtering: $query");
final lowerQuery = query.toLowerCase(); final lowerQuery = query.toLowerCase();
setState(() { setState(() {
filteredDepartment = allDepartment.where((object) { filteredDepartment = allDepartment.where((object) {
final isActiveStatus = final isActiveStatus =
object['is_active'] == "1" ? "active" : "inactive"; object['is_active'] == "1" ? "active" : "inactive";
return (object['department_id']?.toLowerCase().contains(lowerQuery) ?? return (object['department_id']?.toLowerCase().contains(lowerQuery) ??
false) || false) ||
(object['name']?.toLowerCase().contains(lowerQuery) ?? (object['name']?.toLowerCase().contains(lowerQuery) ?? false) ||
false) || (object['description']?.toLowerCase().contains(lowerQuery) ??
(object['description']?.toLowerCase().contains(lowerQuery) ?? false) || false) ||
(isActiveStatus.contains(lowerQuery)); (isActiveStatus.contains(lowerQuery));
}).toList(); }).toList();
}); });
print("filteredDepartment: $filteredDepartment"); print("filteredDepartment: $filteredDepartment");
} }
@override @override
@ -171,11 +169,11 @@ class DepartmentListState extends State<DepartmentList> {
body: Padding( body: Padding(
padding: isDesktop padding: isDesktop
? EdgeInsets.symmetric( ? EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width * horizontal: MediaQuery.of(context).size.width *
0.1, // 30% of screen width as horizontal padding 0.1, // 30% of screen width as horizontal padding
vertical: MediaQuery.of(context).size.height * vertical: MediaQuery.of(context).size.height *
0, // 5% of screen height as vertical padding 0, // 5% of screen height as vertical padding
) )
: EdgeInsets.all(0), : EdgeInsets.all(0),
child: Row( child: Row(
children: [ children: [
@ -297,7 +295,7 @@ class DepartmentListState extends State<DepartmentList> {
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
side: side:
BorderSide(color: Color(0xFF114D8B), width: 2), BorderSide(color: Color(0xFF114D8B), width: 2),
), ),
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 20, vertical: 12), horizontal: 20, vertical: 12),
@ -317,7 +315,7 @@ class DepartmentListState extends State<DepartmentList> {
}, },
child: Row( child: Row(
mainAxisSize: mainAxisSize:
MainAxisSize.min, // Ensures content fits nicely MainAxisSize.min, // Ensures content fits nicely
children: [ children: [
Text( Text(
"Add Department", "Add Department",
@ -344,46 +342,46 @@ class DepartmentListState extends State<DepartmentList> {
isDesktop isDesktop
? SizedBox.shrink() ? SizedBox.shrink()
: Row( : Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Container( Container(
width: MediaQuery.of(context).size.width * 0.8, width: MediaQuery.of(context).size.width * 0.8,
height: 35, height: 35,
child: TextField( child: TextField(
controller: searchController, controller: searchController,
onChanged: filterDepartment, onChanged: filterDepartment,
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search ...", hintText: "Search ...",
hintStyle: TextStyle( hintStyle: TextStyle(
fontSize: 12, color: Color(0xFF9E9DBD)), fontSize: 12, color: Color(0xFF9E9DBD)),
prefixIcon: Icon( prefixIcon: Icon(
Icons.search, Icons.search,
color: Color(0xFF9E9DBD), color: Color(0xFF9E9DBD),
size: 18, size: 18,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: Colors.grey.shade200,
width: 0.5),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: Colors.grey.shade300, width: 1),
),
),
style: GoogleFonts.poppins(
fontSize: 12,
),
),
), ),
border: OutlineInputBorder( // SizedBox(width: 16),
borderRadius: BorderRadius.circular(12), ],
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: Colors.grey.shade200,
width: 0.5),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: Colors.grey.shade300, width: 1),
),
),
style: GoogleFonts.poppins(
fontSize: 12,
),
), ),
),
// SizedBox(width: 16),
],
),
const SizedBox(height: 10), const SizedBox(height: 10),
FutureBuilder<List<dynamic>>( FutureBuilder<List<dynamic>>(
future: futureDepartment, future: futureDepartment,
@ -432,8 +430,9 @@ class DepartmentListState extends State<DepartmentList> {
); );
} }
/* Here collect the list to displayed the data in table or card Used */ /* Here collect the list to displayed the data in table or card Used */
List<dynamic> object = List<dynamic> object = filteredDepartment.isNotEmpty
filteredDepartment.isNotEmpty ? filteredDepartment : allDepartment; ? filteredDepartment
: allDepartment;
/* List is Sorting here */ /* List is Sorting here */
object.sort((a, b) { object.sort((a, b) {
@ -454,7 +453,7 @@ class DepartmentListState extends State<DepartmentList> {
Widget table = LayoutBuilder( Widget table = LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
double minWidth = double minWidth =
isDesktop ? constraints.maxWidth : 1300; isDesktop ? constraints.maxWidth : 1300;
return ConstrainedBox( return ConstrainedBox(
constraints: BoxConstraints(minWidth: minWidth), constraints: BoxConstraints(minWidth: minWidth),
@ -468,64 +467,67 @@ class DepartmentListState extends State<DepartmentList> {
columns: [ columns: [
DataColumn( DataColumn(
label: Text( label: Text(
'Department ID', 'Department ID',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),
)), )),
DataColumn( DataColumn(
label: Text( label: Text(
'Name', 'Name',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),
)), )),
DataColumn( DataColumn(
label: Text( label: Text(
'Description', 'Description',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),
)), )),
DataColumn( DataColumn(
label: Text( label: Text(
'Status', 'Status',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),
)), )),
DataColumn( DataColumn(
label: Text( label: Text(
'Actions', 'Actions',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),
)), )),
], ],
rows: paginatedDepartment.map((tableObject) { rows: paginatedDepartment.map((tableObject) {
String departmentId = tableObject['department_id'] String departmentId =
.toString(); // Get user ID tableObject['department_id']
bool isSelected = selectedDepartmentId == departmentId; .toString(); // Get user ID
bool isSelected =
selectedDepartmentId == departmentId;
return DataRow(cells: [ return DataRow(cells: [
DataCell( DataCell(Text(
Text("${tableObject['department_id'] ?? ''}", "${tableObject['department_id'] ?? ''}",
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
fontFamily: "Inter", fontFamily: "Inter",
))), ))),
DataCell(Text(tableObject['name'] ?? '', DataCell(Text(tableObject['name'] ?? '',
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
fontFamily: "Inter", fontFamily: "Inter",
))), ))),
DataCell(Text(tableObject['description'] ?? 'N/A', DataCell(
style: TextStyle( Text(tableObject['description'] ?? 'N/A',
fontSize: 13, style: TextStyle(
fontFamily: "Inter", fontSize: 13,
), fontFamily: "Inter",
softWrap: true, ),
overflow: TextOverflow.ellipsis)), softWrap: true,
overflow: TextOverflow.ellipsis)),
DataCell( DataCell(
Text( Text(
tableObject['is_active'] == "1" tableObject['is_active'] == "1"
@ -534,7 +536,9 @@ class DepartmentListState extends State<DepartmentList> {
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
fontFamily: "Inter", fontFamily: "Inter",
color: tableObject['is_active'] == "1" ? Colors.green : Colors.red, color: tableObject['is_active'] == "1"
? Colors.green
: Colors.red,
), ),
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@ -558,17 +562,21 @@ class DepartmentListState extends State<DepartmentList> {
final departmentId = int.tryParse( final departmentId = int.tryParse(
tableObject['department_id'] tableObject['department_id']
.toString()); .toString());
if (departmentId != null) { if (departmentId != null) {
print("Table cell - department Id -- $departmentId"); print(
final data = await apiService.getDepartmentDetailsFind(departmentId); "Table cell - department Id -- $departmentId");
final data = await apiService
.getDepartmentDetailsFind(
departmentId);
print("DepartmentId -- $data"); print("DepartmentId -- $data");
showDialog( showDialog(
context: context, context: context,
builder: (context) => DepartmentData( builder: (context) =>
DepartmentData(
isDesktop: isDesktop, isDesktop: isDesktop,
departmentId: departmentId, // Pass the ID departmentId:
departmentId, // Pass the ID
departmentData: data, departmentData: data,
layoutColor: layoutColor!, layoutColor: layoutColor!,
// fetchGetForex: fetchGetForex, // fetchGetForex: fetchGetForex,
@ -612,7 +620,7 @@ class DepartmentListState extends State<DepartmentList> {
// Status and Employee Code // Status and Employee Code
Row( Row(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.spaceBetween, MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
cardObject['department_id'] ?? 'N/A', cardObject['department_id'] ?? 'N/A',
@ -636,20 +644,25 @@ class DepartmentListState extends State<DepartmentList> {
.toString()); .toString());
if (departmentId != null) { if (departmentId != null) {
print("departmentId -- $departmentId"); print(
"departmentId -- $departmentId");
final data = await apiService final data = await apiService
.getDepartmentDetailsFind(departmentId); .getDepartmentDetailsFind(
departmentId);
print("DepartmentId -- $data"); print("DepartmentId -- $data");
showDialog( showDialog(
context: context, context: context,
builder: (context) => DepartmentData( builder: (context) =>
DepartmentData(
isDesktop: isDesktop, isDesktop: isDesktop,
departmentId:departmentId, // Pass the ID departmentId:
departmentData:data, departmentId, // Pass the ID
layoutColor:layoutColor!, departmentData: data,
layoutColor: layoutColor!,
// fetchGetDepartment: fetchGetDepartment, // fetchGetDepartment: fetchGetDepartment,
fetchGetDepartment: refreshData, fetchGetDepartment:
refreshData,
// role: // role:
// "Travel Agent" // "Travel Agent"
), ),
@ -742,7 +755,7 @@ class DepartmentListState extends State<DepartmentList> {
children: [ children: [
Column( Column(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: [ children: [
Text( Text(
cardObject['name'] ?? '', cardObject['name'] ?? '',
@ -757,7 +770,7 @@ class DepartmentListState extends State<DepartmentList> {
), ),
Column( Column(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: [ children: [
Text( Text(
cardObject['description'] ?? '', cardObject['description'] ?? '',
@ -779,39 +792,39 @@ class DepartmentListState extends State<DepartmentList> {
); );
} }
return Expanded( return Expanded(
child: Column( child: Column(
// mainAxisAlignment: MainAxisAlignment.spaceBetween, // mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Expanded( Expanded(
child: isDesktop child: isDesktop
? (searchController.text.isNotEmpty && ? (searchController.text.isNotEmpty &&
filteredDepartment.isEmpty filteredDepartment.isEmpty
? Center( ? Center(
child: Text( child: Text(
"No matches found", "No matches found",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
color: Colors.grey), color: Colors.grey),
), ),
) )
: SingleChildScrollView( : SingleChildScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
child: table, child: table,
)) ))
: (searchController.text.isNotEmpty && : (searchController.text.isNotEmpty &&
filteredDepartment.isEmpty filteredDepartment.isEmpty
? Center( ? Center(
child: Text( child: Text(
"No matches found", "No matches found",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
color: Colors.grey), color: Colors.grey),
), ),
) )
: buildMobileCardView(paginatedDepartment)), : buildMobileCardView(
), paginatedDepartment)),
),
// Expanded( // Expanded(
// child: isDesktop // child: isDesktop
// ? SingleChildScrollView( // ? SingleChildScrollView(

View File

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:dropdown_search/dropdown_search.dart'; import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
@ -51,11 +52,16 @@ class ForexDataState extends State<ForexData> {
int? forexDataId; int? forexDataId;
late String isActive = "1"; late String isActive = "1";
bool isCashEditing = false;
bool isCardEditing = false;
List<String> dataHeader = [ List<String> dataHeader = [
"country_code", "country_code",
"country", "country",
"currency", "currency",
"perdiemAmount" "perdiemAmount",
"cash",
"card"
]; ];
Map<String, dynamic> forex_Detials() { Map<String, dynamic> forex_Detials() {
@ -64,6 +70,8 @@ class ForexDataState extends State<ForexData> {
"country_code": selectedCountry, "country_code": selectedCountry,
"country_name": selectedCountryName, "country_name": selectedCountryName,
"currency": controllers["currency"]?.text, "currency": controllers["currency"]?.text,
"cash_percentage": controllers["cash"]?.text,
"card_percentage": controllers["card"]?.text,
"perdiem_amount": controllers["perdiemAmount"]?.text, "perdiem_amount": controllers["perdiemAmount"]?.text,
"is_active": 1, "is_active": 1,
"created_by": userId, "created_by": userId,
@ -82,6 +90,10 @@ class ForexDataState extends State<ForexData> {
controllers[field] = TextEditingController(); controllers[field] = TextEditingController();
} }
fetchCountries(); fetchCountries();
controllers["cash"]?.addListener(_handleCashChange);
controllers["card"]?.addListener(_handleCardChange);
if (widget.forexId != null) { if (widget.forexId != null) {
print('Editing Forex ID: ${widget.forexId}'); print('Editing Forex ID: ${widget.forexId}');
updateForexDetails(); updateForexDetails();
@ -116,6 +128,8 @@ class ForexDataState extends State<ForexData> {
selectedCurrency = data['currency']; // Optional if used elsewhere selectedCurrency = data['currency']; // Optional if used elsewhere
controllers['currency']?.text = data['currency'] ?? ''; controllers['currency']?.text = data['currency'] ?? '';
controllers['cash']?.text = data['cash_percentage'] ?? '';
controllers['card']?.text = data['card_percentage'] ?? '';
controllers['perdiemAmount']?.text = data['perdiem_amount'].toString(); controllers['perdiemAmount']?.text = data['perdiem_amount'].toString();
isActive = data["is_active"]; isActive = data["is_active"];
final forexId = int.tryParse(data['forex_perdiem_id'].toString()); final forexId = int.tryParse(data['forex_perdiem_id'].toString());
@ -140,6 +154,31 @@ class ForexDataState extends State<ForexData> {
}); });
} }
void _handleCashChange() {
if (isCardEditing) return; // Prevent circular update
isCashEditing = true;
final cashText = controllers["cash"]?.text ?? '';
final cash = int.tryParse(cashText) ?? 0;
final card = 100 - cash;
controllers["card"]?.text = card.toString();
isCashEditing = false;
}
void _handleCardChange() {
if (isCashEditing) return; // Prevent circular update
final cash = int.tryParse(controllers["cash"]?.text ?? '') ?? 0;
final card = int.tryParse(controllers["card"]?.text ?? '') ?? 0;
if (cash + card != 100) {
errorMessages["cash_percentage"] = "Cash and card must total 100%";
} else {
errorMessages.remove("cash_percentage");
}
}
bool validateData() { bool validateData() {
errorMessages.clear(); errorMessages.clear();
@ -147,6 +186,8 @@ class ForexDataState extends State<ForexData> {
"country_code": selectedCountry, "country_code": selectedCountry,
"country": selectedCountryName, "country": selectedCountryName,
"currency": controllers["currency"]?.text, "currency": controllers["currency"]?.text,
"cash_percentage": controllers["cash"]?.text,
"card_percentage": controllers["card"]?.text,
"perdiemAmount": controllers["perdiemAmount"]?.text, "perdiemAmount": controllers["perdiemAmount"]?.text,
}; };
@ -154,7 +195,9 @@ class ForexDataState extends State<ForexData> {
"country_code", "country_code",
"country", "country",
"currency", "currency",
"perdiemAmount" "perdiemAmount",
"cash_percentage",
"card_percentage"
]; ];
// Check validation for each field // Check validation for each field
@ -164,6 +207,13 @@ class ForexDataState extends State<ForexData> {
} }
} }
final cash = int.tryParse(data["cash_percentage"] ?? '') ?? 0;
final card = int.tryParse(data["card_percentage"] ?? '') ?? 0;
if (cash + card != 100) {
errorMessages["card_percentage"] = "Total must be 100%";
}
return errorMessages.isEmpty; return errorMessages.isEmpty;
} }
@ -431,6 +481,107 @@ class ForexDataState extends State<ForexData> {
), ),
// if (isDesktop)SizedBox(width: 8,) else SizedBox(height: 8,), // if (isDesktop)SizedBox(width: 8,) else SizedBox(height: 8,),
SizedBox(
height: 10,
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Cash",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74)),
),
SizedBox(height: 5),
CustomTextFieldForexWrapper(
isFocused: false,
isDesktop: widget.isDesktop,
color: Colors.transparent,
width: widget.isDesktop
? MediaQuery.of(context).size.width * 0.09
: MediaQuery.of(context).size.width * 0.66,
child: SizedBox(
height: 40,
child: TextField(
controller: controllers["cash"],
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
style: const TextStyle(fontSize: 12),
decoration: const InputDecoration(
labelText: "Cash",
labelStyle:
TextStyle(fontSize: 11, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16),
),
)),
),
if (errorMessages["cash_percentage"] != null) ...[
SizedBox(height: 5), // Space before error message
Text(
errorMessages["cash_percentage"]!,
style: TextStyle(color: Colors.red, fontSize: 12),
),
],
],
),
Spacer(),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Card",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74)),
),
SizedBox(height: 5),
CustomTextFieldForexWrapper(
isFocused: false,
isDesktop: widget.isDesktop,
color: Colors.transparent,
width: widget.isDesktop
? MediaQuery.of(context).size.width * 0.09
: MediaQuery.of(context).size.width * 0.66,
child: SizedBox(
height: 40,
child: TextField(
controller: controllers["card"],
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
style: const TextStyle(fontSize: 12),
decoration: const InputDecoration(
labelText: "Card",
labelStyle:
TextStyle(fontSize: 11, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16),
),
)),
),
if (errorMessages["card_percentage"] != null) ...[
SizedBox(height: 5), // Space before error message
Text(
errorMessages["card_percentage"]!,
style: TextStyle(color: Colors.red, fontSize: 12),
),
],
],
)
],
),
SizedBox( SizedBox(
height: 10, height: 10,
), ),

View File

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:frontend/Screens/group/group.dart'; import 'package:frontend/Screens/group/group.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:responsive_builder/responsive_builder.dart'; import 'package:responsive_builder/responsive_builder.dart';
@ -209,9 +210,14 @@ class _GroupListState extends State<GroupList> {
children: [ children: [
Row( Row(
children: [ children: [
const Text('Group List', Text(
style: 'Group List',
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), style: GoogleFonts.poppins(
fontSize: isDesktop ? 16 : 14,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
IconButton( IconButton(
icon: const Icon(Icons.keyboard_arrow_down), icon: const Icon(Icons.keyboard_arrow_down),
onPressed: () {}, onPressed: () {},
@ -234,7 +240,7 @@ class _GroupListState extends State<GroupList> {
}, },
child: Row( child: Row(
children: [ children: [
Text('New Group'), Text('New Group', style: GoogleFonts.poppins(fontSize: 12)),
SizedBox( SizedBox(
width: 5, width: 5,
), ),
@ -300,9 +306,24 @@ class _GroupListState extends State<GroupList> {
Row( Row(
children: [ children: [
Expanded( Expanded(
child: Text("Group Name: ${group['name']}", child: Text("Group Name",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 13, fontWeight: FontWeight.bold)), fontSize: 11.5, fontWeight: FontWeight.w400)),
),
Expanded(
child: Text("Domestic Policy",
style: GoogleFonts.poppins(
fontSize: 11.5, fontWeight: FontWeight.w400)),
),
Expanded(
child: Text("International Policy",
style: GoogleFonts.poppins(
fontSize: 11.5, fontWeight: FontWeight.w400)),
),
Expanded(
child: Text("Description",
style: GoogleFonts.poppins(
fontSize: 11.5, fontWeight: FontWeight.w400)),
), ),
], ],
), ),
@ -311,9 +332,23 @@ class _GroupListState extends State<GroupList> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Expanded( Expanded(
child: Text( child: Text("${group['name']}",
"Policy: ${group['domestic_policy_name'] ?? group['international_policy_name']}")), style: GoogleFonts.poppins(
Expanded(child: Text("${group['description'] ?? 'N/A'}")), fontSize: 13, fontWeight: FontWeight.w600)),
),
Expanded(
child: Text("${group['domestic_policy_name'] ?? 'N/A'}",
style: GoogleFonts.poppins(
fontSize: 13, fontWeight: FontWeight.w600)),
),
Expanded(
child: Text("${group['international_policy_name']}",
style: GoogleFonts.poppins(
fontSize: 13, fontWeight: FontWeight.w600))),
Expanded(
child: Text("${group['description'] ?? 'N/A'}",
style: GoogleFonts.poppins(
fontSize: 13, fontWeight: FontWeight.w600))),
], ],
), ),
Row( Row(

View File

@ -42,8 +42,10 @@ class _ForexScreenState extends State<ForexScreen> {
late ValueNotifier<String?> flightFirstTripDateNotifier; late ValueNotifier<String?> flightFirstTripDateNotifier;
late ValueNotifier<String?> flightLastTripDateNotifier; late ValueNotifier<String?> flightLastTripDateNotifier;
// late final tripuserId;
String? tripuserId;
late String? userCardNumber; // late String? userCardNumber;
Map<String, String?> selectedValues = {}; Map<String, String?> selectedValues = {};
bool isChecked = false; // State variable for checkbox bool isChecked = false; // State variable for checkbox
@ -97,6 +99,10 @@ class _ForexScreenState extends State<ForexScreen> {
String? selectedPerdiemAmount; String? selectedPerdiemAmount;
String? CalculatedOtherExpenses; String? CalculatedOtherExpenses;
String? selectedQuotedAmount; String? selectedQuotedAmount;
int? selectedCashPercent;
int? selectedCardPercent;
bool userEdited = false;
Map<String, dynamic> get forexData { Map<String, dynamic> get forexData {
Map<String, dynamic> data = { Map<String, dynamic> data = {
@ -116,6 +122,8 @@ class _ForexScreenState extends State<ForexScreen> {
"delivery_location": textControllers["_deliveryLocation"]?.text, "delivery_location": textControllers["_deliveryLocation"]?.text,
"comments": textControllers["_comments"]?.text, "comments": textControllers["_comments"]?.text,
"total": selectedQuotedAmount, "total": selectedQuotedAmount,
"card_percentage": selectedCardPercent,
"cash_percentage": selectedCashPercent,
"created_by": widget.loginUser, "created_by": widget.loginUser,
"updated_by": widget.loginUser, "updated_by": widget.loginUser,
}; };
@ -138,6 +146,7 @@ class _ForexScreenState extends State<ForexScreen> {
"country_code": selectedCountry, "country_code": selectedCountry,
"start_date": _formatDate(textControllers["_forexStartDate"]?.text), "start_date": _formatDate(textControllers["_forexStartDate"]?.text),
"end_date": _formatDate(textControllers["_forexEndDate"]?.text), "end_date": _formatDate(textControllers["_forexEndDate"]?.text),
"user_id": tripuserId
// "currency": selectedCurrency ?? "", // "currency": selectedCurrency ?? "",
}; };
} }
@ -186,6 +195,13 @@ class _ForexScreenState extends State<ForexScreen> {
selectedDuration = responseData["duration"]?.toString() ?? ""; selectedDuration = responseData["duration"]?.toString() ?? "";
selectedQuotedAmount = selectedQuotedAmount =
responseData["perdiem_amount"]?.toString() ?? ""; responseData["perdiem_amount"]?.toString() ?? "";
selectedCardPercent =
int.tryParse(responseData["card_percentage"]?.toString() ?? "");
selectedCashPercent =
int.tryParse(responseData["cash_percentage"]?.toString() ?? "");
textControllers["_cardNumber"]?.text =
responseData["forex_card_no"]?.toString() ?? "";
}); });
_onFieldChangedForOthers(); _onFieldChangedForOthers();
_divideQuotedAmount(); _divideQuotedAmount();
@ -325,7 +341,10 @@ class _ForexScreenState extends State<ForexScreen> {
flightFirstTripDateNotifier = ValueNotifier<String?>(null); flightFirstTripDateNotifier = ValueNotifier<String?>(null);
flightLastTripDateNotifier = ValueNotifier<String?>(null); flightLastTripDateNotifier = ValueNotifier<String?>(null);
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) async {
tripuserId = await getTripUserId();
print("tripuserId - $tripuserId");
final result = getFlightTripDateRange(widget.flightData); final result = getFlightTripDateRange(widget.flightData);
flightFirstTripDateNotifier.value = result['firstTripDate']; flightFirstTripDateNotifier.value = result['firstTripDate'];
flightLastTripDateNotifier.value = result['lastTripDate']; flightLastTripDateNotifier.value = result['lastTripDate'];
@ -351,15 +370,15 @@ class _ForexScreenState extends State<ForexScreen> {
void handleUpdatedField() async { void handleUpdatedField() async {
// Set the selected value if available // Set the selected value if available
//
userCardNumber = await getForexCardNumber(); // userCardNumber = await getForexCardNumber();
// userCardNumber = "CD7909043"; // // userCardNumber = "CD7909043";
print("userCardNumber - $userCardNumber"); // print("userCardNumber - $userCardNumber");
if (widget.selectedItem == null && if (widget.selectedItem == null &&
textControllers["_cardNumber"]?.text == "") { textControllers["_cardNumber"]?.text == "") {
print("userCardNumber11 - $userCardNumber"); // print("userCardNumber11 - $userCardNumber");
textControllers["_cardNumber"]?.text = userCardNumber ?? ""; // textControllers["_cardNumber"]?.text = userCardNumber ?? "";
} }
if (widget.selectedItem != null) { if (widget.selectedItem != null) {
@ -381,13 +400,20 @@ class _ForexScreenState extends State<ForexScreen> {
selectedCountry = widget.selectedItem!["country_code"] as String?; selectedCountry = widget.selectedItem!["country_code"] as String?;
selectedCurrency = widget.selectedItem!["currency"] as String?; selectedCurrency = widget.selectedItem!["currency"] as String?;
selectedDuration = widget.selectedItem!["duration"] as String?; selectedDuration = widget.selectedItem!["duration"] as String?;
selectedCardPercent = int.tryParse(
widget.selectedItem!["card_percentage"]?.toString() ?? "");
selectedCashPercent = int.tryParse(
widget.selectedItem!["cash_percentage"]?.toString() ?? "");
selectedPerdiemAmount = widget.selectedItem!["perdiem_amount"] as String?; selectedPerdiemAmount = widget.selectedItem!["perdiem_amount"] as String?;
isChecked = isChecked =
widget.selectedItem!["have_card"] == "1"; // Convert string to bool widget.selectedItem!["have_card"] == "1"; // Convert string to bool
textControllers["_cardNumber"]?.text =
widget.selectedItem!["card_number"]?.toString() ?? "";
// if (textControllers["_cardNumber"] != null) { // if (textControllers["_cardNumber"] != null) {
// print("userCardNumber11 - $userCardNumber"); // print("userCardNumber11 - $userCardNumber");
// textControllers["_cardNumber"]!.text = userCardNumber ?? ''; // textControllers["_cardNumber"]!.text = userCardNumber ?? '';
//
// } // }
_onFieldChangedForOthers(); _onFieldChangedForOthers();
@ -431,7 +457,11 @@ class _ForexScreenState extends State<ForexScreen> {
} }
if (_isForexDataComplete()) { if (_isForexDataComplete()) {
postgetForexData(getForexData); if (tripuserId != null) {
postgetForexData(getForexData);
} else {
print("tripuserId is null");
}
} }
} }
@ -503,35 +533,42 @@ class _ForexScreenState extends State<ForexScreen> {
selectedQuotedAmount = selectedQuotedAmount =
((perdiemAmount + calclateVal).toString() ?? 0) as String?; ((perdiemAmount + calclateVal).toString() ?? 0) as String?;
}); });
_divideQuotedAmount();
if (userEdited) {
_divideQuotedAmount();
}
errorMessages.clear(); errorMessages.clear();
} }
void _divideQuotedAmount() { void _divideQuotedAmount() {
int? quotedAmount = int.tryParse(selectedQuotedAmount!); int? quotedAmount = int.tryParse(selectedQuotedAmount!);
print("quotedAmount - $selectedQuotedAmount");
print("DIVIDREFD - $selectedQuotedAmount -$quotedAmount"); print("DIVIDREFD - $selectedQuotedAmount -$quotedAmount");
if (quotedAmount != null) { if (quotedAmount != null) {
fifteenPercent = // fifteenPercent = (quotedAmount * 15) ~/ 100;
(quotedAmount * 15) ~/ 100; // Calculate 15% (integer division) print("selectedCardPercent - $selectedCashPercent");
fifteenPercent = (quotedAmount * selectedCashPercent!) ~/
100; // Calculate 15% (integer division)
remainingAmount = quotedAmount - fifteenPercent; // Subtract from total remainingAmount = quotedAmount - fifteenPercent; // Subtract from total
// Only set text if the field is empty (user hasn't typed) // // Only set text if the field is empty (user hasn't typed)
if (textControllers["_cash"] != null && // if (textControllers["_cash"] != null &&
textControllers["_cash"]!.text.trim().isEmpty) { // textControllers["_cash"]!.text.trim().isEmpty) {
textControllers["_cash"]!.text = fifteenPercent.toString(); // textControllers["_cash"]!.text = fifteenPercent.toString();
} else { // } else {
print("_cash already has user input, not overwriting"); // print("_cash already has user input, not overwriting");
} // }
//
// if (textControllers["_card"] != null &&
// textControllers["_card"]!.text.trim().isEmpty) {
// textControllers["_card"]!.text = remainingAmount.toString();
// } else {
// print("_card already has user input, not overwriting");
// }
if (textControllers["_card"] != null && textControllers["_cash"]?.text = fifteenPercent.toString();
textControllers["_card"]!.text.trim().isEmpty) { textControllers["_card"]?.text = remainingAmount.toString();
textControllers["_card"]!.text = remainingAmount.toString();
} else {
print("_card already has user input, not overwriting");
}
// textControllers["_cash"]?.text = fifteenPercent.toString();
// textControllers["_card"]?.text = remainingAmount.toString();
print("15% Amount: $fifteenPercent"); print("15% Amount: $fifteenPercent");
print("Remaining Amount: $remainingAmount"); print("Remaining Amount: $remainingAmount");
} else { } else {
@ -588,13 +625,13 @@ class _ForexScreenState extends State<ForexScreen> {
print('CardAmount - $cardAmount'); print('CardAmount - $cardAmount');
textControllers["_card"]?.text = difference.toString(); textControllers["_card"]?.text = difference.toString();
if (enteredAmount == null || enteredAmount > fifteenPercent) { // if (enteredAmount > fifteenPercent) {
errorMessages["deposit_on_cash"] = "Amount cannot exceed $fifteenPercent"; // errorMessages["deposit_on_cash"] = "Amount cannot exceed $fifteenPercent";
} else if (checkValidAmount == quotedAmount) { // } else if (checkValidAmount == quotedAmount) {
errorMessages["deposit_on_card"] = " "; // Clear error if valid // errorMessages["deposit_on_card"] = " "; // Clear error if valid
} else { // } else {
errorMessages["deposit_on_cash"] = ""; // Clear error if valid // errorMessages["deposit_on_cash"] = ""; // Clear error if valid
} // }
// Refresh UI if using StatefulWidget // Refresh UI if using StatefulWidget
setState(() {}); setState(() {});
@ -1253,7 +1290,12 @@ class _ForexScreenState extends State<ForexScreen> {
child: TextField( child: TextField(
focusNode: focusNodes["_transport"], focusNode: focusNodes["_transport"],
controller: textControllers["_transport"], controller: textControllers["_transport"],
onChanged: (value) => _onFieldChangedForOthers(), onChanged: (value) {
setState(() {
userEdited = true;
});
_onFieldChangedForOthers();
},
keyboardType: TextInputType.numberWithOptions(decimal: true), keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [ inputFormatters: [
FilteringTextInputFormatter.allow(RegExp( FilteringTextInputFormatter.allow(RegExp(
@ -1324,7 +1366,12 @@ class _ForexScreenState extends State<ForexScreen> {
child: TextField( child: TextField(
focusNode: focusNodes["_accomodation"], focusNode: focusNodes["_accomodation"],
controller: textControllers["_accomodation"], controller: textControllers["_accomodation"],
onChanged: (value) => _onFieldChangedForOthers(), onChanged: (value) {
setState(() {
userEdited = true;
});
_onFieldChangedForOthers();
},
keyboardType: TextInputType.numberWithOptions(decimal: true), keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [ inputFormatters: [
FilteringTextInputFormatter.allow(RegExp( FilteringTextInputFormatter.allow(RegExp(
@ -1396,7 +1443,12 @@ class _ForexScreenState extends State<ForexScreen> {
child: TextField( child: TextField(
focusNode: focusNodes["_telephone"], focusNode: focusNodes["_telephone"],
controller: textControllers["_telephone"], controller: textControllers["_telephone"],
onChanged: (value) => _onFieldChangedForOthers(), onChanged: (value) {
setState(() {
userEdited = true;
});
_onFieldChangedForOthers();
},
keyboardType: TextInputType.numberWithOptions(decimal: true), keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [ inputFormatters: [
FilteringTextInputFormatter.allow(RegExp( FilteringTextInputFormatter.allow(RegExp(
@ -1536,6 +1588,7 @@ class _ForexScreenState extends State<ForexScreen> {
style: const TextStyle(fontSize: 12), style: const TextStyle(fontSize: 12),
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
onChanged: (value) { onChanged: (value) {
// errorMessages["deposit_on_cash"] = "";
_validateCashAmount( _validateCashAmount(
value); // Call validation when text changes value); // Call validation when text changes
}, },

View File

@ -610,13 +610,13 @@ class TemplatesListState extends State<TemplatesList> {
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),
)), )),
DataColumn( // DataColumn(
label: Text( // label: Text(
'Attributes', // 'Attributes',
style: GoogleFonts.poppins( // style: GoogleFonts.poppins(
fontSize: 13, // fontSize: 13,
fontWeight: FontWeight.w600), // fontWeight: FontWeight.w600),
)), // )),
DataColumn( DataColumn(
label: Text( label: Text(
'Actions', 'Actions',
@ -640,12 +640,12 @@ class TemplatesListState extends State<TemplatesList> {
fontSize: 13, fontSize: 13,
fontFamily: "Inter", fontFamily: "Inter",
))), ))),
DataCell(Text( // DataCell(Text(
getPlaceholderNames(forex['placeholder']), // getPlaceholderNames(forex['placeholder']),
style: TextStyle( // style: TextStyle(
fontSize: 13, // fontSize: 13,
fontFamily: "Inter", // fontFamily: "Inter",
))), // ))),
DataCell( DataCell(
// UserActionsMenu( // UserActionsMenu(
// user: forex, // user: forex,
@ -661,14 +661,14 @@ class TemplatesListState extends State<TemplatesList> {
// final userId = getUserId(user['user_id']); // final userId = getUserId(user['user_id']);
// final usersData = await getUserDetails(userId); // final usersData = await getUserDetails(userId);
// //
final forexId = int.tryParse( final templateId = int.tryParse(
forex['forex_perdiem_id'] forex['forex_perdiem_id']
.toString()); .toString());
if (forexId != null) { if (templateId != null) {
print("ForexId -- $forexId"); print("templateId -- $templateId");
final data = await apiService final data = await apiService
.getForexDetailsFind(forexId); .getTemplateFind(templateId);
print("ForexId -- $data"); print("ForexId -- $data");
} else { } else {
print("Invalid Forex ID"); print("Invalid Forex ID");
@ -725,24 +725,24 @@ class TemplatesListState extends State<TemplatesList> {
SizedBox(height: 2), SizedBox(height: 2),
// Trip Id and Trip Name // Trip Id and Trip Name
Row( // Row(
children: [ // children: [
Column( // Column(
crossAxisAlignment: // crossAxisAlignment:
CrossAxisAlignment.start, // CrossAxisAlignment.start,
children: [ // children: [
Text( // Text(
getPlaceholderNames( // getPlaceholderNames(
forex['placeholder']), // forex['placeholder']),
style: GoogleFonts.poppins( // style: GoogleFonts.poppins(
fontSize: 12, // fontSize: 12,
color: Colors.black87, // color: Colors.black87,
fontWeight: FontWeight.w500), // fontWeight: FontWeight.w500),
), // ),
], // ],
), // ),
], // ],
), // ),
// Actions // Actions
// Actions // Actions

View File

@ -680,7 +680,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
} }
} }
void getSelectedPlanFor() { Future<void> getSelectedPlanFor() async {
var userTripId;
// if (!mounted) return; // if (!mounted) return;
print("getSelectedPlanFor"); print("getSelectedPlanFor");
setState(() { setState(() {
@ -689,18 +690,24 @@ class CreateNewPlansState extends State<CreateNewPlan> {
if (selectedIstravelUser!) { if (selectedIstravelUser!) {
planUsrId = ""; planUsrId = "";
planTravlrId = selectedplanUserId; planTravlrId = selectedplanUserId;
userTripId = selectedplanUserId;
} else { } else {
planUsrId = selectedplanUserId; planUsrId = selectedplanUserId;
planTravlrId = ""; planTravlrId = "";
userTripId = selectedplanUserId;
} }
} else { } else {
print("Is USER ID - $planUsrId "); print("Is USER ID - $planUsrId ");
planUsrId = selfId; planUsrId = selfId;
planTravlrId = ""; planTravlrId = "";
_selectedOption = "Option 1"; _selectedOption = "Option 1";
userTripId = selfId;
} }
}); });
final prefs = await SharedPreferences.getInstance();
await prefs.setString('trip_planned_user', userTripId);
print("USER ID - $planUsrId , TRAVELLER ID - $planTravlrId"); print("USER ID - $planUsrId , TRAVELLER ID - $planTravlrId");
} }

View File

@ -2416,7 +2416,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
), ),
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search Country...", hintText: "Search Airline...",
hintStyle: GoogleFonts.poppins(fontSize: 11.5), hintStyle: GoogleFonts.poppins(fontSize: 11.5),
contentPadding: EdgeInsets.symmetric(horizontal: 10), contentPadding: EdgeInsets.symmetric(horizontal: 10),
), ),
@ -2435,7 +2435,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
// Center-align selected item // Center-align selected item
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Text( child: Text(
selectedItem ?? "Select Country", selectedItem ?? "Select Airline",
style: TextStyle(fontSize: 12), style: TextStyle(fontSize: 12),
), ),
), ),

View File

@ -887,6 +887,51 @@ class ApiService {
} }
} }
Future<Map<String, dynamic>> getTemplateFind(int id) async {
final String apiUrldata = '$apiUrl/api/template/find/$id';
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) {
try {
final data = json.decode(response.body);
// print('findout the result');
// print(data.runtimeType);
// print(data);
if (!data.containsKey('data') || data['data'] is! List) {
throw Exception(
"Invalid response format: 'data' field is missing or not a List");
}
final List<Map<String, dynamic>> listData =
List<Map<String, dynamic>>.from(data['data']);
if (listData.isEmpty) {
throw Exception("No department found with ID $id");
}
return listData[0];
} catch (e) {
throw Exception('Error parsing response: $e');
}
} else {
throw Exception('Failed to load department details');
}
}
Future<bool> showCancelConfirmationDialog( Future<bool> showCancelConfirmationDialog(
BuildContext context, Color? layoutColor) async { BuildContext context, Color? layoutColor) async {
return await showDialog<bool>( return await showDialog<bool>(

View File

@ -7,6 +7,11 @@ Future<String?> getToken() async {
return prefs.getString("auth_token"); return prefs.getString("auth_token");
} }
Future<String?> getTripUserId() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString("trip_planned_user");
}
Future<String?> getLayoutColor() async { Future<String?> getLayoutColor() async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
return prefs.getString("layout_color"); return prefs.getString("layout_color");