228 lines
7.5 KiB
Dart
228 lines
7.5 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'dart:html' as html;
|
|
import 'package:frontend/config/apiUrl.dart'; // 1 newly added
|
|
import 'package:frontend/services/apiService.dart';
|
|
|
|
import 'package:http/http.dart' as http;
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
import 'package:flutter_quill/flutter_quill.dart';
|
|
import 'package:frontend/routes/custom_router.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'Screens/myTemplates/templateTest.dart';
|
|
import 'package:fluttertoast/fluttertoast.dart';
|
|
|
|
class MyApp extends StatefulWidget {
|
|
const MyApp({super.key});
|
|
|
|
@override
|
|
State<MyApp> createState() => _MyAppState();
|
|
}
|
|
|
|
class _MyAppState extends State<MyApp> {
|
|
final ApiService apiService = ApiService();
|
|
String? _authCode;
|
|
String? userRole;
|
|
bool _isAuthRedirect = false; // Only true for Microsoft redirect
|
|
bool _isloading = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
// SemanticsBinding.instance
|
|
// .ensureSemantics(); // -only for testing uncomment, Otherwise Email Template wont allow to type
|
|
if (kIsWeb) {
|
|
final uri = Uri.parse(html.window.location.href);
|
|
print("URI - $uri");
|
|
final fragment = uri.fragment; // e.g., 'authredirection?code=xyz123'
|
|
|
|
print("Full URI: $uri");
|
|
print("Fragment: $fragment");
|
|
|
|
// Parse just the fragment safely
|
|
final fragmentParts = fragment.split('?');
|
|
print("fragmentParts: $fragmentParts");
|
|
final fragmentPath = fragmentParts.first;
|
|
print("fragmentPath: $fragmentPath");
|
|
final query = fragmentParts.length > 1 ? fragmentParts[1] : '';
|
|
|
|
print("query: $query");
|
|
|
|
final queryParams = Uri.splitQueryString(query);
|
|
print("queryParams: $queryParams");
|
|
|
|
final authCode = queryParams['code'];
|
|
|
|
if (fragmentPath == '/authredirection' && authCode != null) {
|
|
setState(() {
|
|
_isAuthRedirect = true; // Show loading screen ONLY for MS login
|
|
});
|
|
print(" Auth code detected at startup: $authCode");
|
|
// ✅ Immediately begin token handling
|
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
// handleTokenUsingMS(authCode);
|
|
// });
|
|
|
|
handleTokenUsingMS(authCode).then((_) {
|
|
// 🔥 No URL cleanup — leave it as is
|
|
setState(() {
|
|
_isAuthRedirect = false;
|
|
});
|
|
});
|
|
|
|
html.window.console.log("Auth code detected: $authCode");
|
|
} else {
|
|
html.window.console.log("No auth code found or wrong path.");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Note : Doing any change means just refer on login_widget.dart file - _login function. 24july2025
|
|
Future<void> handleTokenUsingMS(String authCode) async {
|
|
print("handleTokenUsingMS- $authCode");
|
|
try {
|
|
// final url = 'http://localhost:43627/tstat/auth/verifyMSAuthUser?code=$authCode';
|
|
final url = '$apiUrl/api/auth/verifyMSAuthUser?code=$authCode';
|
|
print("Microsoft BE URL - $url");
|
|
final response = await http.get(
|
|
Uri.parse(url),
|
|
headers: {'Content-Type': 'application/json'},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final responseBody = json.decode(response.body);
|
|
final token = responseBody['token'];
|
|
print("Microsoft_Token - $token");
|
|
setState(() {
|
|
_isloading = true;
|
|
});
|
|
|
|
if (token != null && token.isNotEmpty) {
|
|
print('Microsoft - Token Available');
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString('is_microsoft_user', 'true');
|
|
await storeUserDetails(token);
|
|
setState(() {
|
|
_isloading = false;
|
|
});
|
|
if (_isloading) {
|
|
const CircularProgressIndicator();
|
|
}
|
|
final userData = prefs.getString('user_data');
|
|
print("MS Userdata - $userData");
|
|
final orgDataString = prefs.getString('org_data');
|
|
print("MS orgdata - $orgDataString");
|
|
|
|
if (orgDataString != null && userData != null) {
|
|
Fluttertoast.showToast(
|
|
msg: "You're in!",
|
|
toastLength: Toast.LENGTH_SHORT,
|
|
gravity: ToastGravity.CENTER,
|
|
backgroundColor: Colors.green,
|
|
textColor: Colors.white,
|
|
fontSize: 16,
|
|
webBgColor: "linear-gradient(to right, #28a745, #28a745)",
|
|
);
|
|
|
|
print("Microsoft User Logged In Refer the Role - $userRole");
|
|
// Navigate based on role
|
|
if (userRole == "Travel Agent") {
|
|
router.go('/listTravelAgentPlan');
|
|
} else if (userRole == "Org Admin" || userRole == "Travel Admin") {
|
|
router.go('/StatusDashboard');
|
|
} else {
|
|
router.go('/listPlan');
|
|
}
|
|
}
|
|
} else {
|
|
throw Exception('Token missing in response.');
|
|
}
|
|
} else {
|
|
final error = json.decode(response.body)['message'] ?? 'Auth failed';
|
|
throw Exception(error);
|
|
}
|
|
} catch (e) {
|
|
Fluttertoast.showToast(
|
|
msg: "Login Failed: $e",
|
|
toastLength: Toast.LENGTH_SHORT,
|
|
gravity: ToastGravity.CENTER,
|
|
backgroundColor: Colors.red,
|
|
textColor: Colors.white,
|
|
fontSize: 16,
|
|
webBgColor: "linear-gradient(to right, #dc1c13, #dc1c13)",
|
|
);
|
|
router.go('/');
|
|
}
|
|
}
|
|
|
|
// Note : Doing any change means just refer on login_widget.dart file - storeUserDetails function. 24july2025
|
|
Future<void> storeUserDetails(String token) async {
|
|
try {
|
|
final parts = token.split('.');
|
|
if (parts.length != 3) throw Exception('Invalid token format');
|
|
|
|
final payload = json.decode(
|
|
utf8.decode(base64Url.decode(base64Url.normalize(parts[1]))),
|
|
);
|
|
|
|
final userData = payload['data'];
|
|
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString('auth_token', token);
|
|
await prefs.setString(
|
|
'user_data',
|
|
jsonEncode(userData),
|
|
); // Store full user data
|
|
|
|
if (userData != null) {
|
|
final pref = await SharedPreferences.getInstance();
|
|
await pref.setString('auth_token', token);
|
|
await pref.setString('user_data', jsonEncode(userData));
|
|
|
|
userRole = userData['role'];
|
|
|
|
print("MicroSoft UserData RAW - $userData");
|
|
print("MicroSoft UserData ROLE RAW - ${userData['role']}");
|
|
print("MicroSoft UserData ROLE FECTHED - $userRole");
|
|
}
|
|
print("MicroSoft Started");
|
|
await apiService.getOrganizationData(context);
|
|
print("MicroSoft end");
|
|
} catch (e) {
|
|
print('Error decoding token MS: $e');
|
|
router.go('/');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (_isAuthRedirect) {
|
|
return const MaterialApp(
|
|
home: Scaffold(body: Center(child: CircularProgressIndicator())),
|
|
);
|
|
}
|
|
|
|
return MaterialApp.router(
|
|
title: 'Trip Approval Tool',
|
|
debugShowCheckedModeBanner: false,
|
|
theme: ThemeData(
|
|
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
|
),
|
|
routerConfig: router, // <- your configured GoRouter or other RouterConfig
|
|
localizationsDelegates: const [
|
|
GlobalMaterialLocalizations.delegate,
|
|
GlobalCupertinoLocalizations.delegate,
|
|
GlobalWidgetsLocalizations.delegate,
|
|
FlutterQuillLocalizations.delegate,
|
|
],
|
|
supportedLocales: const [Locale('en'), Locale('es')],
|
|
);
|
|
}
|
|
}
|