From 765ad7909907a5c03de593aa999fdc4af5d4910d Mon Sep 17 00:00:00 2001 From: MyNameIsBatman Date: Sat, 4 Dec 2021 14:43:06 -0300 Subject: [PATCH] Updates --- .../card/header/NitroCardHeaderView.tsx | 6 +- .../card/header/NitroCardHeaderView.types.ts | 1 + src/views/guide-tool/GuideToolView.scss | 4 + src/views/guide-tool/GuideToolView.tsx | 224 +++++++++++++++--- .../guide-tool/common/GuideToolMessage.ts | 21 ++ .../common/GuideToolMessageGroup.ts | 28 +++ src/views/guide-tool/common/index.ts | 1 + .../guide-accept/GuideToolAcceptView.tsx | 2 +- .../guide-accept/GuideToolAcceptView.types.ts | 3 +- .../views/ongoing/GuideToolOngoingView.scss | 50 ++++ .../views/ongoing/GuideToolOngoingView.tsx | 108 ++++++++- .../ongoing/GuideToolOngoingView.types.ts | 4 + .../GuideToolUserCreateRequestView.scss | 12 + .../GuideToolUserCreateRequestView.tsx | 29 +++ .../GuideTooluserCreateRequestView.types.ts | 5 + .../GuideToolUserFeedbackView.tsx | 40 ++++ .../GuideToolUserFeedbackView.types.ts | 4 + .../user-pending/GuideToolUserPendingView.tsx | 32 +++ .../GuideToolUserPendingView.types.ts | 5 + .../GuideToolUserThanksView.tsx} | 8 +- 20 files changed, 526 insertions(+), 61 deletions(-) create mode 100644 src/views/guide-tool/common/GuideToolMessage.ts create mode 100644 src/views/guide-tool/common/GuideToolMessageGroup.ts create mode 100644 src/views/guide-tool/views/ongoing/GuideToolOngoingView.scss create mode 100644 src/views/guide-tool/views/user-create-request/GuideToolUserCreateRequestView.scss create mode 100644 src/views/guide-tool/views/user-create-request/GuideToolUserCreateRequestView.tsx create mode 100644 src/views/guide-tool/views/user-create-request/GuideTooluserCreateRequestView.types.ts create mode 100644 src/views/guide-tool/views/user-feedback/GuideToolUserFeedbackView.tsx create mode 100644 src/views/guide-tool/views/user-feedback/GuideToolUserFeedbackView.types.ts create mode 100644 src/views/guide-tool/views/user-pending/GuideToolUserPendingView.tsx create mode 100644 src/views/guide-tool/views/user-pending/GuideToolUserPendingView.types.ts rename src/views/guide-tool/views/{user-create-request/GuildToolUserCreateRequestView.tsx => user-thanks/GuideToolUserThanksView.tsx} (52%) diff --git a/src/layout/card/header/NitroCardHeaderView.tsx b/src/layout/card/header/NitroCardHeaderView.tsx index 293f163a..23633c02 100644 --- a/src/layout/card/header/NitroCardHeaderView.tsx +++ b/src/layout/card/header/NitroCardHeaderView.tsx @@ -4,7 +4,7 @@ import { NitroCardHeaderViewProps } from './NitroCardHeaderView.types'; export const NitroCardHeaderView: FC = props => { - const { headerText = null, onCloseClick = null, theme = 'primary' } = props; + const { headerText = null, onCloseClick = null, theme = 'primary', noCloseButton = false } = props; const { simple = false } = useNitroCardContext(); const onMouseDown = useCallback((event: MouseEvent) => @@ -20,9 +20,9 @@ export const NitroCardHeaderView: FC = props =>
{ headerText }
-
+ { !noCloseButton &&
-
+
}
diff --git a/src/layout/card/header/NitroCardHeaderView.types.ts b/src/layout/card/header/NitroCardHeaderView.types.ts index 7a5c7e88..25bc13d0 100644 --- a/src/layout/card/header/NitroCardHeaderView.types.ts +++ b/src/layout/card/header/NitroCardHeaderView.types.ts @@ -4,5 +4,6 @@ export interface NitroCardHeaderViewProps { headerText: string; theme?: string; + noCloseButton?: boolean; onCloseClick: (event: MouseEvent) => void; } diff --git a/src/views/guide-tool/GuideToolView.scss b/src/views/guide-tool/GuideToolView.scss index ab7f4aec..2f903155 100644 --- a/src/views/guide-tool/GuideToolView.scss +++ b/src/views/guide-tool/GuideToolView.scss @@ -24,4 +24,8 @@ height: 24px; background-image: url(../../assets/images/guide-tool/guide_tool_info_icon.png); } + + + @import './views/user-create-request/GuideToolUserCreateRequestView'; + @import './views/ongoing/GuideToolOngoingView'; } diff --git a/src/views/guide-tool/GuideToolView.tsx b/src/views/guide-tool/GuideToolView.tsx index 1382bdea..ff34c65a 100644 --- a/src/views/guide-tool/GuideToolView.tsx +++ b/src/views/guide-tool/GuideToolView.tsx @@ -1,19 +1,24 @@ -import { GuideOnDutyStatusMessageEvent, GuideSessionAttachedMessageEvent, GuideSessionOnDutyUpdateMessageComposer, GuideSessionStartedMessageEvent, ILinkEventTracker, PerkAllowancesMessageEvent, PerkEnum } from '@nitrots/nitro-renderer'; +import { GuideOnDutyStatusMessageEvent, GuideSessionAttachedMessageEvent, GuideSessionDetachedMessageEvent, GuideSessionEndedMessageEvent, GuideSessionInvitedToGuideRoomMessageEvent, GuideSessionMessageMessageEvent, GuideSessionOnDutyUpdateMessageComposer, GuideSessionPartnerIsTypingMessageEvent, GuideSessionStartedMessageEvent, ILinkEventTracker, PerkAllowancesMessageEvent, PerkEnum } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useState } from 'react'; -import { AddEventLinkTracker, GetConfiguration, LocalizeText, RemoveLinkEventTracker } from '../../api'; +import { AddEventLinkTracker, GetConfiguration, GetSessionDataManager, LocalizeText, RemoveLinkEventTracker } from '../../api'; import { GuideToolEvent, NotificationAlertEvent } from '../../events'; import { CreateMessageHook, dispatchUiEvent, SendMessageHook, useUiEvent } from '../../hooks'; import { NitroCardHeaderView, NitroCardView } from '../../layout'; -import { GuideSessionState } from './common'; +import { GuideSessionState, GuideToolMessageGroup } from './common'; +import { GuideToolMessage } from './common/GuideToolMessage'; import { GuideToolAcceptView } from './views/guide-accept/GuideToolAcceptView'; import { GuideToolMenuView } from './views/guide-tool-menu/GuideToolMenuView'; import { GuideToolOngoingView } from './views/ongoing/GuideToolOngoingView'; -import { GuildToolUserCreateRequestView } from './views/user-create-request/GuildToolUserCreateRequestView'; +import { GuideToolUserCreateRequestView } from './views/user-create-request/GuideToolUserCreateRequestView'; +import { GuideToolUserFeedbackView } from './views/user-feedback/GuideToolUserFeedbackView'; +import { GuideToolUserPendingView } from './views/user-pending/GuideToolUserPendingView'; +import { GuideToolUserThanksView } from './views/user-thanks/GuideToolUserThanksView'; export const GuideToolView: FC<{}> = props => { const [ isVisible, setIsVisible ] = useState(false); const [ headerText, setHeaderText ] = useState(LocalizeText('guide.help.guide.tool.title')); + const [ noCloseButton, setNoCloseButton ] = useState(false); const [ sessionState, setSessionState ] = useState(GuideSessionState.GUIDE_TOOL_MENU); const [ isOnDuty, setIsOnDuty ] = useState(false); @@ -25,12 +30,58 @@ export const GuideToolView: FC<{}> = props => const [ guidesOnDuty, setGuidesOnDuty ] = useState(0); const [ guardiansOnDuty, setGuardiansOnDuty ] = useState(0); + const [ userRequest, setUserRequest ] = useState(''); + const [ helpRequestDescription, setHelpRequestDescription ] = useState(null); - const [ helpRequestCountdown, setHelpRequestCountdown ] = useState(0); + const [ helpRequestAverageTime, setHelpRequestAverageTime ] = useState(0); const [ ongoingUserId, setOngoingUserId ] = useState(0); const [ ongoingUsername, setOngoingUsername ] = useState(null); const [ ongoingFigure, setOngoingFigure ] = useState(null); + const [ ongoingIsTyping, setOngoingIsTyping ] = useState(false); + const [ ongoingMessageGroups, setOngoingMessageGroups ] = useState([]); + + const updateSessionState = useCallback((newState: string, replacement?: string) => + { + switch(newState) + { + case GuideSessionState.GUIDE_TOOL_MENU: + setHeaderText(LocalizeText('guide.help.guide.tool.title')); + setNoCloseButton(false); + break; + case GuideSessionState.GUIDE_ACCEPT: + setHeaderText(LocalizeText('guide.help.request.guide.accept.title')); + setNoCloseButton(true); + break; + case GuideSessionState.GUIDE_ONGOING: + setHeaderText(LocalizeText('guide.help.request.guide.ongoing.title', ['name'], [replacement])); + setNoCloseButton(true); + break; + case GuideSessionState.USER_CREATE: + setHeaderText(LocalizeText('guide.help.request.user.create.title')); + setNoCloseButton(false); + break; + case GuideSessionState.USER_PENDING: + setHeaderText(LocalizeText('guide.help.request.user.pending.title')); + setNoCloseButton(true); + break; + case GuideSessionState.USER_ONGOING: + setHeaderText(LocalizeText('guide.help.request.user.ongoing.title', ['name'], [replacement])); + setNoCloseButton(true); + break; + case GuideSessionState.USER_FEEDBACK: + setHeaderText(LocalizeText('guide.help.request.user.feedback.title')); + setNoCloseButton(true); + break; + case GuideSessionState.USER_THANKS: + setHeaderText(LocalizeText('guide.help.request.user.thanks.title')); + setNoCloseButton(false); + break; + } + + setSessionState(newState); + setIsVisible(true); + }, []); const onGuideToolEvent = useCallback((event: GuideToolEvent) => { @@ -46,12 +97,10 @@ export const GuideToolView: FC<{}> = props => setIsVisible(value => !value); return; case GuideToolEvent.CREATE_HELP_REQUEST: - setSessionState(GuideSessionState.USER_CREATE); - setHeaderText(LocalizeText('guide.help.request.user.create.title')); - setIsVisible(true); + updateSessionState(GuideSessionState.USER_CREATE); return; } - }, []); + }, [ updateSessionState ]); useUiEvent(GuideToolEvent.SHOW_GUIDE_TOOL, onGuideToolEvent); useUiEvent(GuideToolEvent.HIDE_GUIDE_TOOL, onGuideToolEvent); @@ -87,53 +136,130 @@ export const GuideToolView: FC<{}> = props => { const parser = event.getParser(); - if(parser.asGuide) - { - if(!isOnDuty) return; + setHelpRequestDescription(parser.helpRequestDescription); + setHelpRequestAverageTime(parser.roleSpecificWaitTime); - setSessionState(GuideSessionState.GUIDE_ACCEPT); - setHeaderText(LocalizeText('guide.help.request.guide.accept.title')); - setHelpRequestDescription(parser.helpRequestDescription); - setHelpRequestCountdown(parser.roleSpecificWaitTime); - } - else - { - setSessionState(GuideSessionState.USER_PENDING); - setHeaderText(LocalizeText('guide.help.request.user.pending.title')); - setHelpRequestDescription(parser.helpRequestDescription); - } + if(parser.asGuide && isOnDuty) updateSessionState(GuideSessionState.GUIDE_ACCEPT); - setIsVisible(true); - }, [ isOnDuty ]); + if(!parser.asGuide) updateSessionState(GuideSessionState.USER_PENDING); + + }, [ isOnDuty, updateSessionState ]); CreateMessageHook(GuideSessionAttachedMessageEvent, onGuideSessionAttachedMessageEvent); - + const onGuideSessionStartedMessageEvent = useCallback((event: GuideSessionStartedMessageEvent) => { const parser = event.getParser(); if(isOnDuty) { - setSessionState(GuideSessionState.GUIDE_ONGOING); - setHeaderText(LocalizeText('guide.help.request.guide.ongoing.title', ['name'], [parser.requesterName])); setOngoingUserId(parser.requesterUserId); setOngoingUsername(parser.requesterName); setOngoingFigure(parser.requesterFigure); + updateSessionState(GuideSessionState.GUIDE_ONGOING, parser.requesterName); } else { - setSessionState(GuideSessionState.USER_ONGOING); - setHeaderText(LocalizeText('guide.help.request.user.ongoing.title', ['name'], [parser.guideName])); setOngoingUserId(parser.guideUserId); setOngoingUsername(parser.guideName); setOngoingFigure(parser.guideFigure); + updateSessionState(GuideSessionState.USER_ONGOING, parser.guideName); } - - setIsVisible(true); - }, [ isOnDuty ]); + }, [ isOnDuty, updateSessionState ]); CreateMessageHook(GuideSessionStartedMessageEvent, onGuideSessionStartedMessageEvent); + const onGuideSessionPartnerIsTypingMessageEvent = useCallback((event: GuideSessionPartnerIsTypingMessageEvent) => + { + const parser = event.getParser(); + + setOngoingIsTyping(parser.isTyping); + }, []); + + CreateMessageHook(GuideSessionPartnerIsTypingMessageEvent, onGuideSessionPartnerIsTypingMessageEvent); + + const onGuideSessionMessageMessageEvent = useCallback((event: GuideSessionMessageMessageEvent) => + { + const parser = event.getParser(); + + const messageGroups = [...ongoingMessageGroups]; + + let lastGroup = messageGroups[messageGroups.length - 1]; + + if(!lastGroup || lastGroup.userId !== parser.senderId) + { + lastGroup = new GuideToolMessageGroup(parser.senderId); + messageGroups.push(lastGroup); + } + + lastGroup.addChat(new GuideToolMessage(parser.chatMessage)); + setOngoingMessageGroups(messageGroups); + }, [ ongoingMessageGroups ]); + + CreateMessageHook(GuideSessionMessageMessageEvent, onGuideSessionMessageMessageEvent); + + const onGuideSessionInvitedToGuideRoomMessageEvent = useCallback((event: GuideSessionInvitedToGuideRoomMessageEvent) => + { + const parser = event.getParser(); + + const messageGroups = [...ongoingMessageGroups]; + + let lastGroup = messageGroups[messageGroups.length - 1]; + + const guideId = (isOnDuty ? GetSessionDataManager().userId : ongoingUserId); + + if(!lastGroup || lastGroup.userId !== guideId) + { + lastGroup = new GuideToolMessageGroup(guideId); + messageGroups.push(lastGroup); + } + + lastGroup.addChat(new GuideToolMessage(parser.roomName, parser.roomId)); + setOngoingMessageGroups(messageGroups); + }, [isOnDuty, ongoingMessageGroups, ongoingUserId]); + + CreateMessageHook(GuideSessionInvitedToGuideRoomMessageEvent, onGuideSessionInvitedToGuideRoomMessageEvent); + + const onGuideSessionEndedMessageEvent = useCallback((event: GuideSessionEndedMessageEvent) => + { + if(isOnDuty) + { + setOngoingUserId(0); + setOngoingUsername(null); + setOngoingFigure(null); + setOngoingIsTyping(false); + setOngoingMessageGroups([]); + updateSessionState(GuideSessionState.GUIDE_TOOL_MENU); + } + else + { + updateSessionState(GuideSessionState.USER_FEEDBACK); + } + }, [ isOnDuty, updateSessionState ]); + + CreateMessageHook(GuideSessionEndedMessageEvent, onGuideSessionEndedMessageEvent); + + const onGuideSessionDetachedMessageEvent = useCallback((event: GuideSessionDetachedMessageEvent) => + { + setOngoingUserId(0); + setOngoingUsername(null); + setOngoingFigure(null); + setOngoingIsTyping(false); + setOngoingMessageGroups([]); + + if(isOnDuty) + { + + updateSessionState(GuideSessionState.GUIDE_TOOL_MENU); + } + else + { + updateSessionState(GuideSessionState.USER_THANKS); + } + }, [ isOnDuty, updateSessionState ]); + + CreateMessageHook(GuideSessionDetachedMessageEvent, onGuideSessionDetachedMessageEvent); + const linkReceived = useCallback((url: string) => { const parts = url.split('/'); @@ -166,6 +292,8 @@ export const GuideToolView: FC<{}> = props => { case 'close': setIsVisible(false); + setUserRequest(''); + setSessionState(GuideSessionState.GUIDE_TOOL_MENU); return; case 'toggle_duty': if(!isHandlingBullyReports && !isHandlingGuideRequests && !isHandlingHelpRequests) @@ -192,7 +320,8 @@ export const GuideToolView: FC<{}> = props => return ( - processAction('close') } /> + processAction('close') } noCloseButton={ noCloseButton } /> + { sessionState === GuideSessionState.GUIDE_TOOL_MENU && = props => guardiansOnDuty={ guardiansOnDuty } processAction={ processAction } /> } + { sessionState === GuideSessionState.GUIDE_ACCEPT && - } - { [ GuideSessionState.GUIDE_ONGOING, GuideSessionState.USER_ONGOING].includes(sessionState) && - } - { sessionState === GuideSessionState.USER_CREATE && } + } + + { [ GuideSessionState.GUIDE_ONGOING, GuideSessionState.USER_ONGOING ].includes(sessionState) && + } + + { sessionState === GuideSessionState.USER_CREATE && + } + + { sessionState === GuideSessionState.USER_PENDING && + } + + { sessionState === GuideSessionState.USER_FEEDBACK && + } + + { sessionState === GuideSessionState.USER_THANKS && + } ); }; diff --git a/src/views/guide-tool/common/GuideToolMessage.ts b/src/views/guide-tool/common/GuideToolMessage.ts new file mode 100644 index 00000000..38107266 --- /dev/null +++ b/src/views/guide-tool/common/GuideToolMessage.ts @@ -0,0 +1,21 @@ +export class GuideToolMessage +{ + private _message: string; + private _roomId: number; + + constructor(message: string, roomId?: number) + { + this._message = message; + this._roomId = roomId; + } + + public get message(): string + { + return this._message; + } + + public get roomId(): number + { + return this._roomId; + } +} diff --git a/src/views/guide-tool/common/GuideToolMessageGroup.ts b/src/views/guide-tool/common/GuideToolMessageGroup.ts new file mode 100644 index 00000000..bf03c9b9 --- /dev/null +++ b/src/views/guide-tool/common/GuideToolMessageGroup.ts @@ -0,0 +1,28 @@ +import { GuideToolMessage } from './GuideToolMessage'; + +export class GuideToolMessageGroup +{ + private _userId: number; + private _messages: GuideToolMessage[]; + + constructor(userId: number) + { + this._userId = userId; + this._messages = []; + } + + public addChat(message: GuideToolMessage): void + { + this._messages.push(message); + } + + public get userId(): number + { + return this._userId; + } + + public get messages(): GuideToolMessage[] + { + return this._messages; + } +} diff --git a/src/views/guide-tool/common/index.ts b/src/views/guide-tool/common/index.ts index e8583b2d..8ec193c9 100644 --- a/src/views/guide-tool/common/index.ts +++ b/src/views/guide-tool/common/index.ts @@ -1 +1,2 @@ export * from './GuideSessionState'; +export * from './GuideToolMessageGroup'; diff --git a/src/views/guide-tool/views/guide-accept/GuideToolAcceptView.tsx b/src/views/guide-tool/views/guide-accept/GuideToolAcceptView.tsx index 9f4d4887..add5d948 100644 --- a/src/views/guide-tool/views/guide-accept/GuideToolAcceptView.tsx +++ b/src/views/guide-tool/views/guide-accept/GuideToolAcceptView.tsx @@ -7,7 +7,7 @@ import { GuideToolAcceptViewProps } from './GuideToolAcceptView.types'; export const GuideToolAcceptView: FC = props => { - const { helpRequestDescription = null, helpRequestCountdown = 0, processAction = null } = props; + const { helpRequestDescription = null, helpRequestAverageTime = 0 } = props; const answerRequest = useCallback((response: boolean) => { diff --git a/src/views/guide-tool/views/guide-accept/GuideToolAcceptView.types.ts b/src/views/guide-tool/views/guide-accept/GuideToolAcceptView.types.ts index ff4fb926..c13cadc3 100644 --- a/src/views/guide-tool/views/guide-accept/GuideToolAcceptView.types.ts +++ b/src/views/guide-tool/views/guide-accept/GuideToolAcceptView.types.ts @@ -1,6 +1,5 @@ export interface GuideToolAcceptViewProps { helpRequestDescription: string; - helpRequestCountdown: number; - processAction: (action: string) => void; + helpRequestAverageTime: number; } diff --git a/src/views/guide-tool/views/ongoing/GuideToolOngoingView.scss b/src/views/guide-tool/views/ongoing/GuideToolOngoingView.scss new file mode 100644 index 00000000..8522edc5 --- /dev/null +++ b/src/views/guide-tool/views/ongoing/GuideToolOngoingView.scss @@ -0,0 +1,50 @@ +.chat-messages { + height: 200px; + min-height: 200px; + overflow-y: auto; + + .message-avatar { + position: relative; + overflow: hidden; + width: 50px; + height: 50px; + + .avatar-image { + position: absolute; + margin-left: -22px; + margin-top: -25px; + } + } + + .messages-group-left { + position: relative; + + &:before { + position: absolute; + content: ' '; + width: 0; + height: 0; + border-right: 8px solid rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; + border-top: 8px solid transparent; + border-bottom: 8px solid transparent; + top: 10px; + left: -8px; + } + } + + .messages-group-right { + position: relative; + + &:before { + position: absolute; + content: ' '; + width: 0; + height: 0; + border-left: 8px solid rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; + border-top: 8px solid transparent; + border-bottom: 8px solid transparent; + top: 10px; + right: -8px; + } + } +} diff --git a/src/views/guide-tool/views/ongoing/GuideToolOngoingView.tsx b/src/views/guide-tool/views/ongoing/GuideToolOngoingView.tsx index aee380e5..956a30ce 100644 --- a/src/views/guide-tool/views/ongoing/GuideToolOngoingView.tsx +++ b/src/views/guide-tool/views/ongoing/GuideToolOngoingView.tsx @@ -1,27 +1,111 @@ -import { FC } from 'react'; -import { LocalizeText } from '../../../../api'; -import { NitroCardContentView } from '../../../../layout'; +import { GuideSessionGetRequesterRoomMessageComposer, GuideSessionInviteRequesterMessageComposer, GuideSessionRequesterRoomMessageEvent, GuideSessionResolvedMessageComposer } from '@nitrots/nitro-renderer'; +import { GuideSessionMessageMessageComposer } from '@nitrots/nitro-renderer/src'; +import { FC, KeyboardEvent, useCallback, useState } from 'react'; +import { GetSessionDataManager, LocalizeText, TryVisitRoom } from '../../../../api'; +import { CreateMessageHook, SendMessageHook } from '../../../../hooks'; +import { NitroCardContentView, NitroLayoutButton, NitroLayoutFlex } from '../../../../layout'; +import { NitroLayoutBase } from '../../../../layout/base'; +import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView'; import { GuideToolOngoingViewProps } from './GuideToolOngoingView.types'; export const GuideToolOngoingView: FC = props => { - const { isGuide = false, userId = 0, userName = null, userFigure = null } = props; + const { isGuide = false, userId = 0, userName = null, userFigure = null, isTyping = false, messageGroups = [] } = props; + + const [ messageText, setMessageText ] = useState(''); + + const visit = useCallback(() => + { + SendMessageHook(new GuideSessionGetRequesterRoomMessageComposer()); + }, []); + + const invite = useCallback(() => + { + SendMessageHook(new GuideSessionInviteRequesterMessageComposer()); + }, []); + + const resolve = useCallback(() => + { + SendMessageHook(new GuideSessionResolvedMessageComposer()); + }, []); + + const onGuideSessionRequesterRoomMessageEvent = useCallback((event: GuideSessionRequesterRoomMessageEvent) => + { + const parser = event.getParser(); + + TryVisitRoom(parser.requesterRoomId); + }, []); + + CreateMessageHook(GuideSessionRequesterRoomMessageEvent, onGuideSessionRequesterRoomMessageEvent); + + const sendMessage = useCallback(() => + { + if(!messageText || !messageText.length) return; + + SendMessageHook(new GuideSessionMessageMessageComposer(messageText)); + setMessageText(''); + }, [ messageText ]); + + const onKeyDown = useCallback((event: KeyboardEvent) => + { + if(event.key !== 'Enter') return; + + sendMessage(); + }, [ sendMessage ]); return ( - -
- { isGuide && } - { isGuide && } + +
+ { isGuide &&
+ + +
} { !isGuide &&
{ userName }
{ LocalizeText('guide.help.request.user.ongoing.guide.desc') }
}
{ LocalizeText('guide.help.common.report.link') }
-
-
chat
-
-
{ LocalizeText('guide.help.request.' + (isGuide ? 'guide' : 'user') + '.ongoing.close.link') }
+
+
+ { messageGroups.map((group, index) => + { + return ( + + { (group.userId === userId) && + + + } + + { group.messages.map((message, index) => + { + return ( + + { message.roomId > 0 ? LocalizeText('guide.help.request.user.ongoing.visit.guide.request.message', ['name', 'roomname'], [userName, message.message]) : message.message } + + ); + }) } + + { (group.userId !== userId) && + + + } + + ); + }) } +
+ { isTyping &&
{ LocalizeText('guide.help.common.typing') }
} + + setMessageText(event.target.value) } onKeyDown={ onKeyDown } /> + + { LocalizeText('widgets.chatinput.say') } + + +
+
+
+
{ LocalizeText('guide.help.request.' + (isGuide ? 'guide' : 'user') + '.ongoing.close.link') }
+
); }; diff --git a/src/views/guide-tool/views/ongoing/GuideToolOngoingView.types.ts b/src/views/guide-tool/views/ongoing/GuideToolOngoingView.types.ts index c1f17b97..8a6efe2f 100644 --- a/src/views/guide-tool/views/ongoing/GuideToolOngoingView.types.ts +++ b/src/views/guide-tool/views/ongoing/GuideToolOngoingView.types.ts @@ -1,7 +1,11 @@ +import { GuideToolMessageGroup } from '../../common'; + export interface GuideToolOngoingViewProps { isGuide: boolean; userId: number; userName: string; userFigure: string; + isTyping: boolean; + messageGroups: GuideToolMessageGroup[]; } diff --git a/src/views/guide-tool/views/user-create-request/GuideToolUserCreateRequestView.scss b/src/views/guide-tool/views/user-create-request/GuideToolUserCreateRequestView.scss new file mode 100644 index 00000000..277f0223 --- /dev/null +++ b/src/views/guide-tool/views/user-create-request/GuideToolUserCreateRequestView.scss @@ -0,0 +1,12 @@ +.request-message { + width: 100%; + min-width: 100%; + max-width: 100%; + height: 90px; + min-height: 90px; + max-height: 90px; + border: none; + resize: none; + outline: none; + line-height: 17px; +} diff --git a/src/views/guide-tool/views/user-create-request/GuideToolUserCreateRequestView.tsx b/src/views/guide-tool/views/user-create-request/GuideToolUserCreateRequestView.tsx new file mode 100644 index 00000000..3b1f665f --- /dev/null +++ b/src/views/guide-tool/views/user-create-request/GuideToolUserCreateRequestView.tsx @@ -0,0 +1,29 @@ +import { GuideSessionCreateMessageComposer } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useState } from 'react'; +import { LocalizeText } from '../../../../api'; +import { SendMessageHook } from '../../../../hooks'; +import { NitroCardContentView } from '../../../../layout'; +import { GuideToolUserCreateRequestViewProps } from './GuideTooluserCreateRequestView.types'; + +const MIN_REQUEST_LENGTH: number = 15; + +export const GuideToolUserCreateRequestView: FC = props => +{ + const { userRequest = '', setUserRequest = null } = props; + + const [ isPending, setIsPending ] = useState(false); + + const sendRequest = useCallback(() => + { + setIsPending(true); + SendMessageHook(new GuideSessionCreateMessageComposer(1, userRequest)); + }, [ userRequest ]); + + return ( + +
{ LocalizeText('guide.help.request.user.create.help') }
+ + +
+ ); +}; diff --git a/src/views/guide-tool/views/user-create-request/GuideTooluserCreateRequestView.types.ts b/src/views/guide-tool/views/user-create-request/GuideTooluserCreateRequestView.types.ts new file mode 100644 index 00000000..0bff3e8a --- /dev/null +++ b/src/views/guide-tool/views/user-create-request/GuideTooluserCreateRequestView.types.ts @@ -0,0 +1,5 @@ +export interface GuideToolUserCreateRequestViewProps +{ + userRequest: string; + setUserRequest: (value: string) => void; +} diff --git a/src/views/guide-tool/views/user-feedback/GuideToolUserFeedbackView.tsx b/src/views/guide-tool/views/user-feedback/GuideToolUserFeedbackView.tsx new file mode 100644 index 00000000..57174e47 --- /dev/null +++ b/src/views/guide-tool/views/user-feedback/GuideToolUserFeedbackView.tsx @@ -0,0 +1,40 @@ +import { GuideSessionFeedbackMessageComposer } from '@nitrots/nitro-renderer'; +import { FC, useCallback } from 'react'; +import { LocalizeText } from '../../../../api'; +import { SendMessageHook } from '../../../../hooks'; +import { NitroCardContentView } from '../../../../layout'; +import { GuideToolUserFeedbackViewProps } from './GuideToolUserFeedbackView.types'; + +export const GuideToolUserFeedbackView: FC = props => +{ + const { userName = null } = props; + + const giveFeedback = useCallback((recommend: boolean) => + { + SendMessageHook(new GuideSessionFeedbackMessageComposer(recommend)); + }, []); + + return ( + +
+
+
{ userName }
+
{ LocalizeText('guide.help.request.user.feedback.guide.desc') }
+
+
{ LocalizeText('guide.help.common.report.link') }
+
+
+
+
{ LocalizeText('guide.help.request.user.feedback.closed.title') }
+
{ LocalizeText('guide.help.request.user.feedback.closed.desc') }
+
+
+
{ LocalizeText('guide.help.request.user.feedback.question') }
+
+
giveFeedback(true) }>{ LocalizeText('guide.help.request.user.feedback.positive.button') }
+
giveFeedback(false) }>{ LocalizeText('guide.help.request.user.feedback.negative.button') }
+
+
+
+ ); +}; diff --git a/src/views/guide-tool/views/user-feedback/GuideToolUserFeedbackView.types.ts b/src/views/guide-tool/views/user-feedback/GuideToolUserFeedbackView.types.ts new file mode 100644 index 00000000..937129a9 --- /dev/null +++ b/src/views/guide-tool/views/user-feedback/GuideToolUserFeedbackView.types.ts @@ -0,0 +1,4 @@ +export interface GuideToolUserFeedbackViewProps +{ + userName: string; +} diff --git a/src/views/guide-tool/views/user-pending/GuideToolUserPendingView.tsx b/src/views/guide-tool/views/user-pending/GuideToolUserPendingView.tsx new file mode 100644 index 00000000..3c201a5f --- /dev/null +++ b/src/views/guide-tool/views/user-pending/GuideToolUserPendingView.tsx @@ -0,0 +1,32 @@ +import { GuideSessionRequesterCancelsMessageComposer } from '@nitrots/nitro-renderer'; +import { FC, useCallback } from 'react'; +import { LocalizeText } from '../../../../api'; +import { SendMessageHook } from '../../../../hooks'; +import { NitroCardContentView } from '../../../../layout'; +import { GuideToolUserPendingViewProps } from './GuideToolUserPendingView.types'; + +export const GuideToolUserPendingView: FC = props => +{ + const { helpRequestDescription = null, helpRequestAverageTime = 0 } = props; + + const cancelRequest = useCallback(() => + { + SendMessageHook(new GuideSessionRequesterCancelsMessageComposer()); + }, []); + + return ( + +
+
{ LocalizeText('guide.help.request.guide.accept.request.title') }
+
{ LocalizeText('guide.help.request.type.1') }
+
{ helpRequestDescription }
+
+
+
{ LocalizeText('guide.help.request.user.pending.info.title') }
+
{ LocalizeText('guide.help.request.user.pending.info.message') }
+
{ LocalizeText('guide.help.request.user.pending.info.waiting', ['waitingtime'], [helpRequestAverageTime.toString()]) }
+
+ +
+ ); +}; diff --git a/src/views/guide-tool/views/user-pending/GuideToolUserPendingView.types.ts b/src/views/guide-tool/views/user-pending/GuideToolUserPendingView.types.ts new file mode 100644 index 00000000..a2237f66 --- /dev/null +++ b/src/views/guide-tool/views/user-pending/GuideToolUserPendingView.types.ts @@ -0,0 +1,5 @@ +export interface GuideToolUserPendingViewProps +{ + helpRequestDescription: string; + helpRequestAverageTime: number; +} diff --git a/src/views/guide-tool/views/user-create-request/GuildToolUserCreateRequestView.tsx b/src/views/guide-tool/views/user-thanks/GuideToolUserThanksView.tsx similarity index 52% rename from src/views/guide-tool/views/user-create-request/GuildToolUserCreateRequestView.tsx rename to src/views/guide-tool/views/user-thanks/GuideToolUserThanksView.tsx index dd81430c..502a738e 100644 --- a/src/views/guide-tool/views/user-create-request/GuildToolUserCreateRequestView.tsx +++ b/src/views/guide-tool/views/user-thanks/GuideToolUserThanksView.tsx @@ -2,14 +2,12 @@ import { FC } from 'react'; import { LocalizeText } from '../../../../api'; import { NitroCardContentView } from '../../../../layout'; -export const GuildToolUserCreateRequestView: FC<{}> = props => +export const GuideToolUserThanksView: FC<{}> = props => { return ( -
- { LocalizeText('guide.help.request.user.create.help') } -
- +
{ LocalizeText('guide.help.request.user.thanks.info.title') }
+
{ LocalizeText('guide.help.request.user.thanks.info.desc') }
); };