From 6bb37994deaae352f0835e62a39c865979e8aa86 Mon Sep 17 00:00:00 2001 From: venbaittech Date: Wed, 18 Jun 2025 18:39:02 +0530 Subject: [PATCH] authentication --- assets/images/IconsImg/download.png | Bin 0 -> 741 bytes assets/images/IconsImg/upload.png | Bin 0 -> 729 bytes lib/Screens/allTrips/list_all_plans.dart | 39 +- lib/Screens/allTrips/travel_agent_list.dart | 42 +- lib/Screens/approvals/approval_list.dart | 34 +- .../authentication/login/login_widget.dart | 34 +- lib/Screens/costCenter/costCenter_list.dart | 60 +- lib/Screens/dashboard/status_dashboard.dart | 345 +++-- lib/Screens/department/department_list.dart | 60 +- lib/Screens/forex/forexDetails.dart | 2 +- lib/Screens/forex/forex_list.dart | 87 +- lib/Screens/group/groupList.dart | 56 +- lib/Screens/hotels/hotels_list.dart | 63 +- lib/Screens/myTemplates/template.dart | 35 +- lib/Screens/myTemplates/templateForex.dart | 35 +- lib/Screens/myTemplates/templatesList.dart | 1134 +++++++++-------- lib/Screens/organization/orgSetup.dart | 28 +- lib/Screens/plans/create_plans.dart | 14 + lib/Screens/plans/list_plans.dart | 193 ++- lib/Screens/policy/policy.dart | 37 +- lib/Screens/policy/policy_list.dart | 63 +- lib/Screens/traveller/travellerList.dart | 94 +- .../create_user/create_user.dart | 202 ++- .../create_user/personal_details.dart | 4 + .../create_user/traveller_details.dart | 7 +- lib/Screens/userManagement/user_List.dart | 141 +- lib/app.dart | 87 +- lib/routes/custom_appBar.dart | 639 +++++----- pubspec.yaml | 2 + 29 files changed, 2310 insertions(+), 1227 deletions(-) create mode 100644 assets/images/IconsImg/download.png create mode 100644 assets/images/IconsImg/upload.png diff --git a/assets/images/IconsImg/download.png b/assets/images/IconsImg/download.png new file mode 100644 index 0000000000000000000000000000000000000000..b75475a1eec40c5eee285fec8988861e6ccd1d37 GIT binary patch literal 741 zcmVPx%pGibPRA@u(mpgA0K@i7h_Ka`?x-$(`B*Z&3d;@~02tJdB8q&}q9yX3bYCzZ* z9-^WGTB^hs0u2Jb0S#}EcoYZ;>{9~5nDY%X5|PijcyIUiNQ~Cyd3N^yoB!7U5ECG#pZu#+G0OT)@ zAZ8wh0Lb6(%}s`&RKTR;fCh-~jdmcaR;F$t-9qszpj#+et&)w?rd>I~eDR_Sr?W8w-2K%pz4$944!|bc*%bgi@2o+@QoUB1 zmVuB0u-eyqyb<}!fxTiiFZbu%FFhD1vm9LBf;@zm^L11h}{5cdg%n_~s zz*zfjq$r|8jk)qXPjK)5QUE*%0vboan?2+7vS&;GON#$09OOVCo;m~u3RwW-f5 z<>Y_R9Jymy&G+9{!HKqkf%T;}vDmL5d;pc@Od*#BNTH}gDYXMa5P)Px%lSxEDRA@u(nK5tEKorN{bJBu@D%ll+N~oxa1&M`^P__9HFq<6!kaEk63xWs0#+UtY z5VRFvC}XgL2#bBucu0vg69thAz$x*}TLK8nu^SBFet0Zu z+U4)BAAE|sUZ^KdBVZh3D6wO8@&JAVz}az#5{Wr70Ni~sWqdwxMJAIy) { @override void 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(); loadInitialData(); - - // futurePlans.then((plans) { - // setState(() { - // allPlans = plans; - // filteredPlans = plans; - // }); - // }); - }); - // futurePlans = fetchPlans(); + } } void filterPlans(String query) { diff --git a/lib/Screens/allTrips/travel_agent_list.dart b/lib/Screens/allTrips/travel_agent_list.dart index ad48751..ef90d8e 100644 --- a/lib/Screens/allTrips/travel_agent_list.dart +++ b/lib/Screens/allTrips/travel_agent_list.dart @@ -48,23 +48,39 @@ class _TravelAgentListPlansState extends State { @override void initState() { super.initState(); - getToken(); - - WidgetsBinding.instance.addPostFrameCallback((_) { - initializeData(); - loadInitialData(); - - // futurePlans.then((plans) { - // setState(() { - // allPlans = plans; - // filteredPlans = plans; - // }); - // }); - }); + _checkAuthAndLoadData(); + // getToken(); + // + // 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; + } + getToken(); + initializeData(); + loadInitialData(); + } + void filterPlans(String query) { print("allPlans before filtering: $allPlans"); final lowerQuery = query.toLowerCase(); diff --git a/lib/Screens/approvals/approval_list.dart b/lib/Screens/approvals/approval_list.dart index a38714e..dfe2ec1 100644 --- a/lib/Screens/approvals/approval_list.dart +++ b/lib/Screens/approvals/approval_list.dart @@ -46,16 +46,32 @@ class _ApprovalListState extends State { @override void initState() { super.initState(); - getToken(); - - WidgetsBinding.instance.addPostFrameCallback((_) { - initializeData(); - loadInitialData(); - }); + _checkAuthAndLoadData(); + // getToken(); + // + // WidgetsBinding.instance.addPostFrameCallback((_) { + // initializeData(); + // 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; + } + getToken(); + initializeData(); + loadInitialData(); + } + void loadInitialData() async { String? layoutString = await getLayoutColor(); String? bodyStringColor = await getBodyColor(); @@ -776,9 +792,9 @@ class _ApprovalListState extends State { ), DataCell( Text( - plan.userName.isNotEmpty - ? plan.userName - : plan.travellerName, + plan.userName.isNotEmpty + ? plan.userName + : plan.travellerName, style: TextStyle( fontSize: 13, fontFamily: "Inter", diff --git a/lib/Screens/authentication/login/login_widget.dart b/lib/Screens/authentication/login/login_widget.dart index c61d2a4..e67651c 100644 --- a/lib/Screens/authentication/login/login_widget.dart +++ b/lib/Screens/authentication/login/login_widget.dart @@ -135,16 +135,10 @@ class _LoginWidgetState extends State { timeInSecForIosWeb: 2, backgroundColor: Colors.green, 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") { context.go('/listTravelAgentPlan'); } else if (userRole == "Org Admin" || userRole == "Travel Admin") { @@ -225,12 +219,6 @@ class _LoginWidgetState extends State { _showOtpResetFields = true; // _clearAllFields(); }); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // content: Text("OTP sent to your email"), - // backgroundColor: Colors.green, - // ), - // ); Fluttertoast.showToast( msg: "OTP sent to your email", @@ -240,18 +228,10 @@ class _LoginWidgetState extends State { backgroundColor: Colors.green, textColor: Colors.white, fontSize: 16.0, + webBgColor: "linear-gradient(to right, #28a745, #28a745)", ); } else { print(response); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // content: Text( - // "${jsonDecode(response.body)['messages']['error']}", - // ), - // - // backgroundColor: Colors.red, - // ), - // ); Fluttertoast.showToast( msg: "${jsonDecode(response.body)['messages']['error']}", @@ -304,12 +284,6 @@ class _LoginWidgetState extends State { _showOtpResetFields = false; _clearAllFields(); }); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // content: Text("Password reset successfully"), - // backgroundColor: Colors.green, - // ), - // ); Fluttertoast.showToast( msg: "Password reset successfully", @@ -319,6 +293,7 @@ class _LoginWidgetState extends State { backgroundColor: Colors.green, textColor: Colors.white, fontSize: 16.0, + webBgColor: "linear-gradient(to right, #28a745, #28a745)", ); } else { print('23'); @@ -521,6 +496,7 @@ class _LoginWidgetState extends State { fontSize: widget.isDesktop ? 20 : 18, fontWeight: FontWeight.w700, color: Colors.green, + // color: Color(0xFF212121), ), ), diff --git a/lib/Screens/costCenter/costCenter_list.dart b/lib/Screens/costCenter/costCenter_list.dart index ecef9be..c653e05 100644 --- a/lib/Screens/costCenter/costCenter_list.dart +++ b/lib/Screens/costCenter/costCenter_list.dart @@ -28,7 +28,8 @@ class CostCenterListState extends State { GlobalKey(); final ApiService apiService = ApiService(); - late Future> futureCostCenter; + Future>? futureCostCenter; + // late Future> futureCostCenter; late Map depSingleData; String? selectedCostCenterId; @@ -47,21 +48,50 @@ class CostCenterListState extends State { @override void initState() { super.initState(); - futureCostCenter = fetchGetCostCenter(); - - futureCostCenter.then((object) { - setState(() { - allCostCenter = object; - }); - }); - - WidgetsBinding.instance.addPostFrameCallback((_) { - loadInitialData(); - }); + _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?.then((object) { + setState(() { + allCostCenter = object; + }); + }); + + WidgetsBinding.instance.addPostFrameCallback((_) { + loadInitialData(); + }); + } catch (e) { + print("group : $e"); + } + } + void loadInitialData() async { String? layoutString = await getLayoutColor(); String? bodyStringColor = await getBodyColor(); @@ -89,7 +119,7 @@ class CostCenterListState extends State { futureCostCenter = fetchGetCostCenter(); - return futureCostCenter.then((object) { + return futureCostCenter!.then((object) { print("Calling Refresh Data $object"); setState(() { allCostCenter = object; @@ -406,6 +436,10 @@ class CostCenterListState extends State { FutureBuilder>( future: futureCostCenter, builder: (context, snapshot) { + if (futureCostCenter == null) { + return CircularProgressIndicator(); + } + if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError || diff --git a/lib/Screens/dashboard/status_dashboard.dart b/lib/Screens/dashboard/status_dashboard.dart index 9ec8522..9cbe615 100644 --- a/lib/Screens/dashboard/status_dashboard.dart +++ b/lib/Screens/dashboard/status_dashboard.dart @@ -1,7 +1,11 @@ +import 'dart:async'; import 'dart:convert'; +import 'dart:io'; +import 'dart:html' as html; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:frontend/routes/custom_router.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; @@ -16,7 +20,6 @@ import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; class StatusDashboard extends StatefulWidget { - const StatusDashboard({super.key}); @override @@ -24,15 +27,101 @@ class StatusDashboard extends StatefulWidget { } class StatusDashboardState extends State { - Map? apiData; String? organizationId; + late bool _dialogShown = false; + late StreamSubscription _popStateListener; @override void 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 _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 loadDashboardData() async { @@ -66,13 +155,11 @@ class StatusDashboardState extends State { return null; } - - Future> fetchStatusDashboard() async { - - + Future> fetchStatusDashboard() async { 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(); print("Fetch StatusDashboard -- 2KN Here : $token"); @@ -132,17 +219,18 @@ class StatusDashboardState extends State { } } - @override Widget build(BuildContext context) { final typeBasedCount = List>.from( - (apiData?['data']?['typeBasedCount']) ?? []); + (apiData?['data']?['typeBasedCount']) ?? [], + ); print("apiData - => $apiData"); print("typeBasedCount => $typeBasedCount"); final statusBasedCount = List>.from( - (apiData?['data']?['statusBasedCount']) ?? []); + (apiData?['data']?['statusBasedCount']) ?? [], + ); print("statusBasedCount - => $statusBasedCount"); // 👇 Local function to create the card widget Widget buildInfoCard(String title, int count, double width) { @@ -159,14 +247,24 @@ class StatusDashboardState extends State { child: Column( mainAxisSize: MainAxisSize.min, 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), Text( title, textAlign: TextAlign.center, style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: (title == 'Domestic' || title == 'International') ? 16 : 14, + fontWeight: FontWeight.w600, + fontSize: + (title == 'Domestic' || title == 'International') + ? 16 + : 14, ), ), const SizedBox(height: 8), @@ -182,95 +280,144 @@ class StatusDashboardState extends State { ), ), ); - - - } - return ResponsiveBuilder(builder: (context, sizingInfo) { - bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; + void _handleBackButton() { + final location = GoRouterState.of(context).uri.toString(); - return Scaffold( - backgroundColor: const Color(0xFFf5f5f5), - appBar: CustomAppBar(isDesktop: isDesktop), - drawer: CustomDrawer(isDesktop: false), - body: Padding( - padding: isDesktop - ? EdgeInsets.symmetric( - horizontal: MediaQuery.of(context).size.width * 0.1, // 30% of screen width as horizontal padding - vertical: 10, // 5% of screen height as vertical padding + 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), + appBar: CustomAppBar(isDesktop: isDesktop), + drawer: CustomDrawer(isDesktop: false), + body: Padding( + padding: + isDesktop + ? EdgeInsets.symmetric( + horizontal: + MediaQuery.of(context).size.width * + 0.1, // 30% of screen width as horizontal padding + vertical: 10, // 5% of screen height as vertical padding ) - : EdgeInsets.all(0), - child : LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( // Only needed if child layout depends on height - child: Container( - decoration: BoxDecoration( - color: isDesktop ? Colors.white : const Color(0xFFFCFCFC), - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(30.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Wrap( - spacing: 10, - runSpacing: 10, - children: typeBasedCount.map((item) { - double cardWidth = isDesktop - ? (MediaQuery.of(context).size.width * 0.75 - 10) / 2 // 80% width padding adjusted - : MediaQuery.of(context).size.width - 24; // full width with padding + : EdgeInsets.all(0), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + // Only needed if child layout depends on height + child: Container( + decoration: BoxDecoration( + color: + isDesktop + ? Colors.white + : const Color(0xFFFCFCFC), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(30.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Wrap( + spacing: 10, + runSpacing: 10, + children: + typeBasedCount.map((item) { + double cardWidth = + 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( - width: cardWidth, - child: buildInfoCard(item['value'], item['count'], cardWidth), - ); - }).toList(), - ), - const SizedBox(height: 20), - Wrap( - spacing: 10, - runSpacing: 10, - children: statusBasedCount.map((item) { - double cardWidth = 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( - width: cardWidth, - child: buildInfoCard(item['value'], item['count'], cardWidth), - ); - }).toList(), - ), - - ], - ), - ), - ), - ], - ), - ), - ), - ), - ); - }, - ) - - - - ), - ); - }); + return SizedBox( + width: cardWidth, + child: buildInfoCard( + item['value'], + item['count'], + cardWidth, + ), + ); + }).toList(), + ), + const SizedBox(height: 20), + Wrap( + spacing: 10, + runSpacing: 10, + children: + statusBasedCount.map((item) { + double cardWidth = + 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( + width: cardWidth, + child: buildInfoCard( + item['value'], + item['count'], + cardWidth, + ), + ); + }).toList(), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ); + }, + ), + ), + ), + ); + }, + ); } - -} \ No newline at end of file +} diff --git a/lib/Screens/department/department_list.dart b/lib/Screens/department/department_list.dart index 9eb112e..5d62bf1 100644 --- a/lib/Screens/department/department_list.dart +++ b/lib/Screens/department/department_list.dart @@ -28,7 +28,8 @@ class DepartmentListState extends State { GlobalKey(); final ApiService apiService = ApiService(); - late Future> futureDepartment; + // late Future> futureDepartment; + Future>? futureDepartment; late Map depSingleData; String? selectedDepartmentId; @@ -47,21 +48,50 @@ class DepartmentListState extends State { @override void initState() { super.initState(); - futureDepartment = fetchGetDepartment(); - - futureDepartment.then((object) { - setState(() { - allDepartment = object; - }); - }); - - WidgetsBinding.instance.addPostFrameCallback((_) { - loadInitialData(); - }); + _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?.then((object) { + setState(() { + allDepartment = object; + }); + }); + + WidgetsBinding.instance.addPostFrameCallback((_) { + loadInitialData(); + }); + } catch (e) { + print("group : $e"); + } + } + void loadInitialData() async { String? layoutString = await getLayoutColor(); String? bodyStringColor = await getBodyColor(); @@ -89,7 +119,7 @@ class DepartmentListState extends State { futureDepartment = fetchGetDepartment(); - return futureDepartment.then((object) { + return futureDepartment!.then((object) { print("Calling Refresh Data $object"); setState(() { allDepartment = object; @@ -405,6 +435,10 @@ class DepartmentListState extends State { FutureBuilder>( future: futureDepartment, builder: (context, snapshot) { + if (futureDepartment == null) { + CircularProgressIndicator(); + } + if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError || diff --git a/lib/Screens/forex/forexDetails.dart b/lib/Screens/forex/forexDetails.dart index bed6d4f..a25e338 100644 --- a/lib/Screens/forex/forexDetails.dart +++ b/lib/Screens/forex/forexDetails.dart @@ -14,7 +14,7 @@ import '../../widgets/custom_text_forex.dart'; import 'forex_list.dart'; class ForexData extends StatefulWidget { - final Future> Function() fetchGetForex; + final Future?> Function() fetchGetForex; final bool isDesktop; final Color? layoutColor; diff --git a/lib/Screens/forex/forex_list.dart b/lib/Screens/forex/forex_list.dart index 0169cbd..cbaf57c 100644 --- a/lib/Screens/forex/forex_list.dart +++ b/lib/Screens/forex/forex_list.dart @@ -29,7 +29,8 @@ class ForexDataListState extends State { GlobalKey(); final ApiService apiService = ApiService(); - late Future> futureForex; + // late Future> futureForex; + Future>? futureForex; late Map userSingleData; List? apiCountryData; @@ -49,28 +50,74 @@ class ForexDataListState extends State { @override void initState() { super.initState(); - futureForex = fetchGetForex(); - - futureForex.then((users) { - setState(() { - allForex = users; - }); - }); - - WidgetsBinding.instance.addPostFrameCallback((_) { - fetchCountryList(); - loadInitialData(); - }); + _checkAuthAndLoadData(); + // futureForex = fetchGetForex(); + // + // futureForex.then((users) { + // setState(() { + // allForex = users; + // }); + // }); + // + // WidgetsBinding.instance.addPostFrameCallback((_) { + // fetchCountryList(); + // loadInitialData(); + // }); // futurePlans = fetchPlans(); } - Future> refreshData() { + 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?.then((users) { + setState(() { + allForex = users; + }); + }); + + WidgetsBinding.instance.addPostFrameCallback((_) { + fetchCountryList(); + loadInitialData(); + }); + } catch (e) { + print("group : $e"); + } + } + + // Future?> 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?> refreshData() { print("Calling Refresh Data"); futureForex = fetchGetForex(); - return futureForex.then((users) { + return futureForex!.then((users) { setState(() { allForex = users; filteredForex = users; @@ -557,6 +604,9 @@ class ForexDataListState extends State { FutureBuilder>( future: futureForex, builder: (context, snapshot) { + if (futureForex == null) { + return const CircularProgressIndicator(); + } if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError || @@ -748,9 +798,10 @@ class ForexDataListState extends State { style: TextStyle( fontSize: 13, fontFamily: "Inter", - color: forex['is_active'] == "1" - ? Colors.green - : Colors.grey, + color: + forex['is_active'] == "1" + ? Colors.green + : Colors.grey, ), softWrap: true, overflow: TextOverflow.ellipsis, diff --git a/lib/Screens/group/groupList.dart b/lib/Screens/group/groupList.dart index ade5b54..10ce46d 100644 --- a/lib/Screens/group/groupList.dart +++ b/lib/Screens/group/groupList.dart @@ -23,7 +23,9 @@ class GroupList extends StatefulWidget { class _GroupListState extends State { final ApiService apiService = ApiService(); - late Future> futureGroups; + // late Future> futureGroups; + + Future>? futureGroups; late Map groupSingleData; List? apiCountryData; @@ -45,21 +47,50 @@ class _GroupListState extends State { @override void initState() { super.initState(); - futureGroups = fetchGroups(); + _checkAuthAndLoadData(); + // futureGroups = fetchGroups(); + // + // futureGroups.then((object) { + // setState(() { + // allGroups = object; + // }); + // }); + // + // WidgetsBinding.instance.addPostFrameCallback((_) { + // loadInitialData(); + // fetchGroups(); + // loadAllGroups(); + // }); - futureGroups.then((object) { - setState(() { - allGroups = object; + // 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?.then((object) { + setState(() { + allGroups = object; + }); }); - }); - WidgetsBinding.instance.addPostFrameCallback((_) { loadInitialData(); fetchGroups(); loadAllGroups(); - }); - - // futurePlans = fetchPlans(); + } catch (e) { + print("group : $e"); + } } void loadInitialData() async { @@ -420,9 +451,14 @@ class _GroupListState extends State { ], ), const SizedBox(height: 10), + FutureBuilder>( future: futureGroups, builder: (context, snapshot) { + if (futureGroups == null) { + return const CircularProgressIndicator(); + } + if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError || diff --git a/lib/Screens/hotels/hotels_list.dart b/lib/Screens/hotels/hotels_list.dart index 48731af..270bae5 100644 --- a/lib/Screens/hotels/hotels_list.dart +++ b/lib/Screens/hotels/hotels_list.dart @@ -29,7 +29,8 @@ class HotelsDataListState extends State { GlobalKey(); final ApiService apiService = ApiService(); - late Future> futureHotels; + Future>? futureHotels; + // late Future> futureHotels; late Map userSingleData; List? apiCountryData; @@ -49,28 +50,58 @@ class HotelsDataListState extends State { @override void initState() { super.initState(); - futureHotels = fetchGetHotels(); - - futureHotels.then((objects) { - setState(() { - allHotels = objects; - }); - }); - - WidgetsBinding.instance.addPostFrameCallback((_) { - fetchCountryList(); - loadInitialData(); - }); + _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?.then((objects) { + setState(() { + allHotels = objects; + }); + }); + + WidgetsBinding.instance.addPostFrameCallback((_) { + fetchCountryList(); + loadInitialData(); + }); + } catch (e) { + print("group : $e"); + } + } + Future> refreshData() { print("Calling Refresh Data"); futureHotels = fetchGetHotels(); - return futureHotels.then((objects) { + return futureHotels!.then((objects) { setState(() { allHotels = objects; filteredHotels = objects; @@ -454,6 +485,10 @@ class HotelsDataListState extends State { FutureBuilder>( future: futureHotels, builder: (context, snapshot) { + if (futureHotels == null) { + return CircularProgressIndicator(); + } + if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError || diff --git a/lib/Screens/myTemplates/template.dart b/lib/Screens/myTemplates/template.dart index 6a34d81..5e0f4bd 100644 --- a/lib/Screens/myTemplates/template.dart +++ b/lib/Screens/myTemplates/template.dart @@ -102,14 +102,39 @@ class TemplateState extends State