From d89e3fac8e7022ace142f436d19782fc39282119 Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Wed, 19 Feb 2025 17:53:20 +0400 Subject: [PATCH 1/5] change endpoint --- lib/services/user_permission.dart | 2 +- lib/utils/constants/api_const.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/services/user_permission.dart b/lib/services/user_permission.dart index a3fb2d96..3f02663d 100644 --- a/lib/services/user_permission.dart +++ b/lib/services/user_permission.dart @@ -14,7 +14,7 @@ class UserPermissionApi { Future> fetchUsers(String projectId) async { try { final response = await _httpService.get( - path: ApiEndpoints.getUsers.replaceAll('{projectUuid}', projectId), + path: ApiEndpoints.getUsers.replaceAll('{projectId}', projectId), showServerMessage: true, expectedResponseModel: (json) { debugPrint('fetchUsers Response: $json'); diff --git a/lib/utils/constants/api_const.dart b/lib/utils/constants/api_const.dart index 72a2b778..c7a91e1a 100644 --- a/lib/utils/constants/api_const.dart +++ b/lib/utils/constants/api_const.dart @@ -95,8 +95,8 @@ abstract class ApiEndpoints { static const String inviteUser = '/invite-user'; static const String checkEmail = '/invite-user/check-email'; - static const String getUsers = '/projects/{projectUuid}/user'; - static const String getUserById = '/projects/{projectUuid}/user/{userUuid}'; + static const String getUsers = '/projects/{projectId}/user'; + static const String getUserById = '/projects/{projectId}/user/{userUuid}'; static const String editUser = '/invite-user/{inviteUserUuid}'; static const String deleteUser = '/invite-user/{inviteUserUuid}'; static const String changeUserStatus = '/invite-user/{invitedUserUuid}/disable'; From eafb811d2e78d766b4c01922ba38e1dda1b933a5 Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Thu, 20 Feb 2025 11:26:30 +0400 Subject: [PATCH 2/5] fixed cursor issue --- lib/common/dialog_textfield_dropdown.dart | 106 +++++++++++----------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/lib/common/dialog_textfield_dropdown.dart b/lib/common/dialog_textfield_dropdown.dart index 807f3417..9c508f28 100644 --- a/lib/common/dialog_textfield_dropdown.dart +++ b/lib/common/dialog_textfield_dropdown.dart @@ -20,15 +20,22 @@ class DialogTextfieldDropdown extends StatefulWidget { class _DialogTextfieldDropdownState extends State { bool _isOpen = false; - late OverlayEntry _overlayEntry; + OverlayEntry? _overlayEntry; final TextEditingController _controller = TextEditingController(); - late List _filteredItems; // Filtered items list + final FocusNode _focusNode = FocusNode(); + List _filteredItems = []; @override void initState() { super.initState(); - _controller.text = widget.initialValue ?? 'Select Tag'; - _filteredItems = List.from(widget.items); // Initialize filtered items + _controller.text = widget.initialValue ?? ''; + _filteredItems = List.from(widget.items); + + _focusNode.addListener(() { + if (!_focusNode.hasFocus) { + _closeDropdown(); + } + }); } void _toggleDropdown() { @@ -41,13 +48,16 @@ class _DialogTextfieldDropdownState extends State { void _openDropdown() { _overlayEntry = _createOverlayEntry(); - Overlay.of(context).insert(_overlayEntry); + Overlay.of(context).insert(_overlayEntry!); _isOpen = true; } void _closeDropdown() { - _overlayEntry.remove(); - _isOpen = false; + if (_isOpen && _overlayEntry != null) { + _overlayEntry!.remove(); + _overlayEntry = null; + _isOpen = false; + } } OverlayEntry _createOverlayEntry() { @@ -58,9 +68,7 @@ class _DialogTextfieldDropdownState extends State { return OverlayEntry( builder: (context) { return GestureDetector( - onTap: () { - _closeDropdown(); - }, + onTap: _closeDropdown, behavior: HitTestBehavior.translucent, child: Stack( children: [ @@ -72,40 +80,26 @@ class _DialogTextfieldDropdownState extends State { elevation: 4.0, child: Container( color: ColorsManager.whiteColors, - constraints: const BoxConstraints( - maxHeight: 200.0, - ), - child: ListView.builder( - shrinkWrap: true, - itemCount: _filteredItems.length, - itemBuilder: (context, index) { - final item = _filteredItems[index]; - return Container( - decoration: const BoxDecoration( - border: Border( - bottom: BorderSide( - color: ColorsManager.lightGrayBorderColor, - width: 1.0, + constraints: const BoxConstraints(maxHeight: 200.0), + child: StatefulBuilder( + builder: (context, setStateDropdown) { + return ListView.builder( + shrinkWrap: true, + itemCount: _filteredItems.length, + itemBuilder: (context, index) { + final item = _filteredItems[index]; + return ListTile( + title: Text( + item, + style: const TextStyle(color: Colors.black), ), - ), - ), - child: ListTile( - title: Text(item, - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith( - color: ColorsManager.textPrimaryColor)), - onTap: () { - _controller.text = item; - widget.onSelected(item); - setState(() { - _filteredItems - .remove(item); // Remove selected item - }); - _closeDropdown(); - }, - ), + onTap: () { + _controller.text = item; + widget.onSelected(item); + _closeDropdown(); + }, + ); + }, ); }, ), @@ -122,7 +116,8 @@ class _DialogTextfieldDropdownState extends State { @override Widget build(BuildContext context) { return GestureDetector( - onTap: _toggleDropdown, + onTap: () => FocusScope.of(context).unfocus(), + behavior: HitTestBehavior.opaque, child: Container( padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0), decoration: BoxDecoration( @@ -135,23 +130,26 @@ class _DialogTextfieldDropdownState extends State { Expanded( child: TextFormField( controller: _controller, - onChanged: (value) { - setState(() { - _filteredItems = widget.items - .where((item) => - item.toLowerCase().contains(value.toLowerCase())) - .toList(); // Filter items dynamically - }); + focusNode: _focusNode, + onFieldSubmitted: (value) { widget.onSelected(value); + _closeDropdown(); }, - style: Theme.of(context).textTheme.bodyMedium, + onTapOutside: (event) { + widget.onSelected(_controller.text); + _closeDropdown(); + }, + style: const TextStyle(color: Colors.black), decoration: const InputDecoration( - hintText: 'Enter or Select tag', + hintText: 'Enter or Select a tag', border: InputBorder.none, ), ), ), - const Icon(Icons.arrow_drop_down), + GestureDetector( + onTap: _toggleDropdown, + child: const Icon(Icons.arrow_drop_down), + ), ], ), ), From 57c5f4752c224b75489d3dff6fa3946af24ac471 Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Thu, 20 Feb 2025 11:36:08 +0400 Subject: [PATCH 3/5] fixed theme --- lib/common/dialog_textfield_dropdown.dart | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/common/dialog_textfield_dropdown.dart b/lib/common/dialog_textfield_dropdown.dart index 9c508f28..a63f095a 100644 --- a/lib/common/dialog_textfield_dropdown.dart +++ b/lib/common/dialog_textfield_dropdown.dart @@ -89,10 +89,13 @@ class _DialogTextfieldDropdownState extends State { itemBuilder: (context, index) { final item = _filteredItems[index]; return ListTile( - title: Text( - item, - style: const TextStyle(color: Colors.black), - ), + title: Text(item, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + color: + ColorsManager.textPrimaryColor)), onTap: () { _controller.text = item; widget.onSelected(item); @@ -139,7 +142,7 @@ class _DialogTextfieldDropdownState extends State { widget.onSelected(_controller.text); _closeDropdown(); }, - style: const TextStyle(color: Colors.black), + style: Theme.of(context).textTheme.bodyMedium, decoration: const InputDecoration( hintText: 'Enter or Select a tag', border: InputBorder.none, From 7ee7681e09b3e98307cca3e62d19a90896163cbc Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Thu, 20 Feb 2025 11:47:58 +0400 Subject: [PATCH 4/5] fixed theme --- lib/common/dialog_textfield_dropdown.dart | 41 ++++++++++++++++------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/lib/common/dialog_textfield_dropdown.dart b/lib/common/dialog_textfield_dropdown.dart index a63f095a..ac88e5dc 100644 --- a/lib/common/dialog_textfield_dropdown.dart +++ b/lib/common/dialog_textfield_dropdown.dart @@ -88,19 +88,34 @@ class _DialogTextfieldDropdownState extends State { itemCount: _filteredItems.length, itemBuilder: (context, index) { final item = _filteredItems[index]; - return ListTile( - title: Text(item, - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith( - color: - ColorsManager.textPrimaryColor)), - onTap: () { - _controller.text = item; - widget.onSelected(item); - _closeDropdown(); - }, + + return Container( + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide( + color: ColorsManager.lightGrayBorderColor, + width: 1.0, + ), + ), + ), + child: ListTile( + title: Text(item, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + color: ColorsManager + .textPrimaryColor)), + onTap: () { + _controller.text = item; + widget.onSelected(item); + setState(() { + _filteredItems + .remove(item); // Remove selected item + }); + _closeDropdown(); + }, + ), ); }, ); From e634154fb326b26cc7485d4cbecf18505deb0ef5 Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Thu, 20 Feb 2025 13:31:31 +0400 Subject: [PATCH 5/5] fixed device endpoint --- lib/utils/constants/api_const.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/constants/api_const.dart b/lib/utils/constants/api_const.dart index c7a91e1a..1022d734 100644 --- a/lib/utils/constants/api_const.dart +++ b/lib/utils/constants/api_const.dart @@ -25,7 +25,7 @@ abstract class ApiEndpoints { ////// Devices Management //////////////// - static const String getAllDevices = '/projects/{projectId}/device'; + static const String getAllDevices = '/projects/{projectId}/devices'; static const String getSpaceDevices = '/projects/{projectId}/communities/{communityUuid}/spaces/{spaceUuid}/devices'; static const String getDeviceStatus = '/device/{uuid}/functions/status';