group highlighter

This commit is contained in:
venbaittech 2025-06-19 11:32:30 +05:30
parent 1fcd57f676
commit 691ba181c6
4 changed files with 316 additions and 153 deletions

View File

@ -51,7 +51,10 @@ class _groupState extends State<Group> {
List<dynamic>? apiForDomestic;
List<dynamic>? apiForInternational;
Map<String, String> errorMessages = {};
final Map<String, TextEditingController> controllers = {};
Map<String, FocusNode> focusNodes = {};
Map<String, bool> focusStates = {};
List<String> dataHeader = ["name", "description"];
@ -82,7 +85,14 @@ class _groupState extends State<Group> {
for (var field in dataHeader) {
controllers[field] = TextEditingController();
focusNodes["${field}FocusNode"] = FocusNode();
focusStates["${field}Focused"] = false;
}
print("Focus Nodes KeysII: ${focusNodes.keys.toList()}");
print("Focus States KeysII: ${focusStates.keys.toList()}");
print("Text Controllers KeysII: ${controllers.keys.toList()}");
updateData();
loadInitialData();
});

View File

@ -45,6 +45,9 @@ class GroupDataState extends State<GroupData> {
Map<String, dynamic>? apiData;
final Map<String, TextEditingController> controllers = {};
Map<String, FocusNode> focusNodes = {};
Map<String, bool> focusStates = {};
Map<String, String> errorMessages = {};
List<dynamic> domesticList = [];
@ -97,8 +100,26 @@ class GroupDataState extends State<GroupData> {
apiForInternational = null;
apiData = null;
// for (var field in dataHeader) {
// controllers[field] = TextEditingController();
// }
for (var field in dataHeader) {
controllers[field] = TextEditingController();
focusNodes["${field}FocusNode"] = FocusNode();
focusStates["${field}Focused"] = false;
}
print("Focus Nodes KeysII: ${focusNodes.keys.toList()}");
print("Focus States KeysII: ${focusStates.keys.toList()}");
print("Text Controllers KeysII: ${controllers.keys.toList()}");
for (var key in focusNodes.keys) {
_addFocusListener(focusNodes[key]!, (focus) {
setState(() {
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
});
});
}
if (widget.groupId != null) {
@ -116,12 +137,24 @@ class GroupDataState extends State<GroupData> {
@override
void dispose() {
for (var node in focusNodes.values) {
node.dispose();
}
for (var controller in controllers.values) {
controller.dispose();
}
super.dispose();
}
void _addFocusListener(FocusNode node, Function(bool) updateState) {
node.addListener(() {
setState(() {
updateState(node.hasFocus);
});
});
}
void updateGroupDetails() {
print("Update - ${widget.groupData}");
@ -342,12 +375,16 @@ class GroupDataState extends State<GroupData> {
),
SizedBox(height: 5),
CustomTextFieldForexWrapper(
isFocused: false,
// isFocused: false,
isFocused: focusStates["nameFocused"] ?? false,
isDesktop: widget.isDesktop,
color: Colors.transparent,
child: SizedBox(
height: 40,
child: TextField(
focusNode: focusNodes["nameFocusNode"],
controller: controllers["name"],
style: const TextStyle(fontSize: 12),
decoration: const InputDecoration(
@ -383,16 +420,34 @@ class GroupDataState extends State<GroupData> {
),
SizedBox(height: 5),
CustomTextFieldForexWrapper(
isFocused: false,
isFocused:
focusStates["international_policy_nameFocused"] ?? false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 40,
child: Focus(
focusNode: focusNodes["international_policy_nameFocusNode"],
onFocusChange: (hasFocus) {
setState(() {
focusStates["international_policy_nameFocused"] =
hasFocus;
});
},
child: GestureDetector(
onTap: () {
// Request focus when user taps
focusNodes["international_policy_nameFocusNode"]
?.requestFocus();
},
child: DropdownSearch<String>(
selectedItem:
InternationalMap[selectedInternationalPolicyID],
popupProps: PopupProps.menu(
showSearchBox: true, // Enables search functionality
menuProps: const MenuProps(backgroundColor: Colors.white),
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
constraints: BoxConstraints(maxHeight: 250),
itemBuilder:
(context, item, isSelected) => Padding(
@ -409,7 +464,9 @@ class GroupDataState extends State<GroupData> {
decoration: InputDecoration(
hintText: "Search ...",
hintStyle: GoogleFonts.poppins(fontSize: 11),
contentPadding: EdgeInsets.symmetric(horizontal: 4),
contentPadding: EdgeInsets.symmetric(
horizontal: 4,
),
),
),
),
@ -417,6 +474,7 @@ class GroupDataState extends State<GroupData> {
dropdownDecoratorProps: DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(horizontal: 1),
),
),
@ -434,7 +492,9 @@ class GroupDataState extends State<GroupData> {
// Find the country_code based on selected country_name
selectedInternationalPolicyID =
InternationalMap.entries
.firstWhere((entry) => entry.value == newValue)
.firstWhere(
(entry) => entry.value == newValue,
)
.key;
selectedInternationalPolicyName = newValue;
});
@ -442,6 +502,8 @@ class GroupDataState extends State<GroupData> {
),
),
),
),
),
],
),
const SizedBox(height: 10),
@ -458,15 +520,31 @@ class GroupDataState extends State<GroupData> {
),
SizedBox(height: 5),
CustomTextFieldForexWrapper(
isFocused: false,
isFocused: focusStates["domestic_policy_nameFocused"] ?? false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 40,
child: Focus(
focusNode: focusNodes["domestic_policy_nameFocusNode"],
onFocusChange: (hasFocus) {
setState(() {
focusStates["domestic_policy_nameFocused"] = hasFocus;
});
},
child: GestureDetector(
//
onTap: () {
// Request focus when user taps
focusNodes["domestic_policy_nameFocusNode"]
?.requestFocus();
},
child: DropdownSearch<String>(
selectedItem: DomesticMap[selectedDomesticPolicyID],
popupProps: PopupProps.menu(
showSearchBox: true, // Enables search functionality
menuProps: const MenuProps(backgroundColor: Colors.white),
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
constraints: BoxConstraints(maxHeight: 250),
itemBuilder:
(context, object, isSelected) => Padding(
@ -483,7 +561,9 @@ class GroupDataState extends State<GroupData> {
decoration: InputDecoration(
hintText: "Search ...",
hintStyle: GoogleFonts.poppins(fontSize: 11),
contentPadding: EdgeInsets.symmetric(horizontal: 4),
contentPadding: EdgeInsets.symmetric(
horizontal: 4,
),
),
),
),
@ -508,7 +588,9 @@ class GroupDataState extends State<GroupData> {
// Find the country_code based on selected country_name
selectedDomesticPolicyID =
DomesticMap.entries
.firstWhere((entry) => entry.value == newValue)
.firstWhere(
(entry) => entry.value == newValue,
)
.key;
selectedDomesticPolicyName = newValue;
});
@ -516,6 +598,8 @@ class GroupDataState extends State<GroupData> {
),
),
),
),
),
],
),
const SizedBox(height: 10),
@ -532,13 +616,16 @@ class GroupDataState extends State<GroupData> {
),
SizedBox(height: 5),
CustomTextFieldForexWrapper(
isFocused: false,
isFocused: focusStates["descriptionFocused"] ?? false,
isDesktop: widget.isDesktop,
color: Colors.transparent,
child: SizedBox(
height: 100,
child: TextField(
controller: controllers["description"],
focusNode: focusNodes["descriptionFocusNode"],
style: const TextStyle(fontSize: 12),
maxLines: null,
expands: true,

View File

@ -6,6 +6,7 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../config/apiUrl.dart';
import '../services/apiService.dart';
class CustomDrawer extends StatefulWidget {
@ -116,7 +117,10 @@ class _CustomDrawerState extends State<CustomDrawer> {
String? rawLogoPath = selectedOrg?['logo'];
if (rawLogoPath != null && rawLogoPath.contains('/assets')) {
const baseUrl = "https://apitest.tripapprovaltool.com";
// const baseUrl = "https://apitest.tripapprovaltool.com";
const baseUrl = apiUrl;
final assetPath = rawLogoPath.split('/assets').last;
selectedOrg!['logo'] = "$baseUrl/assets$assetPath";
}
@ -139,13 +143,15 @@ class _CustomDrawerState extends State<CustomDrawer> {
@override
Widget build(BuildContext context) {
Widget drawerContent = Container(
// color: Colors.white,
color: Colors.white,
child: Container(
color: Colors.white,
margin: const EdgeInsets.all(18),
child: Column(
children: [
Container(
margin: const EdgeInsets.only(left: 20),
color: Colors.white,
// margin: const EdgeInsets.only(left: 20),
child: Column(
children: [
Row(
@ -156,7 +162,7 @@ class _CustomDrawerState extends State<CustomDrawer> {
? ClipRect(
child: Image.network(
selectedOrg!['logo'],
width: 100,
width: 50,
height: 50,
fit: BoxFit.contain,
errorBuilder: (context, error, stackTrace) {
@ -197,7 +203,7 @@ class _CustomDrawerState extends State<CustomDrawer> {
userData?["role"] == "Travel Admin")
_buildDrawerItem(
context,
Icons.insights_outlined,
Icons.format_list_bulleted_rounded,
'All Trips',
'/listAllPlan',
),
@ -205,15 +211,15 @@ class _CustomDrawerState extends State<CustomDrawer> {
if (userDetails["role"] == "Travel Agent")
_buildDrawerItem(
context,
Icons.assessment_outlined,
'My Approvals',
Icons.shopping_bag_outlined,
'Trips',
'/listTravelAgentPlan',
),
if (userDetails["role"] != "Travel Agent")
_buildDrawerItem(
context,
Icons.request_page_outlined,
Icons.shopping_bag_outlined,
'My Trips',
'/listPlan',
),
@ -221,33 +227,36 @@ class _CustomDrawerState extends State<CustomDrawer> {
if (userDetails["role"] != "Travel Agent")
_buildDrawerItem(
context,
Icons.assessment_outlined,
Icons.verified_outlined,
'My Approvals',
'/ApprovalList',
),
SizedBox(height: MediaQuery.of(context).size.height * 0.5),
// Spacer(),
SizedBox(height: MediaQuery.of(context).size.height / 2),
Container(
margin: const EdgeInsets.all(20),
margin: const EdgeInsets.only(right: 20),
child: Align(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Powered by",
style: TextStyle(
style: GoogleFonts.poppins(
fontSize: 11,
color: Color(0xFF212121),
color: Colors.grey,
// color: Color(0xFF212121),
),
),
Image.asset(
'assets/images/login/logoNew.jpg',
width: 90,
height: 25,
// width: 90,
height: 45,
fit: BoxFit.contain,
),
],
@ -255,13 +264,22 @@ class _CustomDrawerState extends State<CustomDrawer> {
],
),
),
),
],
),
),
);
return Drawer(
child: ListView(padding: EdgeInsets.zero, children: [drawerContent]),
return Container(
height: MediaQuery.of(context).size.height,
child: Drawer(
backgroundColor: Colors.white,
child: ListView(
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
children: [drawerContent],
),
),
);
// if (widget.isDesktop) {

View File

@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import '../utils/auth_utils.dart';
class CustomTextFieldForexWrapper extends StatefulWidget {
final Widget child;
final bool isFocused;
@ -27,33 +29,79 @@ class CustomTextFieldForexWrapper extends StatefulWidget {
class _CustomTextFieldForexWrapperState
extends State<CustomTextFieldForexWrapper> {
Color? layoutColor;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
loadInitialData();
});
}
void loadInitialData() async {
String? layoutString = await getLayoutColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
});
}
@override
Widget build(BuildContext context) {
return Container(
width: widget.width ?? // Use custom width if provided, else default
width:
widget.width ?? // Use custom width if provided, else default
(widget.isDesktop
? MediaQuery.of(context).size.width * 0.2
: MediaQuery.of(context).size.width * 0.8),
padding: widget.padding,
decoration: BoxDecoration(
color: widget.color,
// color: Color(0xFFF7F7FB),
// color: widget.color,
color: Colors.white,
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
width: widget.isFocused ? 2.0 : 0.5,
color: widget.isFocused ? layoutColor! : Color(0xFFD6D5E6),
// color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
width: widget.isFocused ? 1.0 : 0.5,
),
boxShadow: widget.isFocused
boxShadow:
widget.isFocused
? [
BoxShadow(
color: Color.fromRGBO(120, 180, 252, 0.3),
blurRadius: 10,
color: Colors.white,
// color: Color.fromRGBO(120, 180, 252, 0.3),
// color: Color.fromRGBO(120, 180, 252, 0.3),
blurRadius: 5,
spreadRadius: 2,
offset: Offset(0, 4),
offset: Offset(0, 1),
),
]
: [],
),
// decoration: BoxDecoration(
// color: widget.color,
// // color: Color(0xFFF7F7FB),
// borderRadius: BorderRadius.circular(10),
// border: Border.all(
// color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
// width: widget.isFocused ? 2.0 : 0.5,
// ),
// boxShadow: widget.isFocused
// ? [
// BoxShadow(
// color: Color.fromRGBO(120, 180, 252, 0.3),
// blurRadius: 10,
// spreadRadius: 2,
// offset: Offset(0, 4),
// ),
// ]
// : [],
// ),
child: widget.child,
);
}