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(
children: [
Text(
'My Trips',
'Trips',
style: GoogleFonts.poppins(
fontSize: isDesktop ? 16 : 14,
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/quill_delta.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:path/path.dart' as path;
import 'package:responsive_builder/responsive_builder.dart';
@ -22,11 +23,6 @@ import '../../services/apiService.dart';
import '../../utils/auth_utils.dart';
import '../../widgets/custom_user_travel.dart';
/// Custom Embed Definition
class TimeStampEmbed {
static const String type = 'timeStamp';
}
class Template extends StatefulWidget {
@override
TemplateState createState() => TemplateState();
@ -35,23 +31,27 @@ class Template extends StatefulWidget {
class TemplateState extends State<Template> {
final ApiService apiService = ApiService();
final FocusNode _editorFocusNode = FocusNode();
final ScrollController _editorScrollController = ScrollController();
final QuillController _controller = QuillController.basic();
Color layoutColor = Colors.redAccent;
Color bodyColor = Colors.white;
QuillController _controller = QuillController.basic();
final FocusNode _focusNode = FocusNode();
@override
void 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();
}
@override
void dispose() {
_focusNode.dispose();
_controller.dispose();
_editorScrollController.dispose();
_editorFocusNode.dispose();
super.dispose();
}
@ -185,30 +185,131 @@ class TemplateState extends State<Template> {
controller: _controller,
config: QuillSimpleToolbarConfig(
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),
// Modern editor
// Container(
// height: 300,
// decoration: BoxDecoration(
// border: Border.all(color: Colors.grey),
// borderRadius: BorderRadius.circular(8),
// ),
// child: QuillEditor(
// focusNode: _focusNode,
// scrollController: ScrollController(),
// controller: _controller,
// config: QuillEditorConfig(
// padding: const EdgeInsets.all(8),
// embedBuilders: FlutterQuillEmbeds.editorBuilders(),
// sharedConfigurations: const QuillSharedConfigurations(
// locale: Locale('en'),
// ),
// ),
// ),
// ),
Container(
height: 300,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
),
child: QuillEditor.basic(
focusNode: _editorFocusNode,
scrollController: _editorScrollController,
controller: _controller,
// readOnly: true,
config: QuillEditorConfig(
requestKeyboardFocusOnCheckListChanged: false,
// readOnlyMouseCursor: SystemMouseCursors.text,
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 'dart:html' as html;
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 'dart:convert'; // 3 newly added
@ -45,7 +46,7 @@ class _MyAppState extends State<MyApp> {
SemanticsBinding.instance.ensureSemantics(); // Safe here
if (kIsWeb) {
final uri = Uri.parse(html.window.location.href);
if (uri.path == '/authredirection' &&
if (uri.path == '/tstat/authredirection' &&
uri.queryParameters['code'] != null) {
_authCode = uri.queryParameters['code'];
// _isAuthRedirect = true;
@ -53,51 +54,50 @@ class _MyAppState extends State<MyApp> {
// print(">>> _isAuthRedirect: $_isAuthRedirect");
print(">>> Auth code found at startup: $_authCode");
// You can now:
// - call an API
// - store this in a Provider
// - or just pass it through GoRouter as usual
// if(_authCode){
WidgetsBinding.instance.addPostFrameCallback((_) {
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 {
final response = await http.get(
Uri.parse(url),
headers: { 'Content-Type': 'application/json' }
);
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 != ''){
if (MS_Token != '') {
print('Microsoft - Token Available');
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');
throw Exception('Token not Founded');
}
}else{
} else {
final errorMessage = json.decode(response.body)['message'];
print(errorMessage);
throw Exception(errorMessage);
}
}
catch (e) {
} catch (e) {
print("Error: $e");
}
}
Future<void> storeUserDetails(String token) async {

View File

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