authentication
This commit is contained in:
parent
08f80a8afa
commit
6bb37994de
BIN
assets/images/IconsImg/download.png
Normal file
BIN
assets/images/IconsImg/download.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 741 B |
BIN
assets/images/IconsImg/upload.png
Normal file
BIN
assets/images/IconsImg/upload.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 729 B |
@ -50,20 +50,37 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
getToken();
|
_checkAuthAndLoadData();
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
// // If token exists, load the dashboard data
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// initializeData();
|
||||||
|
// loadInitialData();
|
||||||
|
//
|
||||||
|
// // futurePlans.then((plans) {
|
||||||
|
// // setState(() {
|
||||||
|
// // allPlans = plans;
|
||||||
|
// // filteredPlans = plans;
|
||||||
|
// // });
|
||||||
|
// // });
|
||||||
|
// });
|
||||||
|
// // futurePlans = fetchPlans();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
getToken();
|
||||||
initializeData();
|
initializeData();
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
|
}
|
||||||
// futurePlans.then((plans) {
|
|
||||||
// setState(() {
|
|
||||||
// allPlans = plans;
|
|
||||||
// filteredPlans = plans;
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
// futurePlans = fetchPlans();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void filterPlans(String query) {
|
void filterPlans(String query) {
|
||||||
|
|||||||
@ -48,23 +48,39 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
getToken();
|
_checkAuthAndLoadData();
|
||||||
|
// getToken();
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
//
|
||||||
initializeData();
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
loadInitialData();
|
// initializeData();
|
||||||
|
// loadInitialData();
|
||||||
// futurePlans.then((plans) {
|
//
|
||||||
// setState(() {
|
// // futurePlans.then((plans) {
|
||||||
// allPlans = plans;
|
// // setState(() {
|
||||||
// filteredPlans = plans;
|
// // allPlans = plans;
|
||||||
|
// // filteredPlans = plans;
|
||||||
|
// // });
|
||||||
|
// // });
|
||||||
// });
|
// });
|
||||||
// });
|
|
||||||
});
|
|
||||||
|
|
||||||
// futurePlans = fetchPlans();
|
// futurePlans = fetchPlans();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getToken();
|
||||||
|
initializeData();
|
||||||
|
loadInitialData();
|
||||||
|
}
|
||||||
|
|
||||||
void filterPlans(String query) {
|
void filterPlans(String query) {
|
||||||
print("allPlans before filtering: $allPlans");
|
print("allPlans before filtering: $allPlans");
|
||||||
final lowerQuery = query.toLowerCase();
|
final lowerQuery = query.toLowerCase();
|
||||||
|
|||||||
@ -46,16 +46,32 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
getToken();
|
_checkAuthAndLoadData();
|
||||||
|
// getToken();
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
//
|
||||||
initializeData();
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
loadInitialData();
|
// initializeData();
|
||||||
});
|
// loadInitialData();
|
||||||
|
// });
|
||||||
|
|
||||||
// futurePlans = fetchPlans();
|
// futurePlans = fetchPlans();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getToken();
|
||||||
|
initializeData();
|
||||||
|
loadInitialData();
|
||||||
|
}
|
||||||
|
|
||||||
void loadInitialData() async {
|
void loadInitialData() async {
|
||||||
String? layoutString = await getLayoutColor();
|
String? layoutString = await getLayoutColor();
|
||||||
String? bodyStringColor = await getBodyColor();
|
String? bodyStringColor = await getBodyColor();
|
||||||
|
|||||||
@ -135,16 +135,10 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
timeInSecForIosWeb: 2,
|
timeInSecForIosWeb: 2,
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
fontSize: 16.0,
|
fontSize: 18.0,
|
||||||
|
webBgColor: "linear-gradient(to right, #28a745, #28a745)",
|
||||||
);
|
);
|
||||||
|
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
// SnackBar(
|
|
||||||
// content: Text("Login Successful"),
|
|
||||||
// backgroundColor: Colors.green, // Set background to green
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
|
|
||||||
if (userRole == "Travel Agent") {
|
if (userRole == "Travel Agent") {
|
||||||
context.go('/listTravelAgentPlan');
|
context.go('/listTravelAgentPlan');
|
||||||
} else if (userRole == "Org Admin" || userRole == "Travel Admin") {
|
} else if (userRole == "Org Admin" || userRole == "Travel Admin") {
|
||||||
@ -225,12 +219,6 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
_showOtpResetFields = true;
|
_showOtpResetFields = true;
|
||||||
// _clearAllFields();
|
// _clearAllFields();
|
||||||
});
|
});
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
// SnackBar(
|
|
||||||
// content: Text("OTP sent to your email"),
|
|
||||||
// backgroundColor: Colors.green,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
|
|
||||||
Fluttertoast.showToast(
|
Fluttertoast.showToast(
|
||||||
msg: "OTP sent to your email",
|
msg: "OTP sent to your email",
|
||||||
@ -240,18 +228,10 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
fontSize: 16.0,
|
fontSize: 16.0,
|
||||||
|
webBgColor: "linear-gradient(to right, #28a745, #28a745)",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
print(response);
|
print(response);
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
// SnackBar(
|
|
||||||
// content: Text(
|
|
||||||
// "${jsonDecode(response.body)['messages']['error']}",
|
|
||||||
// ),
|
|
||||||
//
|
|
||||||
// backgroundColor: Colors.red,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
|
|
||||||
Fluttertoast.showToast(
|
Fluttertoast.showToast(
|
||||||
msg: "${jsonDecode(response.body)['messages']['error']}",
|
msg: "${jsonDecode(response.body)['messages']['error']}",
|
||||||
@ -304,12 +284,6 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
_showOtpResetFields = false;
|
_showOtpResetFields = false;
|
||||||
_clearAllFields();
|
_clearAllFields();
|
||||||
});
|
});
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
// SnackBar(
|
|
||||||
// content: Text("Password reset successfully"),
|
|
||||||
// backgroundColor: Colors.green,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
|
|
||||||
Fluttertoast.showToast(
|
Fluttertoast.showToast(
|
||||||
msg: "Password reset successfully",
|
msg: "Password reset successfully",
|
||||||
@ -319,6 +293,7 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
fontSize: 16.0,
|
fontSize: 16.0,
|
||||||
|
webBgColor: "linear-gradient(to right, #28a745, #28a745)",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
print('23');
|
print('23');
|
||||||
@ -521,6 +496,7 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
fontSize: widget.isDesktop ? 20 : 18,
|
fontSize: widget.isDesktop ? 20 : 18,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
color: Colors.green,
|
color: Colors.green,
|
||||||
|
|
||||||
// color: Color(0xFF212121),
|
// color: Color(0xFF212121),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -28,7 +28,8 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
GlobalKey<CostCenterListState>();
|
GlobalKey<CostCenterListState>();
|
||||||
|
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
late Future<List<dynamic>> futureCostCenter;
|
Future<List<dynamic>>? futureCostCenter;
|
||||||
|
// late Future<List<dynamic>> futureCostCenter;
|
||||||
|
|
||||||
late Map<String, dynamic> depSingleData;
|
late Map<String, dynamic> depSingleData;
|
||||||
String? selectedCostCenterId;
|
String? selectedCostCenterId;
|
||||||
@ -47,9 +48,37 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
// futureCostCenter = fetchGetCostCenter();
|
||||||
|
//
|
||||||
|
// futureCostCenter.then((object) {
|
||||||
|
// setState(() {
|
||||||
|
// allCostCenter = object;
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// loadInitialData();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// futurePlans = fetchPlans();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
try {
|
||||||
futureCostCenter = fetchGetCostCenter();
|
futureCostCenter = fetchGetCostCenter();
|
||||||
|
|
||||||
futureCostCenter.then((object) {
|
futureCostCenter?.then((object) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allCostCenter = object;
|
allCostCenter = object;
|
||||||
});
|
});
|
||||||
@ -58,8 +87,9 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
// futurePlans = fetchPlans();
|
print("group : $e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadInitialData() async {
|
void loadInitialData() async {
|
||||||
@ -89,7 +119,7 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
|
|
||||||
futureCostCenter = fetchGetCostCenter();
|
futureCostCenter = fetchGetCostCenter();
|
||||||
|
|
||||||
return futureCostCenter.then((object) {
|
return futureCostCenter!.then((object) {
|
||||||
print("Calling Refresh Data $object");
|
print("Calling Refresh Data $object");
|
||||||
setState(() {
|
setState(() {
|
||||||
allCostCenter = object;
|
allCostCenter = object;
|
||||||
@ -406,6 +436,10 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureCostCenter,
|
future: futureCostCenter,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
if (futureCostCenter == null) {
|
||||||
|
return CircularProgressIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasError ||
|
} else if (snapshot.hasError ||
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:html' as html;
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:frontend/routes/custom_router.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';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
@ -16,7 +20,6 @@ import '../../utils/auth_utils.dart';
|
|||||||
import '../../utils/pagination.dart';
|
import '../../utils/pagination.dart';
|
||||||
|
|
||||||
class StatusDashboard extends StatefulWidget {
|
class StatusDashboard extends StatefulWidget {
|
||||||
|
|
||||||
const StatusDashboard({super.key});
|
const StatusDashboard({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -24,15 +27,101 @@ class StatusDashboard extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class StatusDashboardState extends State<StatusDashboard> {
|
class StatusDashboardState extends State<StatusDashboard> {
|
||||||
|
|
||||||
Map<String, dynamic>? apiData;
|
Map<String, dynamic>? apiData;
|
||||||
String? organizationId;
|
String? organizationId;
|
||||||
|
late bool _dialogShown = false;
|
||||||
|
late StreamSubscription<html.PopStateEvent> _popStateListener;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
loadDashboardData();
|
_checkAuthAndLoadData();
|
||||||
|
|
||||||
|
checkbackbutton();
|
||||||
|
|
||||||
|
// loadDashboardData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkbackbutton() async {
|
||||||
|
// Push a dummy state so back button triggers popstate instead of navigating
|
||||||
|
html.window.history.pushState(null, 'home', html.window.location.href);
|
||||||
|
|
||||||
|
_popStateListener = html.window.onPopState.listen((event) {
|
||||||
|
if (!_dialogShown && mounted) {
|
||||||
|
_showBackConfirmationDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-push to prevent leaving
|
||||||
|
html.window.history.pushState(null, 'home', html.window.location.href);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_popStateListener.cancel(); // ✅ Remove the browser popstate listener
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showBackConfirmationDialog() {
|
||||||
|
if (!mounted) return;
|
||||||
|
|
||||||
|
_dialogShown = true;
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => AlertDialog(
|
||||||
|
title: Text("Confirm"),
|
||||||
|
content: Text("Do you want to logout?"),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context); // Close dialog
|
||||||
|
_dialogShown = false;
|
||||||
|
},
|
||||||
|
child: Text("Cancel"),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.pop(context); // Close dialog
|
||||||
|
_dialogShown = false;
|
||||||
|
await _logoutAndRedirect(context);
|
||||||
|
},
|
||||||
|
child: Text("Logout"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _logoutAndRedirect(BuildContext context) async {
|
||||||
|
print("logue 0");
|
||||||
|
|
||||||
|
// Example: clear session or shared preferences
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.clear();
|
||||||
|
|
||||||
|
context.go("/");
|
||||||
|
|
||||||
|
print("logue 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
checkbackbutton();
|
||||||
|
});
|
||||||
|
// If token exists, load the dashboard data
|
||||||
|
loadDashboardData();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadDashboardData() async {
|
Future<void> loadDashboardData() async {
|
||||||
@ -66,13 +155,11 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<Map<String, dynamic>> fetchStatusDashboard() async {
|
Future<Map<String, dynamic>> fetchStatusDashboard() async {
|
||||||
|
|
||||||
|
|
||||||
organizationId = await getOrgId();
|
organizationId = await getOrgId();
|
||||||
|
|
||||||
final String apiUrlData = '$apiUrl/api/plans/statusDashboard?org_id=$organizationId';
|
final String apiUrlData =
|
||||||
|
'$apiUrl/api/plans/statusDashboard?org_id=$organizationId';
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
|
|
||||||
print("Fetch StatusDashboard -- 2KN Here : $token");
|
print("Fetch StatusDashboard -- 2KN Here : $token");
|
||||||
@ -132,17 +219,18 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final typeBasedCount = List<Map<String, dynamic>>.from(
|
final typeBasedCount = List<Map<String, dynamic>>.from(
|
||||||
(apiData?['data']?['typeBasedCount']) ?? []);
|
(apiData?['data']?['typeBasedCount']) ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
print("apiData - => $apiData");
|
print("apiData - => $apiData");
|
||||||
print("typeBasedCount => $typeBasedCount");
|
print("typeBasedCount => $typeBasedCount");
|
||||||
|
|
||||||
final statusBasedCount = List<Map<String, dynamic>>.from(
|
final statusBasedCount = List<Map<String, dynamic>>.from(
|
||||||
(apiData?['data']?['statusBasedCount']) ?? []);
|
(apiData?['data']?['statusBasedCount']) ?? [],
|
||||||
|
);
|
||||||
print("statusBasedCount - => $statusBasedCount");
|
print("statusBasedCount - => $statusBasedCount");
|
||||||
// 👇 Local function to create the card widget
|
// 👇 Local function to create the card widget
|
||||||
Widget buildInfoCard(String title, int count, double width) {
|
Widget buildInfoCard(String title, int count, double width) {
|
||||||
@ -159,14 +247,24 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Icon(icon, size: 32, color: (title == 'Domestic' || title == 'International') ? Colors.green : Colors.black54), // 👈 Add Icon here
|
Icon(
|
||||||
|
icon,
|
||||||
|
size: 32,
|
||||||
|
color:
|
||||||
|
(title == 'Domestic' || title == 'International')
|
||||||
|
? Colors.green
|
||||||
|
: Colors.black54,
|
||||||
|
), // 👈 Add Icon here
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
title,
|
title,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: (title == 'Domestic' || title == 'International') ? 16 : 14,
|
fontSize:
|
||||||
|
(title == 'Domestic' || title == 'International')
|
||||||
|
? 16
|
||||||
|
: 14,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@ -182,22 +280,42 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
void _handleBackButton() {
|
||||||
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
final location = GoRouterState.of(context).uri.toString();
|
||||||
|
|
||||||
return Scaffold(
|
print("location - $location");
|
||||||
|
if (location.contains('/StatusDashboard')) {
|
||||||
|
// Do nothing or show "Press again to exit" toast
|
||||||
|
print("Blocked back on dashboard");
|
||||||
|
} else {
|
||||||
|
print("dashboard ..");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponsiveBuilder(
|
||||||
|
builder: (context, sizingInfo) {
|
||||||
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
|
return PopScope(
|
||||||
|
canPop: false, // Allow back navigation only if not login screen
|
||||||
|
onPopInvokedWithResult: (didPop, result) {
|
||||||
|
if (didPop) return;
|
||||||
|
_handleBackButton(); // Show exit confirmation dialog
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
backgroundColor: const Color(0xFFf5f5f5),
|
backgroundColor: const Color(0xFFf5f5f5),
|
||||||
appBar: CustomAppBar(isDesktop: isDesktop),
|
appBar: CustomAppBar(isDesktop: isDesktop),
|
||||||
drawer: CustomDrawer(isDesktop: false),
|
drawer: CustomDrawer(isDesktop: false),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: isDesktop
|
padding:
|
||||||
|
isDesktop
|
||||||
? EdgeInsets.symmetric(
|
? EdgeInsets.symmetric(
|
||||||
horizontal: MediaQuery.of(context).size.width * 0.1, // 30% of screen width as horizontal padding
|
horizontal:
|
||||||
|
MediaQuery.of(context).size.width *
|
||||||
|
0.1, // 30% of screen width as horizontal padding
|
||||||
vertical: 10, // 5% of screen height as vertical padding
|
vertical: 10, // 5% of screen height as vertical padding
|
||||||
)
|
)
|
||||||
: EdgeInsets.all(0),
|
: EdgeInsets.all(0),
|
||||||
@ -208,10 +326,14 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
minHeight: constraints.maxHeight,
|
minHeight: constraints.maxHeight,
|
||||||
),
|
),
|
||||||
child: IntrinsicHeight( // Only needed if child layout depends on height
|
child: IntrinsicHeight(
|
||||||
|
// Only needed if child layout depends on height
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isDesktop ? Colors.white : const Color(0xFFFCFCFC),
|
color:
|
||||||
|
isDesktop
|
||||||
|
? Colors.white
|
||||||
|
: const Color(0xFFFCFCFC),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -220,19 +342,34 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(30.0),
|
padding: const EdgeInsets.all(30.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Wrap(
|
Wrap(
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
runSpacing: 10,
|
runSpacing: 10,
|
||||||
children: typeBasedCount.map((item) {
|
children:
|
||||||
double cardWidth = isDesktop
|
typeBasedCount.map((item) {
|
||||||
? (MediaQuery.of(context).size.width * 0.75 - 10) / 2 // 80% width padding adjusted
|
double cardWidth =
|
||||||
: MediaQuery.of(context).size.width - 24; // full width with padding
|
isDesktop
|
||||||
|
? (MediaQuery.of(
|
||||||
|
context,
|
||||||
|
).size.width *
|
||||||
|
0.75 -
|
||||||
|
10) /
|
||||||
|
2 // 80% width padding adjusted
|
||||||
|
: MediaQuery.of(
|
||||||
|
context,
|
||||||
|
).size.width -
|
||||||
|
24; // full width with padding
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: cardWidth,
|
width: cardWidth,
|
||||||
child: buildInfoCard(item['value'], item['count'], cardWidth),
|
child: buildInfoCard(
|
||||||
|
item['value'],
|
||||||
|
item['count'],
|
||||||
|
cardWidth,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
@ -240,18 +377,31 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
Wrap(
|
Wrap(
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
runSpacing: 10,
|
runSpacing: 10,
|
||||||
children: statusBasedCount.map((item) {
|
children:
|
||||||
double cardWidth = isDesktop
|
statusBasedCount.map((item) {
|
||||||
? (MediaQuery.of(context).size.width * 0.90 - 50) / 6 // desktop layout: 6 cards per row
|
double cardWidth =
|
||||||
: MediaQuery.of(context).size.width - 24; // mobile: full width
|
isDesktop
|
||||||
|
? (MediaQuery.of(
|
||||||
|
context,
|
||||||
|
).size.width *
|
||||||
|
0.90 -
|
||||||
|
50) /
|
||||||
|
6 // desktop layout: 6 cards per row
|
||||||
|
: MediaQuery.of(
|
||||||
|
context,
|
||||||
|
).size.width -
|
||||||
|
24; // mobile: full width
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: cardWidth,
|
width: cardWidth,
|
||||||
child: buildInfoCard(item['value'], item['count'], cardWidth),
|
child: buildInfoCard(
|
||||||
|
item['value'],
|
||||||
|
item['count'],
|
||||||
|
cardWidth,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -263,14 +413,11 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -28,7 +28,8 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
GlobalKey<DepartmentListState>();
|
GlobalKey<DepartmentListState>();
|
||||||
|
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
late Future<List<dynamic>> futureDepartment;
|
// late Future<List<dynamic>> futureDepartment;
|
||||||
|
Future<List<dynamic>>? futureDepartment;
|
||||||
|
|
||||||
late Map<String, dynamic> depSingleData;
|
late Map<String, dynamic> depSingleData;
|
||||||
String? selectedDepartmentId;
|
String? selectedDepartmentId;
|
||||||
@ -47,9 +48,37 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
// futureDepartment = fetchGetDepartment();
|
||||||
|
//
|
||||||
|
// futureDepartment.then((object) {
|
||||||
|
// setState(() {
|
||||||
|
// allDepartment = object;
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// loadInitialData();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// futurePlans = fetchPlans();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
try {
|
||||||
futureDepartment = fetchGetDepartment();
|
futureDepartment = fetchGetDepartment();
|
||||||
|
|
||||||
futureDepartment.then((object) {
|
futureDepartment?.then((object) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allDepartment = object;
|
allDepartment = object;
|
||||||
});
|
});
|
||||||
@ -58,8 +87,9 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
// futurePlans = fetchPlans();
|
print("group : $e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadInitialData() async {
|
void loadInitialData() async {
|
||||||
@ -89,7 +119,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
|
|
||||||
futureDepartment = fetchGetDepartment();
|
futureDepartment = fetchGetDepartment();
|
||||||
|
|
||||||
return futureDepartment.then((object) {
|
return futureDepartment!.then((object) {
|
||||||
print("Calling Refresh Data $object");
|
print("Calling Refresh Data $object");
|
||||||
setState(() {
|
setState(() {
|
||||||
allDepartment = object;
|
allDepartment = object;
|
||||||
@ -405,6 +435,10 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureDepartment,
|
future: futureDepartment,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
if (futureDepartment == null) {
|
||||||
|
CircularProgressIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasError ||
|
} else if (snapshot.hasError ||
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import '../../widgets/custom_text_forex.dart';
|
|||||||
import 'forex_list.dart';
|
import 'forex_list.dart';
|
||||||
|
|
||||||
class ForexData extends StatefulWidget {
|
class ForexData extends StatefulWidget {
|
||||||
final Future<List<dynamic>> Function() fetchGetForex;
|
final Future<List<dynamic>?> Function() fetchGetForex;
|
||||||
final bool isDesktop;
|
final bool isDesktop;
|
||||||
final Color? layoutColor;
|
final Color? layoutColor;
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,8 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
GlobalKey<ForexDataListState>();
|
GlobalKey<ForexDataListState>();
|
||||||
|
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
late Future<List<dynamic>> futureForex;
|
// late Future<List<dynamic>> futureForex;
|
||||||
|
Future<List<dynamic>>? futureForex;
|
||||||
|
|
||||||
late Map<String, dynamic> userSingleData;
|
late Map<String, dynamic> userSingleData;
|
||||||
List<dynamic>? apiCountryData;
|
List<dynamic>? apiCountryData;
|
||||||
@ -49,9 +50,38 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
// futureForex = fetchGetForex();
|
||||||
|
//
|
||||||
|
// futureForex.then((users) {
|
||||||
|
// setState(() {
|
||||||
|
// allForex = users;
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// fetchCountryList();
|
||||||
|
// loadInitialData();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// futurePlans = fetchPlans();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
try {
|
||||||
futureForex = fetchGetForex();
|
futureForex = fetchGetForex();
|
||||||
|
|
||||||
futureForex.then((users) {
|
futureForex?.then((users) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allForex = users;
|
allForex = users;
|
||||||
});
|
});
|
||||||
@ -61,16 +91,33 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
fetchCountryList();
|
fetchCountryList();
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
// futurePlans = fetchPlans();
|
print("group : $e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> refreshData() {
|
// Future<List<dynamic>?> refreshData() {
|
||||||
|
// print("Calling Refresh Data");
|
||||||
|
//
|
||||||
|
// // futureForex = fetchGetForex();
|
||||||
|
// futureForex = fetchGetForex() ?? Future.value([]);
|
||||||
|
//
|
||||||
|
// return futureForex.then((users) {
|
||||||
|
// setState(() {
|
||||||
|
// allForex = users;
|
||||||
|
// filteredForex = users;
|
||||||
|
// searchController.text = "";
|
||||||
|
// });
|
||||||
|
// return users;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
Future<List<dynamic>?> refreshData() {
|
||||||
print("Calling Refresh Data");
|
print("Calling Refresh Data");
|
||||||
|
|
||||||
futureForex = fetchGetForex();
|
futureForex = fetchGetForex();
|
||||||
|
|
||||||
return futureForex.then((users) {
|
return futureForex!.then((users) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allForex = users;
|
allForex = users;
|
||||||
filteredForex = users;
|
filteredForex = users;
|
||||||
@ -557,6 +604,9 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureForex,
|
future: futureForex,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
if (futureForex == null) {
|
||||||
|
return const CircularProgressIndicator();
|
||||||
|
}
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasError ||
|
} else if (snapshot.hasError ||
|
||||||
@ -748,7 +798,8 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
color: forex['is_active'] == "1"
|
color:
|
||||||
|
forex['is_active'] == "1"
|
||||||
? Colors.green
|
? Colors.green
|
||||||
: Colors.grey,
|
: Colors.grey,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -23,7 +23,9 @@ class GroupList extends StatefulWidget {
|
|||||||
class _GroupListState extends State<GroupList> {
|
class _GroupListState extends State<GroupList> {
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
|
|
||||||
late Future<List<dynamic>> futureGroups;
|
// late Future<List<dynamic>> futureGroups;
|
||||||
|
|
||||||
|
Future<List<dynamic>>? futureGroups;
|
||||||
|
|
||||||
late Map<String, dynamic> groupSingleData;
|
late Map<String, dynamic> groupSingleData;
|
||||||
List<dynamic>? apiCountryData;
|
List<dynamic>? apiCountryData;
|
||||||
@ -45,21 +47,50 @@ class _GroupListState extends State<GroupList> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
// futureGroups = fetchGroups();
|
||||||
|
//
|
||||||
|
// futureGroups.then((object) {
|
||||||
|
// setState(() {
|
||||||
|
// allGroups = object;
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// loadInitialData();
|
||||||
|
// fetchGroups();
|
||||||
|
// loadAllGroups();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// futurePlans = fetchPlans();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
try {
|
||||||
futureGroups = fetchGroups();
|
futureGroups = fetchGroups();
|
||||||
|
|
||||||
futureGroups.then((object) {
|
futureGroups?.then((object) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allGroups = object;
|
allGroups = object;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
fetchGroups();
|
fetchGroups();
|
||||||
loadAllGroups();
|
loadAllGroups();
|
||||||
});
|
} catch (e) {
|
||||||
|
print("group : $e");
|
||||||
// futurePlans = fetchPlans();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadInitialData() async {
|
void loadInitialData() async {
|
||||||
@ -420,9 +451,14 @@ class _GroupListState extends State<GroupList> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
|
|
||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureGroups,
|
future: futureGroups,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
if (futureGroups == null) {
|
||||||
|
return const CircularProgressIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasError ||
|
} else if (snapshot.hasError ||
|
||||||
|
|||||||
@ -29,7 +29,8 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
GlobalKey<HotelsDataListState>();
|
GlobalKey<HotelsDataListState>();
|
||||||
|
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
late Future<List<dynamic>> futureHotels;
|
Future<List<dynamic>>? futureHotels;
|
||||||
|
// late Future<List<dynamic>> futureHotels;
|
||||||
|
|
||||||
late Map<String, dynamic> userSingleData;
|
late Map<String, dynamic> userSingleData;
|
||||||
List<dynamic>? apiCountryData;
|
List<dynamic>? apiCountryData;
|
||||||
@ -49,9 +50,38 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
// futureHotels = fetchGetHotels();
|
||||||
|
//
|
||||||
|
// futureHotels.then((objects) {
|
||||||
|
// setState(() {
|
||||||
|
// allHotels = objects;
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// fetchCountryList();
|
||||||
|
// loadInitialData();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// futurePlans = fetchPlans();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
try {
|
||||||
futureHotels = fetchGetHotels();
|
futureHotels = fetchGetHotels();
|
||||||
|
|
||||||
futureHotels.then((objects) {
|
futureHotels?.then((objects) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allHotels = objects;
|
allHotels = objects;
|
||||||
});
|
});
|
||||||
@ -61,8 +91,9 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
fetchCountryList();
|
fetchCountryList();
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
// futurePlans = fetchPlans();
|
print("group : $e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> refreshData() {
|
Future<List<dynamic>> refreshData() {
|
||||||
@ -70,7 +101,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
|
|
||||||
futureHotels = fetchGetHotels();
|
futureHotels = fetchGetHotels();
|
||||||
|
|
||||||
return futureHotels.then((objects) {
|
return futureHotels!.then((objects) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allHotels = objects;
|
allHotels = objects;
|
||||||
filteredHotels = objects;
|
filteredHotels = objects;
|
||||||
@ -454,6 +485,10 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureHotels,
|
future: futureHotels,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
if (futureHotels == null) {
|
||||||
|
return CircularProgressIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasError ||
|
} else if (snapshot.hasError ||
|
||||||
|
|||||||
@ -102,7 +102,29 @@ class TemplateState extends State<Template> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
//
|
||||||
|
// for (var field in dataHeader) {
|
||||||
|
// controllers[field] = TextEditingController();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// updateData();
|
||||||
|
// loadinitializeData();
|
||||||
|
// loadInitialData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
try {
|
||||||
for (var field in dataHeader) {
|
for (var field in dataHeader) {
|
||||||
controllers[field] = TextEditingController();
|
controllers[field] = TextEditingController();
|
||||||
}
|
}
|
||||||
@ -110,6 +132,9 @@ class TemplateState extends State<Template> {
|
|||||||
updateData();
|
updateData();
|
||||||
loadinitializeData();
|
loadinitializeData();
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
|
} catch (e) {
|
||||||
|
print("group : $e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -108,7 +108,29 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
//
|
||||||
|
// for (var field in dataHeader) {
|
||||||
|
// controllers[field] = TextEditingController();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// updateData();
|
||||||
|
// loadinitializeData();
|
||||||
|
// loadInitialData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
try {
|
||||||
for (var field in dataHeader) {
|
for (var field in dataHeader) {
|
||||||
controllers[field] = TextEditingController();
|
controllers[field] = TextEditingController();
|
||||||
}
|
}
|
||||||
@ -116,6 +138,9 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
updateData();
|
updateData();
|
||||||
loadinitializeData();
|
loadinitializeData();
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
|
} catch (e) {
|
||||||
|
print("group : $e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -28,7 +28,8 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
// GlobalKey<TemplatesListState>();
|
// GlobalKey<TemplatesListState>();
|
||||||
|
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
late Future<List<dynamic>> futureTemplates;
|
Future<List<dynamic>>? futureTemplates;
|
||||||
|
// late Future<List<dynamic>> futureTemplates;
|
||||||
|
|
||||||
late Map<String, dynamic> userSingleData;
|
late Map<String, dynamic> userSingleData;
|
||||||
List<dynamic>? apiCountryData;
|
List<dynamic>? apiCountryData;
|
||||||
@ -48,9 +49,38 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
// futureTemplates = fetchGetForex();
|
||||||
|
//
|
||||||
|
// futureTemplates.then((users) {
|
||||||
|
// setState(() {
|
||||||
|
// allTemplate = users;
|
||||||
|
// print("AlL tEMPLATESNIT - $allTemplate");
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// loadInitialData();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// futurePlans = fetchPlans();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
try {
|
||||||
futureTemplates = fetchGetForex();
|
futureTemplates = fetchGetForex();
|
||||||
|
|
||||||
futureTemplates.then((users) {
|
futureTemplates?.then((users) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allTemplate = users;
|
allTemplate = users;
|
||||||
print("AlL tEMPLATESNIT - $allTemplate");
|
print("AlL tEMPLATESNIT - $allTemplate");
|
||||||
@ -60,16 +90,17 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
// futurePlans = fetchPlans();
|
print("group : $e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> refreshData() {
|
Future<List<dynamic>?> refreshData() {
|
||||||
print("Calling Refresh Data");
|
print("Calling Refresh Data");
|
||||||
|
|
||||||
futureTemplates = fetchGetForex();
|
futureTemplates = fetchGetForex();
|
||||||
|
|
||||||
return futureTemplates.then((users) {
|
return futureTemplates!.then((users) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allTemplate = users;
|
allTemplate = users;
|
||||||
});
|
});
|
||||||
@ -82,11 +113,13 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
String? bodyStringColor = await getBodyColor();
|
String? bodyStringColor = await getBodyColor();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
layoutColor = layoutString != null
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
? Color(int.parse(layoutString))
|
? Color(int.parse(layoutString))
|
||||||
: Colors.redAccent;
|
: Colors.redAccent;
|
||||||
|
|
||||||
bodyColor = bodyStringColor != null
|
bodyColor =
|
||||||
|
bodyStringColor != null
|
||||||
? Color(int.parse(bodyStringColor))
|
? Color(int.parse(bodyStringColor))
|
||||||
: Colors.white;
|
: Colors.white;
|
||||||
});
|
});
|
||||||
@ -95,9 +128,12 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
String formatTemplateName(String input) {
|
String formatTemplateName(String input) {
|
||||||
return input
|
return input
|
||||||
.split('_') // split by underscore
|
.split('_') // split by underscore
|
||||||
.map((word) => word.isNotEmpty
|
.map(
|
||||||
|
(word) =>
|
||||||
|
word.isNotEmpty
|
||||||
? '${word[0].toUpperCase()}${word.substring(1)}'
|
? '${word[0].toUpperCase()}${word.substring(1)}'
|
||||||
: '')
|
: '',
|
||||||
|
)
|
||||||
.join(' ');
|
.join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +142,8 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
final List<dynamic> decoded = json.decode(raw);
|
final List<dynamic> decoded = json.decode(raw);
|
||||||
final List<String> values = decoded
|
final List<String> values =
|
||||||
|
decoded
|
||||||
.map((e) => e['value'].toString().replaceAll('%', ''))
|
.map((e) => e['value'].toString().replaceAll('%', ''))
|
||||||
.toList();
|
.toList();
|
||||||
return values.join(', ');
|
return values.join(', ');
|
||||||
@ -157,7 +194,10 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createTemplateData(
|
Future<void> createTemplateData(
|
||||||
Map<String, dynamic> userData, String userId, String newStatus) async {
|
Map<String, dynamic> userData,
|
||||||
|
String userId,
|
||||||
|
String newStatus,
|
||||||
|
) async {
|
||||||
final uri = Uri.parse('$apiUrl/api/users/update/$userId');
|
final uri = Uri.parse('$apiUrl/api/users/update/$userId');
|
||||||
|
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
@ -207,8 +247,11 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleToggleUserStatus(String userId, String currentStatus,
|
void handleToggleUserStatus(
|
||||||
Map<String, dynamic> userData) async {
|
String userId,
|
||||||
|
String currentStatus,
|
||||||
|
Map<String, dynamic> userData,
|
||||||
|
) async {
|
||||||
print("Toggling user status - $userId (Current: $currentStatus)");
|
print("Toggling user status - $userId (Current: $currentStatus)");
|
||||||
|
|
||||||
final String apiUrlData =
|
final String apiUrlData =
|
||||||
@ -264,7 +307,8 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
final lowerQuery = query.toLowerCase();
|
final lowerQuery = query.toLowerCase();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
filteredTemplates = allTemplate.where((user) {
|
filteredTemplates =
|
||||||
|
allTemplate.where((user) {
|
||||||
// Match template_name
|
// Match template_name
|
||||||
final templateName =
|
final templateName =
|
||||||
(user['template_name'] ?? '').toString().toLowerCase();
|
(user['template_name'] ?? '').toString().toLowerCase();
|
||||||
@ -277,13 +321,20 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
if (placeholderRaw != null && placeholderRaw is String) {
|
if (placeholderRaw != null && placeholderRaw is String) {
|
||||||
try {
|
try {
|
||||||
final List<dynamic> decoded = json.decode(placeholderRaw);
|
final List<dynamic> decoded = json.decode(placeholderRaw);
|
||||||
final List<String> placeholderValues = decoded
|
final List<String> placeholderValues =
|
||||||
.map((e) =>
|
decoded
|
||||||
e['value'].toString().replaceAll('%', '').toLowerCase())
|
.map(
|
||||||
|
(e) =>
|
||||||
|
e['value']
|
||||||
|
.toString()
|
||||||
|
.replaceAll('%', '')
|
||||||
|
.toLowerCase(),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
matchesPlaceholder =
|
matchesPlaceholder = placeholderValues.any(
|
||||||
placeholderValues.any((value) => value.contains(lowerQuery));
|
(value) => value.contains(lowerQuery),
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignore invalid placeholder format
|
// ignore invalid placeholder format
|
||||||
}
|
}
|
||||||
@ -298,8 +349,10 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(
|
||||||
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
builder: (context, sizingInfo) {
|
||||||
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Color(0xFFf5f5f5),
|
backgroundColor: Color(0xFFf5f5f5),
|
||||||
@ -308,11 +361,14 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
appBar: CustomAppBar(isDesktop: isDesktop),
|
appBar: CustomAppBar(isDesktop: isDesktop),
|
||||||
drawer: CustomDrawer(isDesktop: false),
|
drawer: CustomDrawer(isDesktop: false),
|
||||||
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),
|
||||||
@ -325,7 +381,8 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildGroupList(bool isDesktop) {
|
Widget buildGroupList(bool isDesktop) {
|
||||||
@ -353,7 +410,8 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
// ? EdgeInsets.all(10.0)
|
// ? EdgeInsets.all(10.0)
|
||||||
// : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0),
|
// : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0),
|
||||||
// padding: const EdgeInsets.all(10),
|
// padding: const EdgeInsets.all(10),
|
||||||
height: isDesktop
|
height:
|
||||||
|
isDesktop
|
||||||
? MediaQuery.of(context).size.height * 0.98
|
? MediaQuery.of(context).size.height * 0.98
|
||||||
: MediaQuery.of(context).size.height,
|
: MediaQuery.of(context).size.height,
|
||||||
|
|
||||||
@ -385,9 +443,7 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(
|
SizedBox(width: MediaQuery.of(context).size.width * 0.23),
|
||||||
width: MediaQuery.of(context).size.width * 0.23,
|
|
||||||
),
|
|
||||||
|
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
Container(
|
Container(
|
||||||
@ -399,7 +455,9 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
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),
|
||||||
@ -411,17 +469,19 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.grey.shade200, width: 0.5),
|
color: Colors.grey.shade200,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.grey.shade300, width: 1),
|
color: Colors.grey.shade300,
|
||||||
|
width: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
),
|
||||||
|
style: GoogleFonts.poppins(fontSize: 12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// SizedBox(width: 16),
|
// SizedBox(width: 16),
|
||||||
@ -464,10 +524,7 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
if (!isDesktop)
|
if (!isDesktop) SizedBox(height: 5),
|
||||||
SizedBox(
|
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
isDesktop
|
isDesktop
|
||||||
? SizedBox.shrink()
|
? SizedBox.shrink()
|
||||||
: Row(
|
: Row(
|
||||||
@ -482,7 +539,9 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
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),
|
||||||
@ -495,17 +554,18 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.grey.shade200,
|
color: Colors.grey.shade200,
|
||||||
width: 0.5),
|
width: 0.5,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.grey.shade300, width: 1),
|
color: Colors.grey.shade300,
|
||||||
|
width: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
),
|
||||||
|
style: GoogleFonts.poppins(fontSize: 12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// SizedBox(width: 16),
|
// SizedBox(width: 16),
|
||||||
@ -515,6 +575,9 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureTemplates,
|
future: futureTemplates,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
if (futureTemplates == null) {
|
||||||
|
return CircularProgressIndicator();
|
||||||
|
}
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasError ||
|
} else if (snapshot.hasError ||
|
||||||
@ -543,14 +606,17 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.grey),
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
Text(
|
||||||
"Please Create Templates",
|
"Please Create Templates",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 16, color: Colors.grey),
|
fontSize: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
@ -559,7 +625,8 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<dynamic> templates = filteredTemplates.isNotEmpty
|
List<dynamic> templates =
|
||||||
|
filteredTemplates.isNotEmpty
|
||||||
? filteredTemplates
|
? filteredTemplates
|
||||||
: allTemplate;
|
: allTemplate;
|
||||||
|
|
||||||
@ -573,25 +640,27 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
|
|
||||||
templates.sort((a, b) {
|
templates.sort((a, b) {
|
||||||
try {
|
try {
|
||||||
DateTime dateA =
|
DateTime dateA = DateTime.parse(
|
||||||
DateTime.parse(a['created_at'] ?? '2000-01-01');
|
a['created_at'] ?? '2000-01-01',
|
||||||
DateTime dateB =
|
);
|
||||||
DateTime.parse(b['created_at'] ?? '2000-01-01');
|
DateTime dateB = DateTime.parse(
|
||||||
|
b['created_at'] ?? '2000-01-01',
|
||||||
|
);
|
||||||
return dateB.compareTo(dateA);
|
return dateB.compareTo(dateA);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return 0; // If parsing fails, consider them equal
|
return 0; // If parsing fails, consider them equal
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
List paginatedTemplates = templates
|
List paginatedTemplates =
|
||||||
|
templates
|
||||||
.skip(currentPage * itemsPerPage)
|
.skip(currentPage * itemsPerPage)
|
||||||
.take(itemsPerPage)
|
.take(itemsPerPage)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
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),
|
||||||
@ -600,7 +669,9 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
columnSpacing: isDesktop ? 24.0 : 16.0,
|
columnSpacing: isDesktop ? 24.0 : 16.0,
|
||||||
border: TableBorder(
|
border: TableBorder(
|
||||||
horizontalInside: BorderSide(
|
horizontalInside: BorderSide(
|
||||||
width: 0.5, color: Colors.grey.shade200),
|
width: 0.5,
|
||||||
|
color: Colors.grey.shade200,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
columns: [
|
columns: [
|
||||||
DataColumn(
|
DataColumn(
|
||||||
@ -608,8 +679,10 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
'Template Name',
|
'Template Name',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w600),
|
fontWeight: FontWeight.w600,
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
// DataColumn(
|
// DataColumn(
|
||||||
// label: Text(
|
// label: Text(
|
||||||
// 'Attributes',
|
// 'Attributes',
|
||||||
@ -622,24 +695,33 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
'Actions',
|
'Actions',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w600),
|
fontWeight: FontWeight.w600,
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
rows: paginatedTemplates.map((forex) {
|
rows:
|
||||||
String forexId = forex['template_id']
|
paginatedTemplates.map((forex) {
|
||||||
|
String forexId =
|
||||||
|
forex['template_id']
|
||||||
.toString(); // Get user ID
|
.toString(); // Get user ID
|
||||||
bool isSelected = selectedUserId == forexId;
|
bool isSelected = selectedUserId == forexId;
|
||||||
|
|
||||||
return DataRow(cells: [
|
return DataRow(
|
||||||
DataCell(Text(
|
cells: [
|
||||||
|
DataCell(
|
||||||
|
Text(
|
||||||
// "${forex['template_name'] ?? ''}",
|
// "${forex['template_name'] ?? ''}",
|
||||||
formatTemplateName(
|
formatTemplateName(
|
||||||
forex['template_name'] ?? ''),
|
forex['template_name'] ?? '',
|
||||||
|
),
|
||||||
// Text("{forex['template_name'] ?? ''}",
|
// Text("{forex['template_name'] ?? ''}",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
))),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
// DataCell(Text(
|
// DataCell(Text(
|
||||||
// getPlaceholderNames(forex['placeholder']),
|
// getPlaceholderNames(forex['placeholder']),
|
||||||
// style: TextStyle(
|
// style: TextStyle(
|
||||||
@ -656,7 +738,8 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/IconsImg/edit.png',
|
'assets/images/IconsImg/edit.png',
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 15),
|
height: 15,
|
||||||
|
),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
// final userId = getUserId(user['user_id']);
|
// final userId = getUserId(user['user_id']);
|
||||||
// final usersData = await getUserDetails(userId);
|
// final usersData = await getUserDetails(userId);
|
||||||
@ -664,7 +747,8 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
|
|
||||||
// context.go('/template');
|
// context.go('/template');
|
||||||
final templateId = int.tryParse(
|
final templateId = int.tryParse(
|
||||||
forex['template_id'].toString());
|
forex['template_id'].toString(),
|
||||||
|
);
|
||||||
|
|
||||||
if (templateId != null) {
|
if (templateId != null) {
|
||||||
print("templateId -- $templateId");
|
print("templateId -- $templateId");
|
||||||
@ -672,16 +756,18 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
.getTemplateFind(templateId);
|
.getTemplateFind(templateId);
|
||||||
print("ForexId -- $data");
|
print("ForexId -- $data");
|
||||||
|
|
||||||
context.go('/template', extra: {
|
context.go(
|
||||||
'templateData': data,
|
'/template',
|
||||||
});
|
extra: {'templateData': data},
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
print("Invalid Forex ID");
|
print("Invalid Forex ID");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]);
|
],
|
||||||
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -696,7 +782,9 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
return Card(
|
return Card(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
margin: EdgeInsets.symmetric(
|
margin: EdgeInsets.symmetric(
|
||||||
horizontal: 12, vertical: 6),
|
horizontal: 12,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
@ -714,16 +802,18 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
Text(
|
Text(
|
||||||
// forex['template_name'] ?? 'N/A',
|
// forex['template_name'] ?? 'N/A',
|
||||||
formatTemplateName(
|
formatTemplateName(
|
||||||
forex['template_name'] ?? ''),
|
forex['template_name'] ?? '',
|
||||||
|
),
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Colors.black87,
|
color: Colors.black87,
|
||||||
fontWeight: FontWeight.w700),
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
UserActionsMenu(
|
UserActionsMenu(
|
||||||
user: forex,
|
user: forex,
|
||||||
getUserDetails: (id) =>
|
getUserDetails:
|
||||||
apiService.getSingleUser(id),
|
(id) => apiService.getSingleUser(id),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -764,7 +854,8 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: isDesktop
|
child:
|
||||||
|
isDesktop
|
||||||
? (searchController.text.isNotEmpty &&
|
? (searchController.text.isNotEmpty &&
|
||||||
filteredTemplates.isEmpty
|
filteredTemplates.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
@ -772,7 +863,8 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
"No matches found",
|
"No matches found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey),
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: SingleChildScrollView(
|
: SingleChildScrollView(
|
||||||
@ -786,11 +878,13 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
"No matches found",
|
"No matches found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey),
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: buildMobileCardView(
|
: buildMobileCardView(
|
||||||
paginatedTemplates)),
|
paginatedTemplates,
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
// Expanded(
|
// Expanded(
|
||||||
// child: isDesktop
|
// child: isDesktop
|
||||||
@ -821,9 +915,11 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
]),
|
],
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,13 +53,29 @@ class _OrgSetUpState extends State<OrgSetUp> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// loadAllServices();
|
||||||
|
// getOrganizationData();
|
||||||
|
// initializeData();
|
||||||
|
// loadInitialData();
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
loadAllServices();
|
loadAllServices();
|
||||||
getOrganizationData();
|
getOrganizationData();
|
||||||
initializeData();
|
initializeData();
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadInitialData() async {
|
void loadInitialData() async {
|
||||||
|
|||||||
@ -48,6 +48,20 @@ class _CreatePlansState extends State<CreatePlan> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
// loadInitialData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:core';
|
import 'dart:core';
|
||||||
|
import 'dart:html' as html;
|
||||||
|
|
||||||
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';
|
||||||
@ -12,6 +15,7 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||||||
|
|
||||||
import '../../routes/custom_appBar.dart';
|
import '../../routes/custom_appBar.dart';
|
||||||
import '../../routes/custom_drawer.dart';
|
import '../../routes/custom_drawer.dart';
|
||||||
|
import '../../routes/custom_router.dart';
|
||||||
import '../../services/apiService.dart';
|
import '../../services/apiService.dart';
|
||||||
import '../../utils/auth_utils.dart';
|
import '../../utils/auth_utils.dart';
|
||||||
import '../../utils/pagination.dart';
|
import '../../utils/pagination.dart';
|
||||||
@ -35,6 +39,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
|
|
||||||
String? userId;
|
String? userId;
|
||||||
String? orgId;
|
String? orgId;
|
||||||
|
String? roleUser;
|
||||||
String? token;
|
String? token;
|
||||||
String? TripPlanAction;
|
String? TripPlanAction;
|
||||||
|
|
||||||
@ -44,37 +49,115 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
List<Plan> allPlans = [];
|
List<Plan> allPlans = [];
|
||||||
List<Plan> filteredPlans = [];
|
List<Plan> filteredPlans = [];
|
||||||
TextEditingController searchController = TextEditingController();
|
TextEditingController searchController = TextEditingController();
|
||||||
|
String? location;
|
||||||
|
|
||||||
|
late bool _dialogShown = false;
|
||||||
|
late StreamSubscription<html.PopStateEvent> _popStateListener;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
// futurePlans = fetchPlans();
|
_checkAuthAndLoadData();
|
||||||
//
|
checkbackbutton();
|
||||||
// futurePlans.then((plans) {
|
|
||||||
// setState(() {
|
|
||||||
// allPlans = plans;
|
|
||||||
// filteredPlans = plans;
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
// getToken();
|
||||||
|
// initializeData();
|
||||||
|
// loadInitialData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkbackbutton() async {
|
||||||
|
roleUser = await getRoleUser();
|
||||||
|
print(roleUser);
|
||||||
|
if (roleUser == "User") {
|
||||||
|
print("user");
|
||||||
|
// Push a dummy state so back button triggers popstate instead of navigating
|
||||||
|
html.window.history.pushState(null, '', html.window.location.href);
|
||||||
|
|
||||||
|
_popStateListener = html.window.onPopState.listen((event) {
|
||||||
|
if (!_dialogShown && mounted) {
|
||||||
|
_showBackConfirmationDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-push to prevent leaving
|
||||||
|
html.window.history.pushState(null, '', html.window.location.href);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_popStateListener.cancel(); // ✅ Remove the browser popstate listener
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showBackConfirmationDialog() {
|
||||||
|
if (!mounted) return;
|
||||||
|
|
||||||
|
_dialogShown = true;
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => AlertDialog(
|
||||||
|
title: Text("Confirm"),
|
||||||
|
content: Text("Do you want to logout?"),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context); // Close dialog
|
||||||
|
_dialogShown = false;
|
||||||
|
},
|
||||||
|
child: Text("Cancel"),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.pop(context); // Close dialog
|
||||||
|
_dialogShown = false;
|
||||||
|
await _logoutAndRedirect(context);
|
||||||
|
},
|
||||||
|
child: Text("Logout"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _logoutAndRedirect(BuildContext context) async {
|
||||||
|
print("logue 0");
|
||||||
|
|
||||||
|
// Example: clear session or shared preferences
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.clear();
|
||||||
|
|
||||||
|
context.go("/");
|
||||||
|
|
||||||
|
print("logue 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (roleUser == "User") {
|
||||||
|
print("user");
|
||||||
|
|
||||||
|
// ✅ After login is successful and navigation completes:
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
checkbackbutton();
|
||||||
|
});
|
||||||
|
}
|
||||||
getToken();
|
getToken();
|
||||||
initializeData();
|
initializeData();
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
|
}
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
// initializeData();
|
|
||||||
// loadInitialData();
|
|
||||||
|
|
||||||
// futurePlans.then((plans) {
|
|
||||||
// setState(() {
|
|
||||||
// allPlans = plans;
|
|
||||||
// filteredPlans = plans;
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
|
|
||||||
// futurePlans = fetchPlans();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void refresh() {
|
void refresh() {
|
||||||
@ -135,6 +218,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
token = await getToken();
|
token = await getToken();
|
||||||
userId = await getUserId();
|
userId = await getUserId();
|
||||||
orgId = await getOrgId();
|
orgId = await getOrgId();
|
||||||
|
roleUser = await getRoleUser();
|
||||||
TripPlanAction = await getTripPlanAction();
|
TripPlanAction = await getTripPlanAction();
|
||||||
|
|
||||||
if (token == null || userId == null) {
|
if (token == null || userId == null) {
|
||||||
@ -325,13 +409,31 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _handleBackButton() {
|
||||||
|
// final location = GoRouterState.of(context).uri.toString();
|
||||||
|
|
||||||
|
print("location - $location");
|
||||||
|
if (location!.contains('/listPlan')) {
|
||||||
|
// Do nothing or show "Press again to exit" toast
|
||||||
|
print("Blocked back on /listPlan");
|
||||||
|
} else {
|
||||||
|
print("/listPlan ..");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(
|
return ResponsiveBuilder(
|
||||||
builder: (context, sizingInfo) {
|
builder: (context, sizingInfo) {
|
||||||
bool isDesktop =
|
bool isDesktop =
|
||||||
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
return Scaffold(
|
return PopScope(
|
||||||
|
canPop: false, // Allow back navigation only if not login screen
|
||||||
|
onPopInvokedWithResult: (didPop, result) {
|
||||||
|
if (didPop) return;
|
||||||
|
_handleBackButton(); // Show exit confirmation dialog
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
backgroundColor: Color(0xFFf5f5f5),
|
backgroundColor: Color(0xFFf5f5f5),
|
||||||
// appBar: isDesktop ? null : const CustomAppBar(title: 'Home'),
|
// appBar: isDesktop ? null : const CustomAppBar(title: 'Home'),
|
||||||
// drawer: isDesktop ? null : CustomDrawer(isDesktop: false),
|
// drawer: isDesktop ? null : CustomDrawer(isDesktop: false),
|
||||||
@ -356,6 +458,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -114,9 +114,40 @@ class _PolicyState extends State<Policy> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
// WidgetsFlutterBinding.ensureInitialized();
|
// WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// loadinitializeData();
|
||||||
|
//
|
||||||
|
// updateSelectedServices();
|
||||||
|
// updateData();
|
||||||
|
//
|
||||||
|
// loadInitialData();
|
||||||
|
//
|
||||||
|
// if (widget.policy != null) {
|
||||||
|
// final details = List<Map<String, dynamic>>.from(
|
||||||
|
// widget.policy!['policy_details'],
|
||||||
|
// );
|
||||||
|
// policyCriteriaKey.currentState?.loadPolicyDetails(details);
|
||||||
|
//
|
||||||
|
// policyCriteriaKey.currentState?.fetchTrainFlightClass();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
try {
|
||||||
loadinitializeData();
|
loadinitializeData();
|
||||||
|
|
||||||
updateSelectedServices();
|
updateSelectedServices();
|
||||||
@ -132,7 +163,9 @@ class _PolicyState extends State<Policy> {
|
|||||||
|
|
||||||
policyCriteriaKey.currentState?.fetchTrainFlightClass();
|
policyCriteriaKey.currentState?.fetchTrainFlightClass();
|
||||||
}
|
}
|
||||||
});
|
} catch (e) {
|
||||||
|
print("group : $e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadInitialData() async {
|
void loadInitialData() async {
|
||||||
|
|||||||
@ -21,7 +21,8 @@ class PolicyList extends StatefulWidget {
|
|||||||
|
|
||||||
class _PolicyListState extends State<PolicyList> {
|
class _PolicyListState extends State<PolicyList> {
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
late Future<List<dynamic>> futurePolicy;
|
// late Future<List<dynamic>> futurePolicy;
|
||||||
|
Future<List<dynamic>>? futurePolicy;
|
||||||
|
|
||||||
late Map<String, dynamic> userSingleData;
|
late Map<String, dynamic> userSingleData;
|
||||||
List<dynamic>? apiCountryData;
|
List<dynamic>? apiCountryData;
|
||||||
@ -43,20 +44,48 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
// futurePolicy = fetchPolicy();
|
||||||
|
//
|
||||||
|
// futurePolicy.then((object) {
|
||||||
|
// setState(() {
|
||||||
|
// allPolicy = object;
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// loadInitialData();
|
||||||
|
// fetchPolicy();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// futurePlans = fetchPlans();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
try {
|
||||||
futurePolicy = fetchPolicy();
|
futurePolicy = fetchPolicy();
|
||||||
|
|
||||||
futurePolicy.then((object) {
|
futurePolicy?.then((object) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allPolicy = object;
|
allPolicy = object;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
fetchPolicy();
|
fetchPolicy();
|
||||||
});
|
} catch (e) {
|
||||||
|
print("group : $e");
|
||||||
// futurePlans = fetchPlans();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadInitialData() async {
|
void loadInitialData() async {
|
||||||
@ -91,7 +120,7 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
futurePolicy = fetchPolicy(); // Re-fetch users after status update
|
futurePolicy = fetchPolicy(); // Re-fetch users after status update
|
||||||
|
|
||||||
futurePolicy.then((object) {
|
futurePolicy?.then((object) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allPolicy = object;
|
allPolicy = object;
|
||||||
});
|
});
|
||||||
@ -375,7 +404,7 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
List<dynamic> policyData = await futurePolicy;
|
List? policyData = await futurePolicy;
|
||||||
|
|
||||||
// Print the resolved value
|
// Print the resolved value
|
||||||
print("CREATELIAS - $policyData");
|
print("CREATELIAS - $policyData");
|
||||||
@ -454,6 +483,10 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futurePolicy,
|
future: futurePolicy,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
if (futurePolicy == null) {
|
||||||
|
return const CircularProgressIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasError ||
|
} else if (snapshot.hasError ||
|
||||||
|
|||||||
@ -28,7 +28,8 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
GlobalKey<TravellerListState>();
|
GlobalKey<TravellerListState>();
|
||||||
|
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
late Future<List<dynamic>> futureTraveller;
|
Future<List<dynamic>>? futureTraveller;
|
||||||
|
// late Future<List<dynamic>> futureTraveller;
|
||||||
|
|
||||||
late Map<String, dynamic> depSingleData;
|
late Map<String, dynamic> depSingleData;
|
||||||
String? selectedTravellerId;
|
String? selectedTravellerId;
|
||||||
@ -47,9 +48,37 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
// futureTraveller = fetchGetTraveller();
|
||||||
|
//
|
||||||
|
// futureTraveller.then((object) {
|
||||||
|
// setState(() {
|
||||||
|
// allTraveller = object;
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// loadInitialData();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// futurePlans = fetchPlans();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
try {
|
||||||
futureTraveller = fetchGetTraveller();
|
futureTraveller = fetchGetTraveller();
|
||||||
|
|
||||||
futureTraveller.then((object) {
|
futureTraveller?.then((object) {
|
||||||
setState(() {
|
setState(() {
|
||||||
allTraveller = object;
|
allTraveller = object;
|
||||||
});
|
});
|
||||||
@ -58,8 +87,9 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
// futurePlans = fetchPlans();
|
print("group : $e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadInitialData() async {
|
void loadInitialData() async {
|
||||||
@ -89,7 +119,7 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
|
|
||||||
futureTraveller = fetchGetTraveller();
|
futureTraveller = fetchGetTraveller();
|
||||||
|
|
||||||
return futureTraveller.then((object) {
|
return futureTraveller!.then((object) {
|
||||||
print("Calling Refresh Data $object");
|
print("Calling Refresh Data $object");
|
||||||
setState(() {
|
setState(() {
|
||||||
allTraveller = object;
|
allTraveller = object;
|
||||||
@ -147,14 +177,16 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
final lowerQuery = query.toLowerCase().trim();
|
final lowerQuery = query.toLowerCase().trim();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
filteredTraveller = allTraveller.where((object) {
|
filteredTraveller =
|
||||||
|
allTraveller.where((object) {
|
||||||
final travellerId = object['traveller_id']?.toLowerCase() ?? '';
|
final travellerId = object['traveller_id']?.toLowerCase() ?? '';
|
||||||
final firstName = object['first_name']?.toLowerCase() ?? '';
|
final firstName = object['first_name']?.toLowerCase() ?? '';
|
||||||
final lastName = object['last_name']?.toLowerCase() ?? '';
|
final lastName = object['last_name']?.toLowerCase() ?? '';
|
||||||
final fullName = '$firstName $lastName';
|
final fullName = '$firstName $lastName';
|
||||||
final mobile = object['mobile']?.toLowerCase() ?? '';
|
final mobile = object['mobile']?.toLowerCase() ?? '';
|
||||||
final email = object['email']?.toLowerCase() ?? '';
|
final email = object['email']?.toLowerCase() ?? '';
|
||||||
final isActiveStatus = object['is_active'] == "1" ? "active" : "inactive";
|
final isActiveStatus =
|
||||||
|
object['is_active'] == "1" ? "active" : "inactive";
|
||||||
|
|
||||||
return travellerId.contains(lowerQuery) ||
|
return travellerId.contains(lowerQuery) ||
|
||||||
firstName.contains(lowerQuery) ||
|
firstName.contains(lowerQuery) ||
|
||||||
@ -411,6 +443,10 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureTraveller,
|
future: futureTraveller,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
if (futureTraveller == null) {
|
||||||
|
return CircularProgressIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasError ||
|
} else if (snapshot.hasError ||
|
||||||
|
|||||||
@ -56,6 +56,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
String? orgId;
|
String? orgId;
|
||||||
String? userIdApi;
|
String? userIdApi;
|
||||||
|
|
||||||
|
bool isCheckingToken = false;
|
||||||
|
|
||||||
String? token;
|
String? token;
|
||||||
|
|
||||||
late bool isapiselectedUser = false;
|
late bool isapiselectedUser = false;
|
||||||
@ -152,10 +154,10 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
"date_of_birth": controllers["dob"]?.text,
|
"date_of_birth": controllers["dob"]?.text,
|
||||||
"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,
|
// "agent_supported_service_ids": selectedServiceIds,
|
||||||
"agent_supported_service_ids": selectedServiceIds,
|
"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,
|
||||||
@ -338,8 +340,161 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
// void initState() {
|
||||||
|
// super.initState();
|
||||||
|
// prepareForNewEntry();
|
||||||
|
// selectedTab = "personal";
|
||||||
|
//
|
||||||
|
// // WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
//
|
||||||
|
// // Step 1: Set 'reloaded' flag before page unload
|
||||||
|
// // html.window.onBeforeUnload.listen((event) {
|
||||||
|
// // html.window.localStorage['reloaded'] = 'true';
|
||||||
|
// // });
|
||||||
|
//
|
||||||
|
// apiCountryData = null;
|
||||||
|
// apiUserData = null;
|
||||||
|
// // apiselectedUser = null;
|
||||||
|
// apiCostData = null;
|
||||||
|
// apiRoleData = null;
|
||||||
|
//
|
||||||
|
// // Initialize controllers for each field
|
||||||
|
//
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
// // final wasReloaded = html.window.localStorage['reloaded'] == 'true';
|
||||||
|
// //
|
||||||
|
// // if (wasReloaded) {
|
||||||
|
// // html.window.localStorage.remove('reloaded'); // Clear it
|
||||||
|
// // context.go('/listUser'); // Navigate using go_router
|
||||||
|
// // }
|
||||||
|
//
|
||||||
|
// final extraData =
|
||||||
|
// GoRouterState.of(context).extra as Map<String, dynamic>?;
|
||||||
|
//
|
||||||
|
// if (extraData != null) {
|
||||||
|
// print("extraData: ${extraData['selectedUser']}");
|
||||||
|
//
|
||||||
|
// setState(() {
|
||||||
|
// // apiCountryData = extraData['apiCountryData'];
|
||||||
|
// // apiUserData = extraData['apiUserData'];
|
||||||
|
// //
|
||||||
|
// // userList = apiUserData ?? [];
|
||||||
|
// // userMap = {
|
||||||
|
// // for (var user in userList)
|
||||||
|
// // user['user_id'].toString(): "${user['first_name']} ${user['last_name']}"
|
||||||
|
// // };
|
||||||
|
// // userIdsApi = userMap.keys.toList();
|
||||||
|
//
|
||||||
|
// // Handle selectedUser as a Map (not a List)
|
||||||
|
// apiselectedUser =
|
||||||
|
// extraData['selectedUser']
|
||||||
|
// as Map<String, dynamic>?; // Cast it as a Map
|
||||||
|
// isViewMode = extraData['isViewMode'] ?? false;
|
||||||
|
// isEditProfile = extraData['isEditProfile'] ?? false;
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// print("selectedUser: $apiselectedUser");
|
||||||
|
//
|
||||||
|
// // Add another post-frame callback to check after setState
|
||||||
|
// // await Future.delayed(Duration(
|
||||||
|
// // milliseconds: 100)); // Optional delay to ensure UI has updated
|
||||||
|
// updateData();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// initializeData();
|
||||||
|
// fetchCountries();
|
||||||
|
// fetchDepartment();
|
||||||
|
// fetchUsers();
|
||||||
|
// fetchRoles();
|
||||||
|
// loadInitialData();
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// for (var field in dataHeader) {
|
||||||
|
// controllers[field] = TextEditingController();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
setState(() {
|
||||||
|
isCheckingToken = true;
|
||||||
|
});
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
_checkAuthAndLoadData(); // Safe place to use context
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
setState(() {
|
||||||
|
isCheckingToken = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
final String? token = await getToken();
|
||||||
|
if (!mounted) return;
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
context.go("/");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
isCheckingToken = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
prepareForNewEntry();
|
||||||
|
selectedTab = "personal";
|
||||||
|
|
||||||
|
apiCountryData = null;
|
||||||
|
apiUserData = null;
|
||||||
|
apiCostData = null;
|
||||||
|
apiRoleData = null;
|
||||||
|
|
||||||
|
for (var field in dataHeader) {
|
||||||
|
controllers[field] = TextEditingController();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ✅ Now this is safe here
|
||||||
|
try {
|
||||||
|
final extraData = GoRouterState.of(context).extra;
|
||||||
|
if (extraData != null && extraData is Map<String, dynamic>) {
|
||||||
|
setState(() {
|
||||||
|
apiselectedUser = extraData['selectedUser'] as Map<String, dynamic>?;
|
||||||
|
isViewMode = extraData['isViewMode'] ?? false;
|
||||||
|
isEditProfile = extraData['isEditProfile'] ?? false;
|
||||||
|
});
|
||||||
|
updateData();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("Router extra error: $e");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final async data fetches
|
||||||
|
initializeData();
|
||||||
|
fetchCountries();
|
||||||
|
fetchDepartment();
|
||||||
|
fetchUsers();
|
||||||
|
fetchRoles();
|
||||||
|
loadInitialData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData22() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (!mounted) return;
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
setState(() {
|
||||||
|
isCheckingToken = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (!mounted) return;
|
||||||
|
|
||||||
|
// Future.microtask(() {
|
||||||
prepareForNewEntry();
|
prepareForNewEntry();
|
||||||
selectedTab = "personal";
|
selectedTab = "personal";
|
||||||
|
|
||||||
@ -358,7 +513,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
|
|
||||||
// Initialize controllers for each field
|
// Initialize controllers for each field
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
// WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
// if (!mounted) return;
|
||||||
// final wasReloaded = html.window.localStorage['reloaded'] == 'true';
|
// final wasReloaded = html.window.localStorage['reloaded'] == 'true';
|
||||||
//
|
//
|
||||||
// if (wasReloaded) {
|
// if (wasReloaded) {
|
||||||
@ -405,11 +561,17 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
fetchUsers();
|
fetchUsers();
|
||||||
fetchRoles();
|
fetchRoles();
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
});
|
|
||||||
|
|
||||||
for (var field in dataHeader) {
|
for (var field in dataHeader) {
|
||||||
controllers[field] = TextEditingController();
|
controllers[field] = TextEditingController();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
isCheckingToken = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fetchCountries() async {
|
Future<void> fetchCountries() async {
|
||||||
@ -952,9 +1114,15 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
// ✅ Encode travel_details as a proper JSON string
|
// ✅ Encode travel_details as a proper JSON string
|
||||||
request.fields[key] = jsonEncode(value);
|
request.fields[key] = jsonEncode(value);
|
||||||
|
|
||||||
print("✅ Encoded travel_details: ${request.fields[key]}");
|
print("✅ Encoded travel_details1: ${request.fields[key]}");
|
||||||
|
} else if (key == 'agent_supported_service_ids' && value is List) {
|
||||||
|
request.fields[key] = jsonEncode(value);
|
||||||
|
print("✅ Encoded agent_supported_service_ids: ${request.fields[key]}");
|
||||||
} else {
|
} else {
|
||||||
|
// request.fields[key] = jsonEncode(value);
|
||||||
|
print("✅ Encoded travel_details:${key} - ${value}");
|
||||||
request.fields[key] = value.toString();
|
request.fields[key] = value.toString();
|
||||||
|
print("✅ Encoded travel_details2: ${request.fields[key]}");
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
@ -1043,6 +1211,10 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
bool isDesktop =
|
bool isDesktop =
|
||||||
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
|
if (isCheckingToken) {
|
||||||
|
return Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Color(0xFFf5f5f5),
|
backgroundColor: Color(0xFFf5f5f5),
|
||||||
// appBar: isDesktop ? null : const CustomAppBar(title: 'Create User '),
|
// appBar: isDesktop ? null : const CustomAppBar(title: 'Create User '),
|
||||||
|
|||||||
@ -452,8 +452,12 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
selectedServiceIds.add({"service_id": serviceId});
|
selectedServiceIds.add({"service_id": serviceId});
|
||||||
}
|
}
|
||||||
print("selectedServiceIdsUser --- $selectedServiceIds");
|
print("selectedServiceIdsUser --- $selectedServiceIds");
|
||||||
|
print(
|
||||||
|
"selectedServiceIdsUser1 --- ${json.encode(selectedServiceIds)}",
|
||||||
|
);
|
||||||
// Call the parent's callback
|
// Call the parent's callback
|
||||||
widget.onServiceIdsChanged!(selectedServiceIds);
|
widget.onServiceIdsChanged!(selectedServiceIds);
|
||||||
|
// widget.onServiceIdsChanged!(selectedServiceIds);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|||||||
@ -2377,6 +2377,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
|
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
width:
|
width:
|
||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
@ -2675,14 +2676,14 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Text(
|
return Text(
|
||||||
selectedItem['dropdown_value'] ?? 'Select Seat"',
|
selectedItem['dropdown_value'] ?? 'Select Seat',
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
items: seatOptionsInt,
|
items: seatOptionsInt,
|
||||||
selectedItem:
|
selectedItem:
|
||||||
selectedIntenationalSeat == null
|
selectedIntenationalSeat == null
|
||||||
? {"dropdown_value": "Select Seat"}
|
? null
|
||||||
: {"dropdown_value": selectedIntenationalSeat},
|
: {"dropdown_value": selectedIntenationalSeat},
|
||||||
onChanged:
|
onChanged:
|
||||||
widget.isViewMode
|
widget.isViewMode
|
||||||
@ -3673,7 +3674,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
" * I confirm my passport is valid for next 6 months",
|
" * confirm your passport is valid for next 6 months",
|
||||||
style: GoogleFonts.poppins(fontSize: 10),
|
style: GoogleFonts.poppins(fontSize: 10),
|
||||||
),
|
),
|
||||||
IconForVisa(),
|
IconForVisa(),
|
||||||
|
|||||||
@ -46,6 +46,31 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
// futureUsers = fetchUsers();
|
||||||
|
//
|
||||||
|
// futureUsers.then((users) {
|
||||||
|
// setState(() {
|
||||||
|
// allUsers = users;
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// fetchCountryList();
|
||||||
|
// loadInitialData();
|
||||||
|
// });
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
futureUsers = fetchUsers();
|
futureUsers = fetchUsers();
|
||||||
|
|
||||||
futureUsers.then((users) {
|
futureUsers.then((users) {
|
||||||
@ -53,13 +78,13 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
allUsers = users;
|
allUsers = users;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
fetchCountryList();
|
fetchCountryList();
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
});
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// fetchCountryList();
|
||||||
// futurePlans = fetchPlans();
|
// loadInitialData();
|
||||||
|
// });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadInitialData() async {
|
void loadInitialData() async {
|
||||||
@ -195,7 +220,6 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> handleUpload() async {
|
Future<void> handleUpload() async {
|
||||||
|
|
||||||
final String apiUrldata = '$apiUrl/api/user/userUpload'; // api
|
final String apiUrldata = '$apiUrl/api/user/userUpload'; // api
|
||||||
final String? token = await getToken(); // 2kn
|
final String? token = await getToken(); // 2kn
|
||||||
|
|
||||||
@ -227,7 +251,6 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (reader.readyState == html.FileReader.DONE) {
|
if (reader.readyState == html.FileReader.DONE) {
|
||||||
Uint8List? fileBytes = reader.result as Uint8List?;
|
Uint8List? fileBytes = reader.result as Uint8List?;
|
||||||
if (fileBytes != null) {
|
if (fileBytes != null) {
|
||||||
@ -253,15 +276,23 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
// formData.appendBlob('file', html.Blob([fileBytes]), fileName);
|
// formData.appendBlob('file', html.Blob([fileBytes]), fileName);
|
||||||
|
|
||||||
// Create a multipart request
|
// Create a multipart request
|
||||||
final request = http.MultipartRequest('POST', Uri.parse(apiUrldata));
|
final request = http.MultipartRequest(
|
||||||
|
'POST',
|
||||||
|
Uri.parse(apiUrldata),
|
||||||
|
);
|
||||||
|
|
||||||
// Attach the file to the request
|
// Attach the file to the request
|
||||||
// Set authorization token in headers
|
// Set authorization token in headers
|
||||||
request.headers['Authorization'] = 'Bearer $token';
|
request.headers['Authorization'] = 'Bearer $token';
|
||||||
// request.files.add(http.MultipartFile.fromBytes('file', fileBytes, filename: fileName));
|
// request.files.add(http.MultipartFile.fromBytes('file', fileBytes, filename: fileName));
|
||||||
|
|
||||||
request.files.add(http.MultipartFile.fromBytes( 'user_file', fileBytes, filename: 'user_file.xlsx' ));
|
request.files.add(
|
||||||
|
http.MultipartFile.fromBytes(
|
||||||
|
'user_file',
|
||||||
|
fileBytes,
|
||||||
|
filename: 'user_file.xlsx',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
print('request : $request');
|
print('request : $request');
|
||||||
// Send the request
|
// Send the request
|
||||||
@ -446,6 +477,10 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
// Refresh user list after update
|
// Refresh user list after update
|
||||||
void refreshUserList() {
|
void refreshUserList() {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
print("Search cleared 1");
|
||||||
|
searchController.clear(); // or wrap in setState if needed
|
||||||
|
print("Search cleared - ${searchController.text}");
|
||||||
|
filteredUsers = [];
|
||||||
futureUsers = fetchUsers();
|
futureUsers = fetchUsers();
|
||||||
|
|
||||||
futureUsers.then((users) {
|
futureUsers.then((users) {
|
||||||
@ -573,8 +608,9 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(width: MediaQuery.of(context).size.width * 0.15),
|
SizedBox(width: MediaQuery.of(context).size.width * 0.23),
|
||||||
|
|
||||||
|
// SizedBox(width: MediaQuery.of(context).size.width * 0.15),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
Container(
|
Container(
|
||||||
width: MediaQuery.of(context).size.width * 0.2,
|
width: MediaQuery.of(context).size.width * 0.2,
|
||||||
@ -616,27 +652,62 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
),
|
),
|
||||||
// SizedBox(width: 16),
|
// SizedBox(width: 16),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
OutlinedButton(
|
|
||||||
onPressed: () { apiService.getDownloadUserTemplateForUpload(); },
|
// OutlinedButton(
|
||||||
style: OutlinedButton.styleFrom(
|
// onPressed: () {
|
||||||
backgroundColor: Colors.white,
|
// apiService.getDownloadUserTemplateForUpload();
|
||||||
foregroundColor: Color(0xFF114D8B),
|
// },
|
||||||
side: BorderSide(color: Colors.white),
|
// style: OutlinedButton.styleFrom(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
// backgroundColor: Colors.white,
|
||||||
|
// foregroundColor: Color(0xFF114D8B),
|
||||||
|
// side: BorderSide(color: Colors.white),
|
||||||
|
// padding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 20,
|
||||||
|
// vertical: 16,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// child: Text("Sample Template Download"),
|
||||||
|
// ),
|
||||||
|
IconButton(
|
||||||
|
icon: Image.asset(
|
||||||
|
'assets/images/IconsImg/download.png',
|
||||||
|
width: 25,
|
||||||
|
height: 25,
|
||||||
),
|
),
|
||||||
child: Text("Sample Template Download"),
|
tooltip: 'Sample Template Download',
|
||||||
), Spacer(),
|
onPressed: () {
|
||||||
|
apiService.getDownloadUserTemplateForUpload();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
|
||||||
// Upload Button
|
// Upload Button
|
||||||
OutlinedButton(
|
// OutlinedButton(
|
||||||
onPressed: handleUpload,
|
// onPressed: handleUpload,
|
||||||
style: OutlinedButton.styleFrom(
|
// style: OutlinedButton.styleFrom(
|
||||||
backgroundColor: Colors.white,
|
// backgroundColor: Colors.white,
|
||||||
foregroundColor: Color(0xFF114D8B),
|
// foregroundColor: Color(0xFF114D8B),
|
||||||
side: BorderSide(color: Colors.white),
|
// side: BorderSide(color: Colors.white),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
// padding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 20,
|
||||||
|
// vertical: 16,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// child: Text("User Bulk Upload"),
|
||||||
|
// ),
|
||||||
|
IconButton(
|
||||||
|
icon: Image.asset(
|
||||||
|
'assets/images/IconsImg/upload.png',
|
||||||
|
width: 25,
|
||||||
|
height: 25,
|
||||||
),
|
),
|
||||||
child: Text("User Bulk Upload"),
|
tooltip: 'User Bulk Upload',
|
||||||
), Spacer(),
|
onPressed: () {
|
||||||
|
handleUpload();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
// Spacer(),
|
||||||
|
SizedBox(width: 5),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Color(0xFF114D8B),
|
backgroundColor: Color(0xFF114D8B),
|
||||||
|
|||||||
87
lib/app.dart
87
lib/app.dart
@ -2,7 +2,7 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
// import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'dart:html' as html;
|
import 'dart:html' as html;
|
||||||
import 'package:frontend/config/apiUrl.dart'; // 1 newly added
|
import 'package:frontend/config/apiUrl.dart'; // 1 newly added
|
||||||
import 'package:frontend/services/apiService.dart';
|
import 'package:frontend/services/apiService.dart';
|
||||||
@ -31,10 +31,12 @@ class _MyAppState extends State<MyApp> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// SemanticsBinding.instance.ensureSemantics(); // ✅ Safe here
|
SemanticsBinding.instance.ensureSemantics(); // ✅ Safe here
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
final uri = Uri.parse(html.window.location.href);
|
final uri = Uri.parse(html.window.location.href);
|
||||||
if (uri.path == '/authredirection' &&
|
print("URI - $uri");
|
||||||
|
|
||||||
|
if (uri.path == '/tstat/authredirection' &&
|
||||||
uri.queryParameters['code'] != null) {
|
uri.queryParameters['code'] != null) {
|
||||||
_authCode = uri.queryParameters['code'];
|
_authCode = uri.queryParameters['code'];
|
||||||
// _isAuthRedirect = true;
|
// _isAuthRedirect = true;
|
||||||
@ -51,7 +53,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> handleTokenUsingMS(authCode) async {
|
Future<void> handleTokenUsingMS(String? authCode) async {
|
||||||
if (authCode == null) return;
|
if (authCode == null) return;
|
||||||
|
|
||||||
final url = '$apiUrl/auth/verifyMSAuthUser?code=$authCode';
|
final url = '$apiUrl/auth/verifyMSAuthUser?code=$authCode';
|
||||||
@ -62,10 +64,11 @@ class _MyAppState extends State<MyApp> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final MS_Token = json.decode(response.body)['token'];
|
final responseBody = json.decode(response.body);
|
||||||
|
final MS_Token = responseBody['token'];
|
||||||
print("MS_Token - $MS_Token");
|
print("MS_Token - $MS_Token");
|
||||||
|
|
||||||
if (MS_Token != '') {
|
if (MS_Token != null && MS_Token != '') {
|
||||||
print('Microsoft - Token Available');
|
print('Microsoft - Token Available');
|
||||||
await storeUserDetails(MS_Token);
|
await storeUserDetails(MS_Token);
|
||||||
|
|
||||||
@ -79,20 +82,78 @@ class _MyAppState extends State<MyApp> {
|
|||||||
router.go('/listPlan');
|
router.go('/listPlan');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print('Microsoft - Token Not Available');
|
throw Exception('Token not found in response.');
|
||||||
throw Exception('Token not Founded');
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final errorMessage = json.decode(response.body)['message'];
|
// Handle 400/401/500 etc.
|
||||||
print(errorMessage);
|
String errorMsg;
|
||||||
throw Exception(errorMessage);
|
try {
|
||||||
|
final decoded = json.decode(response.body);
|
||||||
|
errorMsg = decoded['message'] ?? 'Unknown error';
|
||||||
|
} catch (_) {
|
||||||
|
errorMsg = response.body; // fallback to plain text
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
|
print("Error response: $errorMsg");
|
||||||
|
throw Exception("Authentication failed: $errorMsg");
|
||||||
|
}
|
||||||
|
} catch (e, stack) {
|
||||||
|
print("Caught error: $e");
|
||||||
router.go('/');
|
router.go('/');
|
||||||
print("Error: $e");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future<void> handleTokenUsingMS(authCode) async {
|
||||||
|
// if (authCode == null) return;
|
||||||
|
//
|
||||||
|
// final url = '$apiUrl/auth/verifyMSAuthUser?code=$authCode';
|
||||||
|
// try {
|
||||||
|
// final response = await http.get(
|
||||||
|
// Uri.parse(url),
|
||||||
|
// headers: {'Content-Type': 'application/json'},
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// if (response.statusCode == 200) {
|
||||||
|
// final MS_Token = json.decode(response.body)['token'];
|
||||||
|
// print("MS_Token - $MS_Token");
|
||||||
|
//
|
||||||
|
// if (MS_Token != '') {
|
||||||
|
// print('Microsoft - Token Available');
|
||||||
|
// await storeUserDetails(MS_Token);
|
||||||
|
//
|
||||||
|
// print("userRole - $userRole");
|
||||||
|
//
|
||||||
|
// if (userRole == "Travel Agent") {
|
||||||
|
// router.go('/listTravelAgentPlan');
|
||||||
|
// } else if (userRole == "Org Admin" || userRole == "Travel Admin") {
|
||||||
|
// router.go('/listAllPlan');
|
||||||
|
// } else {
|
||||||
|
// router.go('/listPlan');
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// print('Microsoft - Token Not Available');
|
||||||
|
// throw Exception('Token not Founded');
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // final errorMessage = json.decode(response.body)['message'];
|
||||||
|
// // print(errorMessage);
|
||||||
|
// // throw Exception(errorMessage);
|
||||||
|
//
|
||||||
|
// try {
|
||||||
|
// final errorMessage = json.decode(response.body)['message'];
|
||||||
|
// print(errorMessage);
|
||||||
|
// throw Exception(errorMessage);
|
||||||
|
// } catch (_) {
|
||||||
|
// print("Non-JSON error from server: ${response.body}");
|
||||||
|
// throw Exception("Authentication failed: ${response.body}");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } catch (e) {
|
||||||
|
// router.go('/');
|
||||||
|
// print("Error: $e");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
Future<void> storeUserDetails(String token) async {
|
Future<void> storeUserDetails(String token) async {
|
||||||
try {
|
try {
|
||||||
final parts = token.split('.');
|
final parts = token.split('.');
|
||||||
|
|||||||
@ -295,9 +295,26 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
|||||||
context.go('/');
|
context.go('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _handleBackButton() {
|
||||||
|
if (selectedTab == TabSelection.dashboard) {
|
||||||
|
// Do nothing or show "Press again to exit" toast
|
||||||
|
print("Blocked back on dashboard");
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
selectedTab = TabSelection.dashboard;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppBar(
|
return PopScope(
|
||||||
|
canPop: false, // Allow back navigation only if not login screen
|
||||||
|
onPopInvokedWithResult: (didPop, result) {
|
||||||
|
if (didPop) return;
|
||||||
|
_handleBackButton(); // Show exit confirmation dialog
|
||||||
|
},
|
||||||
|
child: AppBar(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
surfaceTintColor: Colors.white,
|
surfaceTintColor: Colors.white,
|
||||||
// elevation: 3,
|
// elevation: 3,
|
||||||
@ -331,7 +348,11 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
|||||||
width: 130, //130
|
width: 130, //130
|
||||||
height: 80, //80
|
height: 80, //80
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (
|
||||||
|
context,
|
||||||
|
error,
|
||||||
|
stackTrace,
|
||||||
|
) {
|
||||||
return const CircleAvatar(
|
return const CircleAvatar(
|
||||||
radius: 20,
|
radius: 20,
|
||||||
child: Icon(
|
child: Icon(
|
||||||
@ -372,7 +393,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
|||||||
'/StatusDashboard',
|
'/StatusDashboard',
|
||||||
),
|
),
|
||||||
layoutColor!,
|
layoutColor!,
|
||||||
isSelected: selectedTab == TabSelection.dashboard,
|
isSelected:
|
||||||
|
selectedTab == TabSelection.dashboard,
|
||||||
icon: Icons.dashboard,
|
icon: Icons.dashboard,
|
||||||
// icon: Icons.insights_outlined,
|
// icon: Icons.insights_outlined,
|
||||||
),
|
),
|
||||||
@ -388,7 +410,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
|||||||
'/listAllPlan',
|
'/listAllPlan',
|
||||||
),
|
),
|
||||||
layoutColor!,
|
layoutColor!,
|
||||||
isSelected: selectedTab == TabSelection.allTrips,
|
isSelected:
|
||||||
|
selectedTab == TabSelection.allTrips,
|
||||||
icon: Icons.format_list_bulleted_rounded,
|
icon: Icons.format_list_bulleted_rounded,
|
||||||
// icon: Icons.insights_outlined,
|
// icon: Icons.insights_outlined,
|
||||||
),
|
),
|
||||||
@ -407,7 +430,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
|||||||
icon: Icons.shopping_bag_outlined,
|
icon: Icons.shopping_bag_outlined,
|
||||||
// icon: Icons.request_page_outlined,
|
// 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",
|
||||||
() => handleTabChange(
|
() => handleTabChange(
|
||||||
@ -454,7 +478,10 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
|||||||
(context) => PopupMenuButton<String>(
|
(context) => PopupMenuButton<String>(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
offset: const Offset(0, 50), // 👈 shift it 50 pixels down
|
offset: const Offset(
|
||||||
|
0,
|
||||||
|
50,
|
||||||
|
), // 👈 shift it 50 pixels down
|
||||||
onSelected: (String value) {
|
onSelected: (String value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case '/OrganizationSettings':
|
case '/OrganizationSettings':
|
||||||
@ -509,7 +536,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
|||||||
menuItems
|
menuItems
|
||||||
.where(
|
.where(
|
||||||
(item) =>
|
(item) =>
|
||||||
item['value'] == '/CreateUserDetails' ||
|
item['value'] ==
|
||||||
|
'/CreateUserDetails' ||
|
||||||
item['value'] == '/logout',
|
item['value'] == '/logout',
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
@ -617,6 +645,7 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
|||||||
color: layoutColor, // Set the color of the bottom border
|
color: layoutColor, // Set the color of the bottom border
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -105,6 +105,8 @@ flutter:
|
|||||||
- assets/images/IconsImg/Frame.png
|
- assets/images/IconsImg/Frame.png
|
||||||
- assets/images/IconsImg/delete.png
|
- assets/images/IconsImg/delete.png
|
||||||
- assets/images/IconsImg/edit.png
|
- assets/images/IconsImg/edit.png
|
||||||
|
- assets/images/IconsImg/upload.png
|
||||||
|
- assets/images/IconsImg/download.png
|
||||||
- assets/images/IconsImg/planPdf_icon.png
|
- assets/images/IconsImg/planPdf_icon.png
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user