travel policy

This commit is contained in:
venbaittech 2025-05-28 12:40:58 +05:30
parent b630ac35b7
commit 93f69128b5
11 changed files with 1003 additions and 552 deletions

View File

@ -116,7 +116,7 @@ class _LoginWidgetState extends State<LoginWidget> {
if (userRole == "Travel Agent") { if (userRole == "Travel Agent") {
context.go('/listTravelAgentPlan'); context.go('/listTravelAgentPlan');
} else if (userRole == "Org Admin" || userRole == "Travel Admin") { } else if (userRole == "Org Admin" || userRole == "Travel Admin") {
context.go('/listAllPlan'); context.go('/StatusDashboard');
} else { } else {
context.go('/listPlan'); context.go('/listPlan');
} }

View File

@ -346,7 +346,9 @@ class ForexDataState extends State<ForexData> {
Row( Row(
children: [ children: [
Text( Text(
(forexDataId != null) ? 'Edit Perdiem Amount' : 'Create Perdiem Amount', (forexDataId != null)
? 'Update Perdiem Amount'
: 'Create Perdiem Amount',
style: GoogleFonts.poppins(fontSize: 15, color: Colors.black), style: GoogleFonts.poppins(fontSize: 15, color: Colors.black),
), ),
const Spacer(), const Spacer(),

View File

@ -39,9 +39,34 @@ class Template extends StatefulWidget {
class TemplateState extends State<Template> { class TemplateState extends State<Template> {
final ApiService apiService = ApiService(); final ApiService apiService = ApiService();
final QuillController _controller = () {
return QuillController.basic(
config: QuillControllerConfig(
clipboardConfig: QuillClipboardConfig(
enableExternalRichPaste: true,
onImagePaste: (imageBytes) async {
if (kIsWeb) {
// Dart IO is unsupported on the web.
return null;
}
// Save the image somewhere and return the image URL that will be
// stored in the Quill Delta JSON (the document).
final newFileName =
'image-file-${DateTime.now().toIso8601String()}.png';
final newPath = path.join(
io.Directory.systemTemp.path,
newFileName,
);
final file = await io.File(
newPath,
).writeAsBytes(imageBytes, flush: true);
return file.path;
},
),
));
}();
final FocusNode _editorFocusNode = FocusNode(); final FocusNode _editorFocusNode = FocusNode();
// final ScrollController _editorScrollController = ScrollController(); final ScrollController _editorScrollController = ScrollController();
// final QuillController _controller = QuillController.basic(); // final QuillController _controller = QuillController.basic();
Color layoutColor = Colors.redAccent; Color layoutColor = Colors.redAccent;
Color bodyColor = Colors.white; Color bodyColor = Colors.white;
@ -77,7 +102,10 @@ class TemplateState extends State<Template> {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_editorFocusNode.requestFocus(); // Ensure focus is requested _editorFocusNode.requestFocus(); // Ensure focus is requested
}); });
_controller.document = Document.fromJson(kQuillDefaultSample);
// _controller.document = Document.fromJson(kQuillDefaultSample); // _controller.document = Document.fromJson(kQuillDefaultSample);
// _controller.document = Document.fromJson();
// _controller.document.toPlainText();
// _controller.readOnly = false; // _controller.readOnly = false;
updateData(); updateData();
@ -85,9 +113,16 @@ class TemplateState extends State<Template> {
} }
@override @override
// void dispose() {
// // controllers.dispose();
// // _editorScrollController.dispose();
// _editorFocusNode.dispose();
// super.dispose();
// }
void dispose() { void dispose() {
// controllers.dispose(); _controller.dispose();
// _editorScrollController.dispose(); _editorScrollController.dispose();
_editorFocusNode.dispose(); _editorFocusNode.dispose();
super.dispose(); super.dispose();
} }
@ -177,6 +212,16 @@ class TemplateState extends State<Template> {
height: 20, height: 20,
), ),
buildTempalteSubject(isDesktop), buildTempalteSubject(isDesktop),
IconButton(
icon: const Icon(Icons.output),
tooltip: 'Print Delta JSON to log',
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
'The JSON Delta has been printed to the console.')));
debugPrint(jsonEncode(_controller.document.toDelta().toJson()));
},
),
SizedBox( SizedBox(
height: 20, height: 20,
), ),
@ -238,65 +283,129 @@ class TemplateState extends State<Template> {
const SizedBox(height: 10), const SizedBox(height: 10),
// Modern toolbar // Expanded(
// QuillSimpleToolbar( //
// child: QuillEditor(
// focusNode: _editorFocusNode,
// scrollController: _editorScrollController,
// controller: _controller, // controller: _controller,
// config: QuillSimpleToolbarConfig( // config: QuillEditorConfig(
// embedButtons: FlutterQuillEmbeds.toolbarButtons(), // placeholder: 'Start writing your notes...',
// showClipboardPaste: true, // padding: const EdgeInsets.all(16),
// customButtons: [ // embedBuilders: [
// QuillToolbarCustomButtonOptions( // ...FlutterQuillEmbeds.editorBuilders(
// icon: const Icon(Icons.add_alarm_rounded), // imageEmbedConfig: QuillEditorImageEmbedConfig(
// onPressed: () { // imageProviderBuilder: (context, imageUrl) {
// _controller.document.insert( // // https://pub.dev/packages/flutter_quill_extensions#-image-assets
// _controller.selection.extentOffset, // if (imageUrl.startsWith('assets/')) {
// TimeStampEmbed( // return AssetImage(imageUrl);
// 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();
// } // }
// return null;
// }, // },
// ), // ),
// linkStyle: QuillToolbarLinkStyleButtonOptions( // videoEmbedConfig: QuillEditorVideoEmbedConfig(
// validateLink: (link) { // customVideoBuilder: (videoUrl, readOnly) {
// // Treats all links as valid. When launching the URL, // // To load YouTube videos https://github.com/singerdmx/flutter-quill/releases/tag/v10.8.0
// // `https://` is prefixed if the link is incomplete (e.g., `google.com` `https://google.com`) // return null;
// // however this happens only within the editor.
// return true;
// }, // },
// ), // ),
// ), // ),
// TimeStampEmbedBuilder(),
// ],
// ), // ),
// ), // ),
// const SizedBox(height: 10), // ),
//
// Modern toolbar
QuillSimpleToolbar(
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.readOnly = true;
_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 // // Modern editor
// Container( Container(
// height: 300, height: 200,
// 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(
focusNode: _editorFocusNode,
scrollController: _editorScrollController,
controller: _controller,
config: QuillEditorConfig(
placeholder: 'Start writing your notes...',
padding: const EdgeInsets.all(16),
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(),
],
),
),
),
// child: QuillEditor.basic( // child: QuillEditor.basic(
// focusNode: _editorFocusNode, // focusNode: _editorFocusNode,
// scrollController: _editorScrollController, // scrollController: _editorScrollController,
@ -306,7 +415,7 @@ class TemplateState extends State<Template> {
// requestKeyboardFocusOnCheckListChanged: false, // requestKeyboardFocusOnCheckListChanged: false,
// // readOnlyMouseCursor: SystemMouseCursors.text, // // readOnlyMouseCursor: SystemMouseCursors.text,
// enableScribble: true, // enableScribble: true,
// // // readOnly: false,
// padding: const EdgeInsets.all(8), // padding: const EdgeInsets.all(8),
// placeholder: 'Type something...', // placeholder: 'Type something...',
// embedBuilders: [ // embedBuilders: [
@ -331,7 +440,6 @@ class TemplateState extends State<Template> {
// ], // ],
// ), // ),
// ), // ),
// ),
], ],
); );
} }

