diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 465c5af..fe95696 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -35,17 +35,19 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await buildHubConnection(); } - void getChatMemberFromSearch(String sName, int cUserId) async { - isLoading = true; - notifyListeners(); + Future?> getChatMemberFromSearch(String sName, int cUserId) async { Response response = await ApiClient().getJsonForResponse( - "${ApiConsts.chatSearchMember}$sName/$cUserId", + "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSearchMember}$sName/$cUserId", token: AppState().chatDetails!.response!.token, ); + return searchUserJsonModel(response.body); + logger.d(response.body); isLoading = false; notifyListeners(); } + List searchUserJsonModel(String str) => List.from(json.decode(str).map((x) => ChatUser.fromJson(x))); + void getUserRecentChats() async { Response response = await ApiClient().getJsonForResponse( "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}", @@ -64,8 +66,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$pagination", token: AppState().chatDetails!.response!.token, ); - logger.d(response.body); - userChatHistory = getSingleUserChatintoModel(response.body); + logger.d(response.statusCode); + print(response.body); + if (response.statusCode == 204) { + print(null); + userChatHistory = []; + } else { + userChatHistory = getSingleUserChatintoModel(response.body); + } isLoading = false; notifyListeners(); } @@ -79,7 +87,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { hubConnection = await HubConnectionBuilder() .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]) - .configureLogging(Logger("Logs Enabled")) + .configureLogging( + Logger("Logs Enabled"), + ) .build(); hubConnection.onclose( ({Exception? error}) { @@ -159,7 +169,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // print("================= Status Online // Offline ===================="); List items = args!.toList(); logger.d(items); - for (var user in searchedChats!) { + for (ChatUser user in searchedChats!) { if (user.id == items.first["id"]) { user.userStatus = items.first["userStatus"]; } @@ -172,7 +182,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { if (value.isEmpty || value == "") { tmp = pChatHistory; } else { - for (var element in pChatHistory!) { + for (ChatUser element in pChatHistory!) { if (element.userName!.toLowerCase().contains(value.toLowerCase())) { tmp.add(element); } diff --git a/lib/ui/attendance/add_vacation_rule_screen.dart b/lib/ui/attendance/add_vacation_rule_screen.dart index 4846053..aa48696 100644 --- a/lib/ui/attendance/add_vacation_rule_screen.dart +++ b/lib/ui/attendance/add_vacation_rule_screen.dart @@ -433,6 +433,7 @@ class _AddVacationRuleScreenState extends State { child: SearchEmployeeBottomSheet( title: LocaleKeys.searchForEmployee.tr(), apiMode: LocaleKeys.delegate.tr(), + fromChat: false, onSelectEmployee: (_selectedEmployee) { // Navigator.pop(context); selectedReplacementEmployee = _selectedEmployee; diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 18c11bf..ef984a3 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -163,6 +163,7 @@ class _ChatHomeScreenState extends State { child: SearchEmployeeBottomSheet( title: LocaleKeys.searchForEmployee.tr(), apiMode: LocaleKeys.delegate.tr(), + fromChat: true, onSelectEmployee: (_selectedEmployee) { // Navigator.pop(context); // selectedReplacementEmployee = _selectedEmployee; diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index eb8e493..81cfe0f 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -224,6 +224,7 @@ class _AddLeaveBalanceScreenState extends State { child: SearchEmployeeBottomSheet( title: LocaleKeys.searchForEmployee.tr(), apiMode: LocaleKeys.delegate.tr(), + fromChat: false, onSelectEmployee: (_selectedEmployee) { // Navigator.pop(context); selectedReplacementEmployee = _selectedEmployee; diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index e807a7b..14da765 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -1,14 +1,21 @@ +import 'dart:convert'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; import 'package:mohem_flutter_app/api/worklist/worklist_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; import 'package:mohem_flutter_app/models/get_action_history_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart'; import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart'; @@ -21,17 +28,19 @@ class SearchEmployeeBottomSheet extends StatefulWidget { String title, apiMode; List? actionHistoryList; Function(ReplacementList) onSelectEmployee; + bool fromChat; - SearchEmployeeBottomSheet( - {required this.title, - required this.apiMode, - this.notificationID, - this.actionHistoryList, - required this.onSelectEmployee}); + SearchEmployeeBottomSheet({ + required this.title, + required this.apiMode, + this.notificationID, + this.actionHistoryList, + required this.onSelectEmployee, + required this.fromChat, + }); @override - State createState() => - _SearchEmployeeBottomSheetState(); + State createState() => _SearchEmployeeBottomSheetState(); } class _SearchEmployeeBottomSheetState extends State { @@ -49,6 +58,9 @@ class _SearchEmployeeBottomSheetState extends State { List? favouriteUserList; List? nonFavouriteUserList; + // Chat Items + List? chatUsersList = []; + int _selectedSearchIndex = 0; void fetchUserByInput({bool isNeedLoading = true}) async { @@ -59,12 +71,30 @@ class _SearchEmployeeBottomSheetState extends State { userId: _selectedSearchIndex == 1 ? searchText : "", email: _selectedSearchIndex == 2 ? searchText : "", ); - favouriteUserList = replacementList - ?.where((element) => element.isFavorite ?? false) - .toList(); - nonFavouriteUserList = replacementList - ?.where((element) => !(element.isFavorite ?? false)) - .toList(); + favouriteUserList = replacementList?.where((element) => element.isFavorite ?? false).toList(); + nonFavouriteUserList = replacementList?.where((element) => !(element.isFavorite ?? false)).toList(); + Utils.hideLoading(context); + setState(() {}); + } catch (e) { + Utils.hideLoading(context); + Utils.handleException(e, context, null); + } + + if (isNeedLoading) Utils.hideLoading(context); + setState(() {}); + return null; + } + + void fetchChatUser({bool isNeedLoading = true}) async { + try { + Utils.showLoading(context); + + chatUsersList = await ChatProviderModel().getChatMemberFromSearch(searchText, int.parse(AppState().chatDetails!.response!.id.toString())); + print("================================"); + print(jsonEncode(chatUsersList)); + // + // favouriteUserList = replacementList?.where((element) => element.isFavorite ?? false).toList(); + // nonFavouriteUserList = replacementList?.where((element) => !(element.isFavorite ?? false)).toList(); Utils.hideLoading(context); setState(() {}); } catch (e) { @@ -114,57 +144,113 @@ class _SearchEmployeeBottomSheetState extends State { IconButton( constraints: const BoxConstraints(), onPressed: () async { - await SystemChannels.textInput - .invokeMethod('TextInput.hide'); - fetchUserByInput(); + await SystemChannels.textInput.invokeMethod('TextInput.hide'); + widget.fromChat ? fetchChatUser() : fetchUserByInput(); }, icon: Icon(Icons.search)) ], ), + if (replacementList != null) replacementList!.isEmpty ? Utils.getNoDataWidget(context).expanded - : ListView( - physics: const BouncingScrollPhysics(), - padding: EdgeInsets.only(top: 21, bottom: 8), - children: [ - if (favouriteUserList?.isNotEmpty ?? false) ...[ - "Favorites".toText16(), - 12.height, - ListView.separated( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (cxt, index) => - employeeItemView(favouriteUserList![index]), - separatorBuilder: (cxt, index) => Container( - height: 1, - color: MyColors.borderE3Color, - ), - itemCount: favouriteUserList?.length ?? 0), - 12.height, - ], - if (nonFavouriteUserList?.isNotEmpty ?? false) ...[ - "Related".toText16(), - 12.height, - ListView.separated( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (cxt, index) => employeeItemView( - nonFavouriteUserList![index]), - separatorBuilder: (cxt, index) => Container( - height: 1, - color: MyColors.borderE3Color, + : ListView( + physics: const BouncingScrollPhysics(), + padding: EdgeInsets.only(top: 21, bottom: 8), + children: [ + if (favouriteUserList?.isNotEmpty ?? false) ...[ + "Favorites".toText16(), + 12.height, + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (cxt, index) => employeeItemView(favouriteUserList![index]), + separatorBuilder: (cxt, index) => Container( + height: 1, + color: MyColors.borderE3Color, + ), + itemCount: favouriteUserList?.length ?? 0), + 12.height, + ], + if (nonFavouriteUserList?.isNotEmpty ?? false) ...[ + "Related".toText16(), + 12.height, + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (cxt, index) => employeeItemView(nonFavouriteUserList![index]), + separatorBuilder: (cxt, index) => Container( + height: 1, + color: MyColors.borderE3Color, + ), + itemCount: nonFavouriteUserList?.length ?? 0), + ] + ], + ).expanded, + + if(widget.fromChat) + if (chatUsersList != null && widget.fromChat) + chatUsersList!.isEmpty + ? Utils.getNoDataWidget(context) + : ListView( + physics: const BouncingScrollPhysics(), + padding: EdgeInsets.only(top: 0, bottom: 8), + children: [ + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + + itemBuilder: (cxt, index) { + return ListTile( + leading: Stack( + children: [ + SvgPicture.asset( + "assets/images/user.svg", + height: 48, + width: 48, + ), + Positioned( + right: 5, + bottom: 1, + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: chatUsersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), + ), ), - itemCount: nonFavouriteUserList?.length ?? 0), - ] - ], - ).expanded + ) + ], + ), + title: (chatUsersList![index].userName ?? "").toText14(color: MyColors.darkTextColor), + subtitle: (chatUsersList![index].isTyping == true ? "Something is Typing" : "Last message text").toText11(color: MyColors.normalTextColor), + trailing: ("Today").toText10(color: MyColors.lightTextColor), + minVerticalPadding: 0, + onTap: () { + Navigator.pop(context); + Navigator.pushNamed( + context, + AppRoutes.chatDetailed, + arguments: {"targetUser": chatUsersList![index]}, + ); + }, + ); + }, + separatorBuilder: (cxt, index) => Container( + height: 1, + color: MyColors.borderE3Color, + ), + itemCount: chatUsersList?.length ?? 0), + 12.height, + ], + ).expanded, ], ).paddingOnly(left: 21, right: 21, bottom: 0, top: 21).expanded, - Container( - width: double.infinity, - height: 1, - color: MyColors.lightGreyEFColor), + + Container(width: double.infinity, height: 1, color: MyColors.lightGreyEFColor), DefaultButton( LocaleKeys.cancel.tr(), () { @@ -201,11 +287,7 @@ class _SearchEmployeeBottomSheetState extends State { Expanded( child: (replacement.employeeDisplayName ?? "").toText12(), ), - Icon(Icons.star, - size: 16, - color: replacement.isFavorite! - ? MyColors.yellowFavColor - : MyColors.borderCEColor), + Icon(Icons.star, size: 16, color: replacement.isFavorite! ? MyColors.yellowFavColor : MyColors.borderCEColor), ], ), ), @@ -228,9 +310,7 @@ class _SearchEmployeeBottomSheetState extends State { width: double.infinity, height: double.infinity, decoration: BoxDecoration( - color: value == groupValue - ? MyColors.grey3AColor - : Colors.transparent, + color: value == groupValue ? MyColors.grey3AColor : Colors.transparent, borderRadius: BorderRadius.all(const Radius.circular(100)), ), ),