Merge branch 'main' of bitbucket.org:venbainformationtechnology/ts-tat into main

This commit is contained in:
VE10-Sanjeev 2025-05-22 12:26:36 +00:00
commit 3474a1dbca
4 changed files with 155 additions and 54 deletions

View File

@ -325,7 +325,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
Row( Row(
children: [ children: [
Text( Text(
'My Trips', 'Trips',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: isDesktop ? 16 : 14, fontSize: isDesktop ? 16 : 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,

View File

@ -12,6 +12,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_quill/flutter_quill_internal.dart'; import 'package:flutter_quill/flutter_quill_internal.dart';
import 'package:flutter_quill/quill_delta.dart'; import 'package:flutter_quill/quill_delta.dart';
import 'package:flutter_quill_extensions/flutter_quill_extensions.dart'; import 'package:flutter_quill_extensions/flutter_quill_extensions.dart';
import 'package:frontend/Screens/myTemplates/quill_delta_sample.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:responsive_builder/responsive_builder.dart'; import 'package:responsive_builder/responsive_builder.dart';
@ -22,11 +23,6 @@ import '../../services/apiService.dart';
import '../../utils/auth_utils.dart'; import '../../utils/auth_utils.dart';
import '../../widgets/custom_user_travel.dart'; import '../../widgets/custom_user_travel.dart';
/// Custom Embed Definition
class TimeStampEmbed {
static const String type = 'timeStamp';
}
class Template extends StatefulWidget { class Template extends StatefulWidget {
@override @override
TemplateState createState() => TemplateState(); TemplateState createState() => TemplateState();
@ -35,23 +31,27 @@ class Template extends StatefulWidget {
class TemplateState extends State<Template> { class TemplateState extends State<Template> {
final ApiService apiService = ApiService(); final ApiService apiService = ApiService();
final FocusNode _editorFocusNode = FocusNode();
final ScrollController _editorScrollController = ScrollController();
final QuillController _controller = QuillController.basic();
Color layoutColor = Colors.redAccent; Color layoutColor = Colors.redAccent;
Color bodyColor = Colors.white; Color bodyColor = Colors.white;
QuillController _controller = QuillController.basic();
final FocusNode _focusNode = FocusNode();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_controller = QuillController.basic(); // starts with empty document WidgetsBinding.instance.addPostFrameCallback((_) {
_editorFocusNode.requestFocus(); // Ensure focus is requested
});
// _controller.document = Document.fromJson(kQuillDefaultSample);
loadInitialData(); loadInitialData();
} }
@override @override
void dispose() { void dispose() {
_focusNode.dispose();
_controller.dispose(); _controller.dispose();
_editorScrollController.dispose();
_editorFocusNode.dispose();
super.dispose(); super.dispose();
} }
@ -185,30 +185,131 @@ class TemplateState extends State<Template> {
controller: _controller, controller: _controller,
config: QuillSimpleToolbarConfig( config: QuillSimpleToolbarConfig(
embedButtons: FlutterQuillEmbeds.toolbarButtons(), embedButtons: FlutterQuillEmbeds.toolbarButtons(),
showClipboardPaste: true,
customButtons: [
QuillToolbarCustomButtonOptions(
icon: const Icon(Icons.add_alarm_rounded),
onPressed: () {
_controller.document.insert(
_controller.selection.extentOffset,
TimeStampEmbed(
DateTime.now().toString(),
),
);
_controller.updateSelection(
TextSelection.collapsed(
offset: _controller.selection.extentOffset + 1,
),
ChangeSource.local,
);
},
),
],
buttonOptions: QuillSimpleToolbarButtonOptions(
base: QuillToolbarBaseButtonOptions(
afterButtonPressed: () {
final isDesktop = {
TargetPlatform.linux,
TargetPlatform.windows,
TargetPlatform.macOS
}.contains(defaultTargetPlatform);
if (isDesktop) {
_editorFocusNode.requestFocus();
}
},
),
linkStyle: QuillToolbarLinkStyleButtonOptions(
validateLink: (link) {
// Treats all links as valid. When launching the URL,
// `https://` is prefixed if the link is incomplete (e.g., `google.com` `https://google.com`)
// however this happens only within the editor.
return true;
},
),
),
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
// Modern editor // Modern editor
// Container( Container(
// height: 300, height: 300,
// decoration: BoxDecoration( decoration: BoxDecoration(
// border: Border.all(color: Colors.grey), border: Border.all(color: Colors.grey),
// borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
// ), ),
// child: QuillEditor( child: QuillEditor.basic(
// focusNode: _focusNode, focusNode: _editorFocusNode,
// scrollController: ScrollController(), scrollController: _editorScrollController,
// controller: _controller, controller: _controller,
// config: QuillEditorConfig( // readOnly: true,
// padding: const EdgeInsets.all(8), config: QuillEditorConfig(
// embedBuilders: FlutterQuillEmbeds.editorBuilders(), requestKeyboardFocusOnCheckListChanged: false,
// sharedConfigurations: const QuillSharedConfigurations( // readOnlyMouseCursor: SystemMouseCursors.text,
// locale: Locale('en'), enableScribble: true,
// ),
// ), padding: const EdgeInsets.all(8),
// ), placeholder: 'Type something...',
// ), embedBuilders: [
...FlutterQuillEmbeds.editorBuilders(
imageEmbedConfig: QuillEditorImageEmbedConfig(
imageProviderBuilder: (context, imageUrl) {
// https://pub.dev/packages/flutter_quill_extensions#-image-assets
if (imageUrl.startsWith('assets/')) {
return AssetImage(imageUrl);
}
return null;
},
),
videoEmbedConfig: QuillEditorVideoEmbedConfig(
customVideoBuilder: (videoUrl, readOnly) {
// To load YouTube videos https://github.com/singerdmx/flutter-quill/releases/tag/v10.8.0
return null;
},
),
),
TimeStampEmbedBuilder(),
],
),
),
),
],
);
}
}
class TimeStampEmbed extends Embeddable {
const TimeStampEmbed(
String value,
) : super(timeStampType, value);
static const String timeStampType = 'timeStamp';
static TimeStampEmbed fromDocument(Document document) =>
TimeStampEmbed(jsonEncode(document.toDelta().toJson()));
Document get document => Document.fromJson(jsonDecode(data));
}
class TimeStampEmbedBuilder extends EmbedBuilder {
@override
String get key => 'timeStamp';
@override
String toPlainText(Embed node) {
return node.value.data;
}
@override
Widget build(
BuildContext context,
EmbedContext embedContext,
) {
return Row(
children: [
const Icon(Icons.access_time_rounded),
Text(embedContext.node.value.data as String),
], ],
); );
} }