View File

@ -8,6 +8,8 @@ import 'dart:typed_data';
import 'dart:html' as html; import 'dart:html' as html;
import 'dart:ui' as web; import 'dart:ui' as web;
import 'package:google_fonts/google_fonts.dart';
import 'package:reorderables/reorderables.dart';
import 'package:web/web.dart' as web; import 'package:web/web.dart' as web;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -42,6 +44,9 @@ class _PolicyState extends State<Policy> {
final ApiService apiService = ApiService(); final ApiService apiService = ApiService();
// List<String> services = [];
List<Map<String, dynamic>> services = [];
String? servicesJson;
Color? layoutColor; Color? layoutColor;
Color? bodyColor; Color? bodyColor;
late String policyType = "domestic"; late String policyType = "domestic";
@ -94,6 +99,7 @@ class _PolicyState extends State<Policy> {
"name": _policyController.text, "name": _policyController.text,
"domestic": SelectedDomestic, "domestic": SelectedDomestic,
"international": SelectedInternational, "international": SelectedInternational,
"services_ids": services,
"is_active": "1", "is_active": "1",
"org_id": orgId, "org_id": orgId,
"created_by": userId, "created_by": userId,
@ -201,7 +207,9 @@ class _PolicyState extends State<Policy> {
final details = final details =
List<Map<String, dynamic>>.from(widget.policy!['policy_details']); List<Map<String, dynamic>>.from(widget.policy!['policy_details']);
print("Filtered Selected Services - $details"); print(
"UUFiltered Selected Services - ${widget.policy!['services_ids']} ");
// pr int("UUFiltered Selected Services - $details");
final filtered = selectedAllServices! final filtered = selectedAllServices!
.where((service) => .where((service) =>
@ -212,13 +220,33 @@ class _PolicyState extends State<Policy> {
ServicesChoosed = filtered; ServicesChoosed = filtered;
}); });
print("Filtered Selected Services Chooesed1: $ServicesChoosed"); print("Filtered Selected Services ChooesedIpfa1: $ServicesChoosed");
if (ServicesChoosed!.isNotEmpty) { if (ServicesChoosed!.isNotEmpty) {
String firstServiceName = ServicesChoosed?.first['name']; String firstServiceName = ServicesChoosed?.first['name'];
print("✅ First service name selected for filter: $firstServiceName"); print("✅ First service name selected for filter: $firstServiceName");
selectedService = firstServiceName; selectedService = firstServiceName;
// services = ServicesChoosed!
// .map((service) => service['name'].toString())
// .toList();
} }
if (widget.policy != null && widget.policy!['services_ids'] != null) {
final decoded = jsonDecode(widget.policy!['services_ids']);
setState(() {
services = List<Map<String, dynamic>>.from(decoded)
.map((service) => {
'service_id': service['service_id'].toString(),
'name': service['name'].toString(),
'order': service['order'].toString(),
})
.toList();
});
print("✅ Loaded services from policy (decoded): $services");
}
print("Filtered Selected Services Added to Policy: $ServicesChoosed"); print("Filtered Selected Services Added to Policy: $ServicesChoosed");
} else { } else {
final filtered = selectedAllServices! final filtered = selectedAllServices!
@ -226,8 +254,23 @@ class _PolicyState extends State<Policy> {
selectedIds.contains(service['service_id'].toString())) selectedIds.contains(service['service_id'].toString()))
.toList(); .toList();
print("ServicesChoosedYY: $ServicesChoosed");
setState(() { setState(() {
ServicesChoosed = filtered; ServicesChoosed = filtered;
// services = ServicesChoosed!
// .map((service) => service['name'].toString())
// .toList();
// ServicesChoosed = filtered;
services = ServicesChoosed!
.map((service) => {
'service_id': service['service_id'].toString(),
'name':
service['name'].toString(), // no space before 'name'
'order': service['order'].toString(),
})
.toList();
}); });
print("Filtered Selected Services Chooesed1: $ServicesChoosed"); print("Filtered Selected Services Chooesed1: $ServicesChoosed");
@ -264,6 +307,7 @@ class _PolicyState extends State<Policy> {
} }
void handleSubmit() async { void handleSubmit() async {
print("Services - $services");
print("USR Detail Submit - $policyData"); print("USR Detail Submit - $policyData");
policyCriteriaKey.currentState?.saveCurrentPolicy(); policyCriteriaKey.currentState?.saveCurrentPolicy();
@ -534,10 +578,10 @@ class _PolicyState extends State<Policy> {
children: [ children: [
Text( Text(
"Choose Policy Type", "Choose Policy Type",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 18, fontSize: 12,
color: Colors.black, fontWeight: FontWeight.w600,
), color: Color(0xFF575A74)),
), ),
], ],
), ),
@ -570,7 +614,7 @@ class _PolicyState extends State<Policy> {
height: 10, height: 10,
), ),
Divider( Divider(
thickness: 0.2, thickness: 0.1,
color: Colors.grey, color: Colors.grey,
), ),
if (errorMessages["policy_details"] != null) ...[ if (errorMessages["policy_details"] != null) ...[
@ -580,6 +624,31 @@ class _PolicyState extends State<Policy> {
style: TextStyle(color: Colors.red, fontSize: 12), style: TextStyle(color: Colors.red, fontSize: 12),
), ),
], ],
isDesktop
? Padding(
padding: const EdgeInsets.only(left: 30.0, right: 98.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Approval Criteria",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74)),
),
Text(
"Service Priority",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74)),
)
],
),
)
: SizedBox.shrink(),
isDesktop isDesktop
? Container( ? Container(
// color: Colors.yellow.shade50, // color: Colors.yellow.shade50,
@ -606,13 +675,19 @@ class _PolicyState extends State<Policy> {
), ),
) )
: Expanded( : Expanded(
child: Row( child: Container(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [ children: [
// _buildPolicyOrdering(isDesktop), _buildPolicyCategoryList(isDesktop),
_buildPolicyOrdering(isDesktop),
_buildPolicyCategory(isDesktop), _buildPolicyCategory(isDesktop),
], ],
), ),
), ),
),
),
// isDesktop // isDesktop
// ? Expanded( // ? Expanded(
// child: Row( // child: Row(
@ -644,10 +719,10 @@ class _PolicyState extends State<Policy> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text("Policy Name", Text("Policy Name",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w200, fontWeight: FontWeight.w600,
color: Colors.black)), color: Color(0xFF575A74))),
SizedBox(height: 5), SizedBox(height: 5),
CustomTextFieldUserWrapper( CustomTextFieldUserWrapper(
isFocused: false, isFocused: false,
@ -655,12 +730,13 @@ class _PolicyState extends State<Policy> {
child: SizedBox( child: SizedBox(
height: 40, height: 40,
child: TextField( child: TextField(
style: TextStyle(fontSize: 12), style: GoogleFonts.poppins(fontSize: 12),
controller: _policyController, controller: _policyController,
onChanged: (value) => _clearError("name"), onChanged: (value) => _clearError("name"),
decoration: InputDecoration( decoration: InputDecoration(
labelText: "Policy Name", labelText: "Policy Name",
labelStyle: TextStyle(fontSize: 12, color: Colors.grey), labelStyle:
GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16), contentPadding: EdgeInsets.symmetric(vertical: 16),
@ -682,10 +758,10 @@ class _PolicyState extends State<Policy> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text("Policy Type", Text("Policy Type",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w200, fontWeight: FontWeight.w600,
color: Colors.black)), color: Color(0xFF575A74))),
SizedBox(height: 5), SizedBox(height: 5),
Row( Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
@ -702,21 +778,177 @@ class _PolicyState extends State<Policy> {
Widget _buildPolicyCategoryList(bool isDesktop) { Widget _buildPolicyCategoryList(bool isDesktop) {
return Container( return Container(
margin: const EdgeInsets.only(top: 8.0),
// color: Colors.white, // color: Colors.white,
height: MediaQuery.of(context).size.height, height: isDesktop ? MediaQuery.of(context).size.height * 0.55 : null,
// color: Colors.blueGrey.shade200, // color: Colors.blueGrey.shade200,
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null, width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
decoration: BoxDecoration(
border: Border.all(color: Colors.blueGrey.shade100, width: 0.35)),
child: isDesktop child: isDesktop
? Column( ? Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [_buildPolicySubCategoryList(isDesktop)], children: [_buildPolicySubCategoryList(isDesktop)],
),
) )
: Container( : Column(
children: [
Container(
// color: Colors.amber, // color: Colors.amber,
child: Expanded( child: _buildPolicySubCategoryList(isDesktop),
child: Row( // child: Text("FAta"),
mainAxisAlignment: MainAxisAlignment.start, // child: Row(
children: [_buildPolicySubCategoryList(isDesktop)], // mainAxisAlignment: MainAxisAlignment.start,
// children: [_buildPolicySubCategoryList(isDesktop)],
// ),
),
],
),
);
}
Widget _buildPolicySubCategoryList(bool isDesktop) {
if (services.isEmpty) {
return const Center(child: CircularProgressIndicator());
}
if (isDesktop) {
// 🖥 Desktop (vertical ReorderableListView)
return Expanded(
child: ReorderableListView(
onReorder: (oldIndex, newIndex) {
setState(() {
if (newIndex > oldIndex) newIndex -= 1;
final item = services.removeAt(oldIndex);
services.insert(newIndex, item);
});
},
children: List.generate(services.length, (i) {
return SizedBox(
key: ValueKey(services[i]['service_id']),
width: 185,
height: 35,
// height: MediaQuery.of(context).size.height * 0.025,
child: _buildServiceTile(services[i], i.toString()),
);
}),
),
);
} else {
// 📱 Mobile (horizontal ReorderableWrap)
return Container(
// color: Colors.red,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Service Ordering"),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: ReorderableWrap(
spacing: 8,
runSpacing: 8,
direction: Axis.horizontal,
needsLongPressDraggable: true,
onReorder: (oldIndex, newIndex) {
setState(() {
final item = services.removeAt(oldIndex);
services.insert(newIndex, item);
});
},
children: List.generate(services.length, (i) {
return SizedBox(
key: ValueKey(services[i]),
height: isDesktop ? 10 : 45,
// child: _buildServiceTile(services[i]['service_id'], i.toString()),
child: _buildServiceTile(services[i], i.toString()),
);
}),
),
),
],
),
);
}
}
Widget _buildServiceTile(Map<String, dynamic> service, String index) {
bool isSelected = selectedServiceIndex.value == index;
String name = service['name']; // or 'service_id', as needed
return GestureDetector(
onTap: () {
setState(() {
selectedServiceIndex.value = index;
});
},
child: Container(
margin: const EdgeInsets.all(5),
decoration: BoxDecoration(
// color: Colors.yellow.shade50,
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.white),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
blurRadius: 2,
offset: const Offset(0, 1),
)
],
),
alignment: Alignment.center,
child: Text(
name,
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 12,
),
),
),
);
}
Widget _buildServiceTile1(Map<String, dynamic> service, String index) {
// bool isSelected = selectedServiceIndex.value == index;
// bool isSelected = selectedServiceIndex.value == index;
// String name = service['service_id']
bool isSelected = selectedServiceIndex.value == index;
String name = service['name'];
return GestureDetector(
onTap: () {
setState(() {
selectedServiceIndex.value = index;
});
},
child: Container(
height: 5,
// padding: const EdgeInsets.symmetric(horizontal: 1, vertical: 2),
margin: const EdgeInsets.all(1),
decoration: BoxDecoration(
color: Colors.white,
// color: isSelected ? const Color(0xFF114D8B) : Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.white),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
blurRadius: 2,
offset: const Offset(0, 1),
)
],
),
alignment: Alignment.center,
child: Text(
name,
style: GoogleFonts.poppins(
color: Colors.black,
// color: isSelected ? Colors.white : Colors.black87,
fontSize: 12,
// fontWeight: FontWeight.w100,
), ),
), ),
), ),
@ -727,8 +959,8 @@ class _PolicyState extends State<Policy> {
return Container( return Container(
// height: 50, // height: 50,
// color: Colors.white, // color: Colors.white,
// color: Colors.blueGrey.shade200, // color: Colors.yellow.shade200,
padding: isDesktop ? const EdgeInsets.only(left: 35) : null, padding: isDesktop ? const EdgeInsets.only(left: 30, top: 8) : null,
width: isDesktop ? MediaQuery.of(context).size.width * 0.62 : null, width: isDesktop ? MediaQuery.of(context).size.width * 0.62 : null,
// width: isDesktop ? MediaQuery.of(context).size.width * 0.75 : null, // width: isDesktop ? MediaQuery.of(context).size.width * 0.75 : null,
child: isDesktop child: isDesktop
@ -736,20 +968,18 @@ class _PolicyState extends State<Policy> {
// color: Colors.amber, // color: Colors.amber,
child: Expanded( child: Expanded(
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [_buildPolicyServiceOrdering(isDesktop)], children: [_buildPolicyServiceOrdering(isDesktop)],
), ),
), ),
) )
: Container( : Container(
// color: Colors.amber, // color: Colors.amber,
child: Expanded(
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [_buildPolicyServiceOrdering(isDesktop)], children: [_buildPolicyServiceOrdering(isDesktop)],
), ),
), ),
),
); );
} }
@ -776,7 +1006,7 @@ class _PolicyState extends State<Policy> {
bool isSelected = selectedServiceIndex.value == index.toString(); bool isSelected = selectedServiceIndex.value == index.toString();
return SizedBox( return SizedBox(
// width: isDesktop ? 140 : null, // width: isDesktop ? 40 : null,
height: isDesktop height: isDesktop
? max((MediaQuery.of(context).size.height * 0.075), 10) ? max((MediaQuery.of(context).size.height * 0.075), 10)
: 45, : 45,
@ -816,13 +1046,13 @@ class _PolicyState extends State<Policy> {
children: [ children: [
Text( Text(
service, service,
style: TextStyle( style: GoogleFonts.poppins(
color: isSelected color: isSelected
? const Color(0xFF114D8B) ? const Color(0xFF114D8B)
: Colors.black87, : Colors.black87,
fontSize: 13, fontSize: 13,
fontWeight: fontWeight:
isSelected ? FontWeight.bold : FontWeight.w100, isSelected ? FontWeight.bold : FontWeight.w500,
decoration: TextDecoration decoration: TextDecoration
.none, // remove built-in underline .none, // remove built-in underline
), ),
@ -846,7 +1076,7 @@ class _PolicyState extends State<Policy> {
); );
} }
Widget _buildPolicySubCategoryList(bool isDesktop) { Widget _buildPolicySubCategoryList1(bool isDesktop) {
// List<String> services = [ // List<String> services = [
// "Flight", // "Flight",
// "Train", // "Train",
@ -887,7 +1117,7 @@ class _PolicyState extends State<Policy> {
onTap: () { onTap: () {
print("Selected Services - $service - $index"); print("Selected Services - $service - $index");
setState(() { setState(() {
selectedServiceIndex.value = index.toString(); // selectedServiceIndex.value = index.toString();
// selectedService = service; // selectedService = service;
// //
// if (selectedService == "Flight" || // if (selectedService == "Flight" ||
@ -931,7 +1161,7 @@ class _PolicyState extends State<Policy> {
alignment: Alignment.center, alignment: Alignment.center,
child: Text( child: Text(
service, service,
style: TextStyle( style: GoogleFonts.poppins(
color: isSelected ? Colors.white : Colors.black87, color: isSelected ? Colors.white : Colors.black87,
fontSize: 13, fontSize: 13,
fontWeight: fontWeight:
@ -947,7 +1177,7 @@ class _PolicyState extends State<Policy> {
Widget _buildPolicyCategory(bool isDesktop) { Widget _buildPolicyCategory(bool isDesktop) {
return Container( return Container(
margin: EdgeInsets.all(10), margin: isDesktop ? EdgeInsets.all(5) : null,
// color: Colors.brown.shade100, // color: Colors.brown.shade100,
// child: Text("data"), // child: Text("data"),
// color: Colors.white60, // color: Colors.white60,
@ -988,7 +1218,7 @@ class _PolicyState extends State<Policy> {
children: [ children: [
Text( Text(
"Domestic", "Domestic",
style: TextStyle( style: GoogleFonts.poppins(
color: _selectedTripType == "1" ? Colors.white : Colors.black, color: _selectedTripType == "1" ? Colors.white : Colors.black,
fontWeight: _selectedTripType == "1" ? FontWeight.w600 : null, fontWeight: _selectedTripType == "1" ? FontWeight.w600 : null,
fontSize: 13), fontSize: 13),
@ -1042,7 +1272,7 @@ class _PolicyState extends State<Policy> {
children: [ children: [
Text( Text(
"International", "International",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 13, fontSize: 13,
color: _selectedTripType == "2" ? Colors.white : Colors.black, color: _selectedTripType == "2" ? Colors.white : Colors.black,
fontWeight: _selectedTripType == "2" ? FontWeight.w600 : null, fontWeight: _selectedTripType == "2" ? FontWeight.w600 : null,
@ -1115,7 +1345,10 @@ class _PolicyState extends State<Policy> {
onPressed: () { onPressed: () {
context.go('/PolicyList'); context.go('/PolicyList');
}, },
child: Text("Cancel")), child: Text(
"Cancel",
style: GoogleFonts.poppins(fontSize: 10),
)),
SizedBox( SizedBox(
width: 20, width: 20,
), ),
@ -1140,7 +1373,10 @@ class _PolicyState extends State<Policy> {
), ),
onPressed: onPressed:
isViewMode ? null : handleSubmit, // Disable when in view mode isViewMode ? null : handleSubmit, // Disable when in view mode
child: Text("Submit"), child: Text(
"Submit",
style: GoogleFonts.poppins(fontSize: 10),
),
), ),
) )
]; ];
@ -1163,7 +1399,10 @@ class _PolicyState extends State<Policy> {
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
visualDensity: VisualDensity.compact, visualDensity: VisualDensity.compact,
dense: true, dense: true,
title: Text("Domestic"), title: Text(
"Domestic",
style: GoogleFonts.poppins(fontSize: 12),
),
value: "1", value: "1",
groupValue: _selectedTripType, groupValue: _selectedTripType,
onChanged: (value) { onChanged: (value) {

View File

@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:dropdown_search/dropdown_search.dart'; import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import '../../config/apiUrl.dart'; import '../../config/apiUrl.dart';
@ -100,6 +101,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
void saveCurrentPolicy() { void saveCurrentPolicy() {
if (ServiceId != null) { if (ServiceId != null) {
print("Saving curremt Add or Update");
addOrUpdatePolicy(ServiceId!); addOrUpdatePolicy(ServiceId!);
} }
} }
@ -154,7 +156,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"service_id": serviceId, "service_id": serviceId,
"cost": costController[serviceId]?.text, "cost": costController[serviceId]?.text,
// "class": classController[serviceId]?.text, // "class": classController[serviceId]?.text,
"class": classAction[serviceId], "class": classAction[serviceId] ?? "",
"a1_action": FirstApproverAction[serviceId], "a1_action": FirstApproverAction[serviceId],
"a2_action": SecondApproverAction[serviceId], "a2_action": SecondApproverAction[serviceId],
"a3_action": ThirdApproverAction[serviceId], "a3_action": ThirdApproverAction[serviceId],
@ -184,6 +186,8 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
if (hasValue && allActionsNull) { if (hasValue && allActionsNull) {
validationErrors[serviceId] = "Please select all actions."; validationErrors[serviceId] = "Please select all actions.";
return; return;
} else {
print("HAS VAlue");
} }
validationErrors.remove(serviceId); validationErrors.remove(serviceId);
@ -319,38 +323,42 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// widget.isDesktop ? SizedBox(height: 10) : SizedBox(height: 5), // widget.isDesktop ? SizedBox(height: 10) : SizedBox(height: 5),
Row( // Row(
mainAxisAlignment: MainAxisAlignment.start, // mainAxisAlignment: MainAxisAlignment.start,
children: [ // children: [
Padding( // Padding(
padding: const EdgeInsets.only(left: 28.0), // padding: widget.isDesktop
child: Text( // ? const EdgeInsets.only(left: 28.0)
" Policy Criteria For ${widget.selectedService} ", // : const EdgeInsets.only(left: 0),
style: TextStyle( // child: Text(
fontSize: 13, // " Policy Criteria For ${widget.selectedService} ",
color: Color(0xFF9E9DBD), // style: GoogleFonts.poppins(
fontWeight: FontWeight.bold), // fontSize: 13,
), // color: Color(0xFF9E9DBD),
) // fontWeight: FontWeight.bold),
], // ),
), // )
// ],
// ),
if (widget.isClass!) if (widget.isClass!)
widget.isDesktop ? SizedBox(height: 5) : SizedBox(height: 5), widget.isDesktop ? SizedBox(height: 1) : SizedBox(height: 1),
Padding( Padding(
padding: const EdgeInsets.only(left: 28.0), padding: widget.isDesktop
? const EdgeInsets.only(left: 0.0)
: const EdgeInsets.only(left: 0),
child: Row( child: Row(
children: [ children: [
Container( Container(
// color: Colors.grey, // color: Colors.grey,
padding: padding:
const EdgeInsets.only(top: 5, bottom: 5, left: 5, right: 5), const EdgeInsets.only(top: 2, bottom: 2, left: 5, right: 5),
child: widget.isDesktop child: widget.isDesktop
? Row( ? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
if (widget.isClass) if (widget.isClass)
buildClassWidget(widget.isDesktop), buildClassWidget(widget.isDesktop),
SizedBox(width: 30), SizedBox(width: 45),
if (widget.isCost!) buildCostWidget(widget.isDesktop), if (widget.isCost!) buildCostWidget(widget.isDesktop),
], ],
) )
@ -367,7 +375,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
], ],
), ),
), ),
if (widget.isCost!) SizedBox(height: 15), if (widget.isCost!) SizedBox(height: 5),
if (validationErrors[ServiceId] != null) if (validationErrors[ServiceId] != null)
Row( Row(
children: [ children: [
@ -378,7 +386,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
fontWeight: FontWeight.bold)) fontWeight: FontWeight.bold))
], ],
), ),
if (validationErrors[ServiceId] != null) SizedBox(height: 15), if (validationErrors[ServiceId] != null) SizedBox(height: 5),
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: null, border: null,
@ -397,6 +405,9 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
width: widget.isDesktop width: widget.isDesktop
? MediaQuery.of(context).size.width * 0.56 ? MediaQuery.of(context).size.width * 0.56
: 600, : 600,
height: widget.isDesktop
? MediaQuery.of(context).size.height * 0.56
: null,
child: Column( child: Column(
children: [ children: [
Container( Container(
@ -408,7 +419,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
// ), // ),
), ),
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
top: 10, bottom: 10, left: 35, right: 35), top: 10, bottom: 0, left: 0, right: 35),
child: Row( child: Row(
mainAxisAlignment: widget.isDesktop mainAxisAlignment: widget.isDesktop
? MainAxisAlignment.spaceAround ? MainAxisAlignment.spaceAround
@ -418,7 +429,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
flex: 2, flex: 2,
child: Text( child: Text(
"Approver", "Approver",
style: TextStyle( style: GoogleFonts.poppins(
color: Color(0xFF9E9DBD), color: Color(0xFF9E9DBD),
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 12), fontSize: 12),
@ -428,7 +439,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
flex: 2, flex: 2,
child: Text( child: Text(
"Actions", "Actions",
style: TextStyle( style: GoogleFonts.poppins(
color: Color(0xFF9E9DBD), color: Color(0xFF9E9DBD),
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 12), fontSize: 12),
@ -436,7 +447,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
), ),
Text( Text(
"Parallel Action", "Parallel Action",
style: TextStyle( style: GoogleFonts.poppins(
color: Color(0xFF9E9DBD), color: Color(0xFF9E9DBD),
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 12), fontSize: 12),
@ -449,13 +460,13 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
color: Colors.grey, color: Colors.grey,
), ),
SizedBox( SizedBox(
height: 180, // height: 180,
child: SingleChildScrollView(
// scrollDirection: Axis.vertical, // scrollDirection: Axis.vertical,
child: Container( child: Container(
// height: MediaQuery.of(context).size.height * 3,
// color: Colors.grey, // color: Colors.grey,
margin: margin: const EdgeInsets.only(right: 20, left: 0),
const EdgeInsets.only(right: 20, left: 20),
// color: Colors.grey.shade100, // color: Colors.grey.shade100,
child: Column(children: [ child: Column(children: [
Container( Container(
@ -463,13 +474,16 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text("Approver 1"), Text(
"Approver 1",
style: GoogleFonts.poppins(fontSize: 13),
),
Spacer(), Spacer(),
CustomTextFieldUserWrapper( CustomTextFieldUserWrapper(
isFocused: false, isFocused: false,
isDesktop: widget.isDesktop, isDesktop: widget.isDesktop,
child: SizedBox( child: SizedBox(
height: 40, height: 35,
child: DropdownSearch<String>( child: DropdownSearch<String>(
selectedItem: selectedItem:
FirstApproverAction[ServiceId], FirstApproverAction[ServiceId],
@ -478,8 +492,8 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
// showSearchBox: true, // showSearchBox: true,
fit: FlexFit fit: FlexFit
.loose, // Allows flexible height .loose, // Allows flexible height
constraints: BoxConstraints( constraints:
maxHeight: 250), BoxConstraints(maxHeight: 250),
itemBuilder: itemBuilder:
(context, item, isSelected) => (context, item, isSelected) =>
Padding( Padding(
@ -489,7 +503,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
vertical: 8.0), vertical: 8.0),
child: Text( child: Text(
item, item,
style: TextStyle( style: GoogleFonts.poppins(
fontSize: fontSize:
12, // 👈 Smaller text size here 12, // 👈 Smaller text size here
color: Colors color: Colors
@ -511,26 +525,22 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
contentPadding: contentPadding:
EdgeInsets.symmetric( EdgeInsets.symmetric(
horizontal: 1, horizontal: 1,
), vertical: 5),
), ),
), ),
dropdownBuilder: dropdownBuilder:
(context, selectedItem) => (context, selectedItem) => Text(
Align(
// Center-align selected item
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select", selectedItem ?? "Select",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
color: Color(0xFF114D8B)), color: Color(0xFF114D8B)),
), ),
),
onChanged: (String? newValue) { onChanged: (String? newValue) {
setState(() { setState(() {
// Find the country_code based on selected country_name // Find the country_code based on selected country_name
FirstApproverAction[ FirstApproverAction[ServiceId!] =
ServiceId!] = newValue; newValue;
// print("selectedUserType - $selectedUserType"); // print("selectedUserType - $selectedUserType");
@ -546,8 +556,8 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
GestureDetector( GestureDetector(
onTap: () { onTap: () {
setState(() { setState(() {
SelectedParallelProcess[ SelectedParallelProcess[ServiceId!] =
ServiceId!] = "1"; "1";
}); });
print( print(
@ -559,8 +569,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all( border: Border.all(
color: color: (SelectedParallelProcess[
(SelectedParallelProcess[
ServiceId] == ServiceId] ==
"1") "1")
? Colors.green ? Colors.green
@ -586,13 +595,16 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text("Approver 2"), Text(
"Approver 2",
style: GoogleFonts.poppins(fontSize: 13),
),
Spacer(), Spacer(),
CustomTextFieldUserWrapper( CustomTextFieldUserWrapper(
isFocused: false, isFocused: false,
isDesktop: widget.isDesktop, isDesktop: widget.isDesktop,
child: SizedBox( child: SizedBox(
height: 40, height: 35,
child: DropdownSearch<String>( child: DropdownSearch<String>(
selectedItem: selectedItem:
SecondApproverAction[ServiceId], SecondApproverAction[ServiceId],
@ -601,8 +613,8 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
// showSearchBox: true, // showSearchBox: true,
fit: FlexFit fit: FlexFit
.loose, // Allows flexible height .loose, // Allows flexible height
constraints: BoxConstraints( constraints:
maxHeight: 250), BoxConstraints(maxHeight: 250),
itemBuilder: itemBuilder:
(context, item, isSelected) => (context, item, isSelected) =>
Padding( Padding(
@ -634,26 +646,22 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
contentPadding: contentPadding:
EdgeInsets.symmetric( EdgeInsets.symmetric(
horizontal: 1, horizontal: 1,
), vertical: 5),
), ),
), ),
dropdownBuilder: dropdownBuilder:
(context, selectedItem) => (context, selectedItem) => Text(
Align(
// Center-align selected item
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select", selectedItem ?? "Select",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
color: Color(0xFF114D8B)), color: Color(0xFF114D8B)),
), ),
),
onChanged: (String? newValue) { onChanged: (String? newValue) {
setState(() { setState(() {
// Find the country_code based on selected country_name // Find the country_code based on selected country_name
SecondApproverAction[ SecondApproverAction[ServiceId!] =
ServiceId!] = newValue; newValue;
// print("selectedUserType - $selectedUserType"); // print("selectedUserType - $selectedUserType");
@ -669,8 +677,8 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
GestureDetector( GestureDetector(
onTap: () { onTap: () {
setState(() { setState(() {
SelectedParallelProcess[ SelectedParallelProcess[ServiceId!] =
ServiceId!] = "2"; "2";
}); });
print( print(
@ -714,13 +722,16 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text("Approver 3"), Text(
"Approver 3",
style: GoogleFonts.poppins(fontSize: 13),
),
Spacer(), Spacer(),
CustomTextFieldUserWrapper( CustomTextFieldUserWrapper(
isFocused: false, isFocused: false,
isDesktop: widget.isDesktop, isDesktop: widget.isDesktop,
child: SizedBox( child: SizedBox(
height: 40, height: 35,
child: DropdownSearch<String>( child: DropdownSearch<String>(
selectedItem: selectedItem:
ThirdApproverAction[ServiceId], ThirdApproverAction[ServiceId],
@ -729,8 +740,8 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
// showSearchBox: true, // showSearchBox: true,
fit: FlexFit fit: FlexFit
.loose, // Allows flexible height .loose, // Allows flexible height
constraints: BoxConstraints( constraints:
maxHeight: 250), BoxConstraints(maxHeight: 250),
itemBuilder: itemBuilder:
(context, item, isSelected) => (context, item, isSelected) =>
Padding( Padding(
@ -740,7 +751,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
vertical: 8.0), vertical: 8.0),
child: Text( child: Text(
item, item,
style: TextStyle( style: GoogleFonts.poppins(
fontSize: fontSize:
12, // 👈 Smaller text size here 12, // 👈 Smaller text size here
color: Colors color: Colors
@ -762,26 +773,24 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
contentPadding: contentPadding:
EdgeInsets.symmetric( EdgeInsets.symmetric(
horizontal: 1, horizontal: 1,
), vertical: 5),
), ),
), ),
dropdownBuilder: dropdownBuilder:
(context, selectedItem) => (context, selectedItem) =>
Align(
// Center-align selected item // Center-align selected item
alignment: Alignment.centerLeft, Text(
child: Text(
selectedItem ?? "Select", selectedItem ?? "Select",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
color: Color(0xFF114D8B)), color: Color(0xFF114D8B)),
), ),
),
onChanged: (String? newValue) { onChanged: (String? newValue) {
setState(() { setState(() {
// Find the country_code based on selected country_name // Find the country_code based on selected country_name
ThirdApproverAction[ ThirdApproverAction[ServiceId!] =
ServiceId!] = newValue; newValue;
// print("selectedUserType - $selectedUserType"); // print("selectedUserType - $selectedUserType");
@ -797,8 +806,8 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
GestureDetector( GestureDetector(
onTap: () { onTap: () {
setState(() { setState(() {
SelectedParallelProcess[ SelectedParallelProcess[ServiceId!] =
ServiceId!] = "3"; "3";
}); });
print( print(
"SelectedParallelProcess - $SelectedParallelProcess[ServiceId]"); "SelectedParallelProcess - $SelectedParallelProcess[ServiceId]");
@ -809,7 +818,10 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all( border: Border.all(
color: ((SelectedParallelProcess[ServiceId] == "1") || color:
((SelectedParallelProcess[
ServiceId] ==
"1") ||
(SelectedParallelProcess[ (SelectedParallelProcess[
ServiceId] == ServiceId] ==
"2") || "2") ||
@ -844,7 +856,6 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
]), ]),
), ),
), ),
)
], ],
)), )),
], ],
@ -879,7 +890,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
DropdownMenuItem<String>( DropdownMenuItem<String>(
value: null, value: null,
child: Text("No options available", child: Text("No options available",
style: TextStyle(color: Colors.grey)), style: GoogleFonts.poppins(color: Colors.grey)),
), ),
); );
} }
@ -914,9 +925,9 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text("Class", Text("Class",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w200, // fontWeight: FontWeight.w200,
color: Colors.black)), color: Colors.black)),
SizedBox(height: 5), SizedBox(height: 5),
CustomTextFieldUserWrapper( CustomTextFieldUserWrapper(
@ -948,7 +959,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
// controller: _hotelNameController, // controller: _hotelNameController,
value: classAction[ServiceId], value: classAction[ServiceId],
style: TextStyle(fontSize: 12), style: GoogleFonts.poppins(fontSize: 12),
decoration: InputDecoration( decoration: InputDecoration(
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric( contentPadding: EdgeInsets.symmetric(
@ -979,9 +990,9 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text("Cost", Text("Cost",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w200, // fontWeight: FontWeight.w200,
color: Colors.black)), color: Colors.black)),
SizedBox(height: 5), SizedBox(height: 5),
CustomTextFieldUserWrapper( CustomTextFieldUserWrapper(
@ -990,7 +1001,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
child: SizedBox( child: SizedBox(
height: 40, height: 40,
child: TextField( child: TextField(
style: TextStyle(fontSize: 12), style: GoogleFonts.poppins(fontSize: 12),
controller: costController[ServiceId], controller: costController[ServiceId],
// enabled: !isViewMode, // enabled: !isViewMode,
onChanged: (value) { onChanged: (value) {
@ -998,7 +1009,8 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
}, },
decoration: InputDecoration( decoration: InputDecoration(
labelText: "Cost", labelText: "Cost",
labelStyle: TextStyle(fontSize: 12, color: Colors.grey), labelStyle:
GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16), contentPadding: EdgeInsets.symmetric(vertical: 16),

View File

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:frontend/Screens/group/group.dart'; import 'package:frontend/Screens/group/group.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:responsive_builder/responsive_builder.dart'; import 'package:responsive_builder/responsive_builder.dart';
@ -218,9 +219,14 @@ class _PolicyListState extends State<PolicyList> {
children: [ children: [
Row( Row(
children: [ children: [
const Text('Policy List', Text(
style: 'Policy List',
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), style: GoogleFonts.poppins(
fontSize: isDesktop ? 16 : 14,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
IconButton( IconButton(
icon: const Icon(Icons.keyboard_arrow_down), icon: const Icon(Icons.keyboard_arrow_down),
onPressed: () {}, onPressed: () {},
@ -243,7 +249,8 @@ class _PolicyListState extends State<PolicyList> {
}, },
child: Row( child: Row(
children: [ children: [
Text('New Policy'), Text('New Policy',
style: GoogleFonts.poppins(fontSize: 12)),
SizedBox( SizedBox(
width: 5, width: 5,
), ),
@ -315,16 +322,39 @@ class _PolicyListState extends State<PolicyList> {
Row( Row(
children: [ children: [
Expanded( Expanded(
flex: 2, flex: 1,
child: Text("Policy Name: ${policy['name']}", child: Text("Policy Name",
style: TextStyle( style: GoogleFonts.poppins(
fontSize: 13, fontWeight: FontWeight.bold)), fontSize: 11.5, fontWeight: FontWeight.w400)),
), ),
Expanded(flex: 1, child: Text(" ${policy['created_on']}")), Expanded(
Expanded(flex: 1, child: Text("${policy['created_by']}")), flex: 1,
child: Text("Policy Type",
style: GoogleFonts.poppins(
fontSize: 11.5, fontWeight: FontWeight.w400))),
// Expanded(flex: 1, child: Text("${policy['created_by']}")),
], ],
), ),
SizedBox(height: 4), SizedBox(height: 4),
Row(
children: [
Expanded(
flex: 1,
child: Text("${policy['name']}",
style: GoogleFonts.poppins(
fontSize: 13, fontWeight: FontWeight.w600)),
),
Expanded(
flex: 1,
child: Text(
policy['domestic'] == "1"
? "Domestic"
: "International",
style: GoogleFonts.poppins(
fontSize: 13, fontWeight: FontWeight.w600))),
// Expanded(flex: 1, child: Text("${policy['created_by']}")),
],
),
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [

View File

@ -1162,9 +1162,9 @@ class PersonalDetailsState extends State<PersonalDetails> {
items: apiRoleData?.map<DropdownMenuItem<String>>((item) { items: apiRoleData?.map<DropdownMenuItem<String>>((item) {
return DropdownMenuItem( return DropdownMenuItem(
value: item['dropdown_key'], // ID as value value: item['dropdown_key'], // ID as value
child: Text(item['dropdown_value'] ?? "Select")); child: Text(item['dropdown_value'] ?? "Select Role"));
}).toList(), }).toList(),
hint: Text("Select"), hint: Text("Select Role"),
disabledHint: Text( disabledHint: Text(
selectedRole ?? "Select Role", selectedRole ?? "Select Role",
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),

View File

@ -6,7 +6,13 @@ import 'package:shared_preferences/shared_preferences.dart'; // don't forget
import '../services/apiService.dart'; import '../services/apiService.dart';
import '../utils/auth_utils.dart'; import '../utils/auth_utils.dart';
enum TabSelection { allTrips, myTrips, myApprovals, allMenu, dashboard } enum TabSelection {
dashboard,
allTrips,
myTrips,
myApprovals,
allMenu,
}
class CustomAppBar extends StatefulWidget implements PreferredSizeWidget { class CustomAppBar extends StatefulWidget implements PreferredSizeWidget {
final bool isDesktop; final bool isDesktop;
@ -188,7 +194,9 @@ class _CustomAppBarState extends State<CustomAppBar> {
print("location - $location"); print("location - $location");
setState(() { setState(() {
if (location.contains('/listAllPlan') || if (location.contains('/StatusDashboard')) {
selectedTab = TabSelection.dashboard;
} else if (location.contains('/listAllPlan') ||
location.contains('/allTrips/trips')) { location.contains('/allTrips/trips')) {
selectedTab = TabSelection.allTrips; selectedTab = TabSelection.allTrips;
} else if (location.contains('/listPlan') || } else if (location.contains('/listPlan') ||
@ -197,8 +205,6 @@ class _CustomAppBarState extends State<CustomAppBar> {
selectedTab = TabSelection.myTrips; selectedTab = TabSelection.myTrips;
} else if (location.contains('/ApprovalList')) { } else if (location.contains('/ApprovalList')) {
selectedTab = TabSelection.myApprovals; selectedTab = TabSelection.myApprovals;
} else if (location.contains('/StatusDashboard')) {
selectedTab = TabSelection.dashboard;
} else { } else {
selectedTab = TabSelection.allMenu; selectedTab = TabSelection.allMenu;
} }

View File

@ -1048,4 +1048,49 @@ class ApiService {
throw Exception('Failed to load CostCenter details'); throw Exception('Failed to load CostCenter details');
} }
} }
Future<Map<String, dynamic>> getHotelsDetailsFind(int id) async {
final String apiUrldata = '$apiUrl/api/findHotels?hotel_id=$id';
final token = await getToken();
if (token == null) {
throw Exception('Token not found. Please log in.');
}
final response = await http.get(
Uri.parse(apiUrldata),
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
);
if (response.statusCode == 200) {
try {
final data = json.decode(response.body);
// print('findout the result');
// print(data.runtimeType);
// print(data);
if (!data.containsKey('data') || data['data'] is! List) {
throw Exception(
"Invalid response format: 'data' field is missing or not a List");
}
final List<Map<String, dynamic>> listData =
List<Map<String, dynamic>>.from(data['data']);
if (listData.isEmpty) {
throw Exception("No Hotel data found with ID $id");
}
return listData[0];
} catch (e) {
throw Exception('Error parsing response: $e');
}
} else {
throw Exception('Failed to load Hotel details');
}
}
} }

View File

@ -701,6 +701,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.2" version: "3.2.2"
reorderables:
dependency: "direct main"
description:
name: reorderables
sha256: "004a886e4878df1ee27321831c838bc1c976311f4ca6a74ce7d561e506540a77"
url: "https://pub.dev"
source: hosted
version: "0.6.0"
responsive_builder: responsive_builder:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -53,6 +53,7 @@ dependencies:
flutter_quill: ^11.4.1 flutter_quill: ^11.4.1
flutter_quill_extensions: ^11.0.0 flutter_quill_extensions: ^11.0.0
flutter_localization: ^0.3.2 flutter_localization: ^0.3.2
reorderables: ^0.6.0
dev_dependencies: dev_dependencies: