Merge branch 'main' of bitbucket.org:venbainformationtechnology/ts-tat into main
This commit is contained in:
commit
3474a1dbca
@ -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,
|
||||||
|
|||||||
@ -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),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
40
lib/app.dart
40
lib/app.dart
@ -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,29 +54,20 @@ 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'];
|
||||||
@ -84,6 +76,16 @@ class _MyAppState extends State<MyApp> {
|
|||||||
if (MS_Token != '') {
|
if (MS_Token != '') {
|
||||||
print('Microsoft - Token Available');
|
print('Microsoft - Token Available');
|
||||||
await storeUserDetails(MS_Token);
|
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 {
|
} else {
|
||||||
print('Microsoft - Token Not Available');
|
print('Microsoft - Token Not Available');
|
||||||
throw Exception('Token not Founded');
|
throw Exception('Token not Founded');
|
||||||
@ -93,11 +95,9 @@ class _MyAppState extends State<MyApp> {
|
|||||||
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 {
|
||||||
|
|||||||
@ -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!,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user