View File

@ -23,6 +23,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_quill/flutter_quill.dart' hide Text; import 'package:flutter_quill/flutter_quill.dart' hide Text;
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:go_router/go_router.dart';
import 'package:http/http.dart' as http; // 2 newly added import 'package:http/http.dart' as http; // 2 newly added
import 'dart:convert'; // 3 newly added import 'dart:convert'; // 3 newly added
@ -45,7 +46,7 @@ class _MyAppState extends State<MyApp> {
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' && 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;
@ -53,51 +54,50 @@ class _MyAppState extends State<MyApp> {
// print(">>> _isAuthRedirect: $_isAuthRedirect"); // print(">>> _isAuthRedirect: $_isAuthRedirect");
print(">>> Auth code found at startup: $_authCode"); print(">>> Auth code found at startup: $_authCode");
// You can now: WidgetsBinding.instance.addPostFrameCallback((_) {
// - call an API
// - store this in a Provider
// - or just pass it through GoRouter as usual
// if(_authCode){
handleTokenUsingMS(_authCode); handleTokenUsingMS(_authCode);
// }else{ });
// _isAuthRedirect = false;
// }
} }
} }
} }
Future<void> handleTokenUsingMS(_authCode) async { Future<void> handleTokenUsingMS(authCode) async {
if (authCode == null) return;
final url = '$apiUrl/auth/auth/verifyMSAuthUser?code=$_authCode'; final url = '$apiUrl/auth/verifyMSAuthUser?code=$authCode';
try { try {
final response = await http.get( final response = await http
Uri.parse(url), .get(Uri.parse(url), headers: {'Content-Type': 'application/json'});
headers: { 'Content-Type': 'application/json' }
);
if (response.statusCode == 200) { if (response.statusCode == 200) {
final MS_Token = json.decode(response.body)['token']; final MS_Token = json.decode(response.body)['token'];
print("MS_Token - $MS_Token"); print("MS_Token - $MS_Token");
if(MS_Token != ''){ if (MS_Token != '') {
print('Microsoft - Token Available'); print('Microsoft - Token Available');
await storeUserDetails(MS_Token); await storeUserDetails(MS_Token);
}else{
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'); print('Microsoft - Token Not Available');
throw Exception('Token not Founded'); throw Exception('Token not Founded');
} }
}else{ } else {
final errorMessage = json.decode(response.body)['message']; final errorMessage = json.decode(response.body)['message'];
print(errorMessage); print(errorMessage);
throw Exception(errorMessage); throw Exception(errorMessage);
} }
} } catch (e) {
catch (e) {
print("Error: $e"); print("Error: $e");
} }
} }
Future<void> storeUserDetails(String token) async { Future<void> storeUserDetails(String token) async {

View File

@ -277,7 +277,7 @@ class _CustomAppBarState extends State<CustomAppBar> {
if (userData?["role"] == "Travel Agent") if (userData?["role"] == "Travel Agent")
buildNavItem( buildNavItem(
"My Trips", "Trips",
() => handleTabChange( () => handleTabChange(
TabSelection.myTrips, '/listTravelAgentPlan'), TabSelection.myTrips, '/listTravelAgentPlan'),
layoutColor!, layoutColor!,