diff --git a/app/ee/omnichannel/containers/CloseLivechatSheet/index.tsx b/app/ee/omnichannel/containers/CloseLivechatSheet/index.tsx deleted file mode 100644 index d1a03121a..000000000 --- a/app/ee/omnichannel/containers/CloseLivechatSheet/index.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; - -import ActionSheetContentWithInputAndSubmit from '../../../../containers/ActionSheet/ActionSheetContentWithInputAndSubmit'; -import I18n from '../../../../i18n'; - -const CloseLivechatSheet = ({ - onSubmit = () => {}, - onCancel = () => {} -}: { - onSubmit: (comment: string) => void; - onCancel: () => void; -}) => ( - -); - -export default CloseLivechatSheet; diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index fd5b85696..187264989 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -840,5 +840,7 @@ "Show_badge_for_mentions": "Show badge for mentions", "Show_badge_for_mentions_Info": "Display badge for direct mentions only", "error-init-video-conf": "Error starting video call", - "totp-invalid": "Code or password invalid" + "totp-invalid": "Code or password invalid", + "Close_Chat": "Close Chat", + "Select_tags": "Select tags" } \ No newline at end of file diff --git a/app/i18n/locales/pt-BR.json b/app/i18n/locales/pt-BR.json index ef59e82d8..020de9326 100644 --- a/app/i18n/locales/pt-BR.json +++ b/app/i18n/locales/pt-BR.json @@ -793,5 +793,7 @@ "Mark_as_unread_Info": "Mostrar sala como não lida quando houver mensagens não lidas", "Show_badge_for_mentions": "Mostrar contador para menções", "Show_badge_for_mentions_Info": "Mostrar contador somente para menções diretas", - "totp-invalid": "Código ou senha inválida" + "totp-invalid": "Código ou senha inválida", + "Close_Chat": "Fechar Conversa", + "Select_tags": "Selecionar tag(s)" } \ No newline at end of file diff --git a/app/lib/methods/helpers/closeLivechat.ts b/app/lib/methods/helpers/closeLivechat.ts index cff8a8a2b..ff49a0a66 100644 --- a/app/lib/methods/helpers/closeLivechat.ts +++ b/app/lib/methods/helpers/closeLivechat.ts @@ -7,14 +7,16 @@ import log from './log'; export const closeLivechat = async ({ rid, comment, - isMasterDetail + isMasterDetail, + tags }: { rid: string; isMasterDetail: boolean; comment?: string; + tags?: string[]; }) => { try { - await Services.closeLivechat(rid, comment); + await Services.closeLivechat(rid, comment, tags); if (isMasterDetail) { Navigation.navigate('DrawerNavigator'); } else { diff --git a/app/lib/services/restApi.ts b/app/lib/services/restApi.ts index cb97af0ac..27c72d048 100644 --- a/app/lib/services/restApi.ts +++ b/app/lib/services/restApi.ts @@ -18,6 +18,7 @@ import { getDeviceToken } from '../notifications'; import { RoomTypes, roomTypeToApiType, unsubscribeRooms } from '../methods'; import sdk from './sdk'; import { compareServerVersion, getBundleId, isIOS } from '../methods/helpers'; +import { ILivechatTag } from '../../definitions/ILivechatTag'; export const createChannel = ({ name, @@ -347,9 +348,15 @@ export const getTeamListRoom = ({ return sdk.get('teams.listRooms', params); }; -export const closeLivechat = (rid: string, comment?: string) => +export const closeLivechat = (rid: string, comment?: string, tags?: string[]) => { + // RC 3.2.0 + let params; + if (tags && tags?.length) { + params = { tags }; + } // RC 0.29.0 - sdk.methodCallWrapper('livechat:closeRoom', rid, comment, { clientAction: true }); + return sdk.methodCallWrapper('livechat:closeRoom', rid, comment, { clientAction: true, ...params }); +}; export const editLivechat = (userData: TParams, roomData: TParams): Promise<{ error?: string }> => // RC 0.55.0 @@ -398,13 +405,7 @@ export const getRoutingConfig = (): Promise<{ // RC 2.0.0 sdk.methodCallWrapper('livechat:getRoutingConfig'); -export const getTagsList = (): Promise< - { - _id: string; - name: string; - departments: string[]; - }[] -> => +export const getTagsList = (): Promise => // RC 2.0.0 sdk.methodCallWrapper('livechat:getTagsList'); diff --git a/app/stacks/InsideStack.tsx b/app/stacks/InsideStack.tsx index 6a525d575..ea17fee27 100644 --- a/app/stacks/InsideStack.tsx +++ b/app/stacks/InsideStack.tsx @@ -22,6 +22,7 @@ import AutoTranslateView from '../views/AutoTranslateView'; import DirectoryView from '../views/DirectoryView'; import NotificationPrefView from '../views/NotificationPreferencesView'; import ForwardLivechatView from '../views/ForwardLivechatView'; +import CloseLivechatView from '../views/CloseLivechatView'; import LivechatEditView from '../views/LivechatEditView'; import PickerView from '../views/PickerView'; import ThreadMessagesView from '../views/ThreadMessagesView'; @@ -116,6 +117,7 @@ const ChatsStackNavigator = () => { options={NotificationPrefView.navigationOptions} /> + { options={NotificationPrefView.navigationOptions} /> + diff --git a/app/stacks/MasterDetailStack/types.ts b/app/stacks/MasterDetailStack/types.ts index 9d69428a0..d5e871362 100644 --- a/app/stacks/MasterDetailStack/types.ts +++ b/app/stacks/MasterDetailStack/types.ts @@ -4,6 +4,8 @@ import { NavigatorScreenParams } from '@react-navigation/core'; import { IAttachment } from '../../definitions/IAttachment'; import { IMessage } from '../../definitions/IMessage'; import { ISubscription, SubscriptionType, TSubscriptionModel } from '../../definitions/ISubscription'; +import { ILivechatDepartment } from '../../definitions/ILivechatDepartment'; +import { ILivechatTag } from '../../definitions/ILivechatTag'; export type MasterDetailChatsStackParamList = { RoomView: { @@ -111,6 +113,12 @@ export type ModalStackParamList = { ForwardLivechatView: { rid: string; }; + CloseLivechatView: { + rid: string; + departmentId?: string; + departmentInfo?: ILivechatDepartment; + tagsList?: ILivechatTag[]; + }; CannedResponsesListView: { rid: string; }; diff --git a/app/stacks/types.ts b/app/stacks/types.ts index 6265b3aaa..d09d37f0c 100644 --- a/app/stacks/types.ts +++ b/app/stacks/types.ts @@ -11,6 +11,8 @@ import { ICannedResponse } from '../definitions/ICannedResponse'; import { TDataSelect } from '../definitions/IDataSelect'; import { ModalStackParamList } from './MasterDetailStack/types'; import { TThreadModel } from '../definitions'; +import { ILivechatDepartment } from '../definitions/ILivechatDepartment'; +import { ILivechatTag } from '../definitions/ILivechatTag'; export type ChatsStackParamList = { ModalStackNavigator: NavigatorScreenParams; @@ -114,6 +116,12 @@ export type ChatsStackParamList = { ForwardLivechatView: { rid: string; }; + CloseLivechatView: { + rid: string; + departmentId?: string; + departmentInfo?: ILivechatDepartment; + tagsList?: ILivechatTag[]; + }; LivechatEditView: { room: ISubscription; roomUser: any; // TODO: Change diff --git a/app/views/CloseLivechatView.tsx b/app/views/CloseLivechatView.tsx new file mode 100644 index 000000000..5490bb57e --- /dev/null +++ b/app/views/CloseLivechatView.tsx @@ -0,0 +1,122 @@ +import React, { useState, useLayoutEffect } from 'react'; +import { StyleSheet, ScrollView, Text } from 'react-native'; +import { BlockContext } from '@rocket.chat/ui-kit'; + +import { IBaseScreen } from '../definitions'; +import I18n from '../i18n'; +import { ChatsStackParamList } from '../stacks/types'; +import { useTheme } from '../theme'; +import KeyboardView from '../containers/KeyboardView'; +import SafeAreaView from '../containers/SafeAreaView'; +import { FormTextInput } from '../containers/TextInput'; +import Button from '../containers/Button'; +import { useAppSelector } from '../lib/hooks'; +import sharedStyles from './Styles'; +import scrollPersistTaps from '../lib/methods/helpers/scrollPersistTaps'; +import { MultiSelect } from '../containers/UIKit/MultiSelect'; +import { closeLivechat } from '../lib/methods/helpers/closeLivechat'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: 16 + }, + subtitleText: { + marginBottom: 10, + fontSize: 14, + ...sharedStyles.textSemibold + }, + buttonMarginVertical: { marginVertical: 20 } +}); + +const CloseLivechatView = ({ navigation, route }: IBaseScreen) => { + const rid = route.params?.rid; + const departmentInfo = route.params?.departmentInfo; + const tagsList = route.params?.tagsList; + const requestTags = departmentInfo?.requestTagBeforeClosingChat; + + const [inputValue, setInputValue] = useState(''); + const [tagParamSelected, setTagParamSelected] = useState([]); + + const { colors } = useTheme(); + + const { isMasterDetail, livechatRequestComment } = useAppSelector(state => ({ + isMasterDetail: state.app.isMasterDetail, + livechatRequestComment: state.settings.Livechat_request_comment_when_closing_conversation as boolean + })); + + useLayoutEffect(() => { + navigation.setOptions({ + title: I18n.t('Close_Chat') + }); + }, [navigation]); + + const canSubmit = () => { + if (!requestTags && !livechatRequestComment) { + return true; + } + if (requestTags && tagParamSelected.length > 0 && !livechatRequestComment) { + return true; + } + if (livechatRequestComment && !!inputValue && !requestTags) { + return true; + } + if (livechatRequestComment && requestTags && tagParamSelected.length > 0 && !!inputValue) { + return true; + } + return false; + }; + + const submit = () => { + closeLivechat({ rid, isMasterDetail, comment: inputValue, tags: tagParamSelected }); + }; + + return ( + + + + setInputValue(text)} + onSubmitEditing={() => { + if (canSubmit()) { + submit(); + } + }} + /> + + {requestTags ? ( + <> + {I18n.t('Tags')} + ({ text: { text: name }, value: name }))} + onChange={({ value }: { value: string[] }) => { + setTagParamSelected(value); + }} + placeholder={{ text: I18n.t('Select_tags') }} + value={tagParamSelected} + context={BlockContext.FORM} + multiselect + inputStyle={{ borderColor: colors.separatorColor, borderWidth: 2 }} + /> + + ) : null} +