mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-23 14:40:50 +01:00
Updates
This commit is contained in:
parent
78cd946335
commit
765ad79099
@ -4,7 +4,7 @@ import { NitroCardHeaderViewProps } from './NitroCardHeaderView.types';
|
||||
|
||||
export const NitroCardHeaderView: FC<NitroCardHeaderViewProps> = 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<HTMLDivElement>) =>
|
||||
@ -20,9 +20,9 @@ export const NitroCardHeaderView: FC<NitroCardHeaderViewProps> = props =>
|
||||
<div className="row nitro-card-header overflow-hidden">
|
||||
<div className="d-flex justify-content-center align-items-center w-100 position-relative">
|
||||
<div className="h5 text-shadow header-text">{ headerText }</div>
|
||||
<div className="position-absolute header-close" onMouseDownCapture={ onMouseDown } onClick={ onCloseClick }>
|
||||
{ !noCloseButton && <div className="position-absolute header-close" onMouseDownCapture={ onMouseDown } onClick={ onCloseClick }>
|
||||
<i className="fas fa-times" />
|
||||
</div>
|
||||
</div> }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,5 +4,6 @@ export interface NitroCardHeaderViewProps
|
||||
{
|
||||
headerText: string;
|
||||
theme?: string;
|
||||
noCloseButton?: boolean;
|
||||
onCloseClick: (event: MouseEvent) => void;
|
||||
}
|
||||
|
@ -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';
|
||||
}
|
||||
|
@ -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<boolean>(false);
|
||||
const [ headerText, setHeaderText ] = useState<string>(LocalizeText('guide.help.guide.tool.title'));
|
||||
const [ noCloseButton, setNoCloseButton ] = useState<boolean>(false);
|
||||
const [ sessionState, setSessionState ] = useState<string>(GuideSessionState.GUIDE_TOOL_MENU);
|
||||
|
||||
const [ isOnDuty, setIsOnDuty ] = useState<boolean>(false);
|
||||
@ -25,12 +30,58 @@ export const GuideToolView: FC<{}> = props =>
|
||||
const [ guidesOnDuty, setGuidesOnDuty ] = useState<number>(0);
|
||||
const [ guardiansOnDuty, setGuardiansOnDuty ] = useState<number>(0);
|
||||
|
||||
const [ userRequest, setUserRequest ] = useState<string>('');
|
||||
|
||||
const [ helpRequestDescription, setHelpRequestDescription ] = useState<string>(null);
|
||||
const [ helpRequestCountdown, setHelpRequestCountdown ] = useState<number>(0);
|
||||
const [ helpRequestAverageTime, setHelpRequestAverageTime ] = useState<number>(0);
|
||||
|
||||
const [ ongoingUserId, setOngoingUserId ] = useState<number>(0);
|
||||
const [ ongoingUsername, setOngoingUsername ] = useState<string>(null);
|
||||
const [ ongoingFigure, setOngoingFigure ] = useState<string>(null);
|
||||
const [ ongoingIsTyping, setOngoingIsTyping ] = useState<boolean>(false);
|
||||
const [ ongoingMessageGroups, setOngoingMessageGroups ] = useState<GuideToolMessageGroup[]>([]);
|
||||
|
||||
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,24 +136,14 @@ 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);
|
||||
|
||||
@ -114,26 +153,113 @@ export const GuideToolView: FC<{}> = props =>
|
||||
|
||||
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 (
|
||||
<NitroCardView className="nitro-guide-tool" simple={ true }>
|
||||
<NitroCardHeaderView headerText={ headerText } onCloseClick={ () => processAction('close') } />
|
||||
<NitroCardHeaderView headerText={ headerText } onCloseClick={ () => processAction('close') } noCloseButton={ noCloseButton } />
|
||||
|
||||
{ sessionState === GuideSessionState.GUIDE_TOOL_MENU &&
|
||||
<GuideToolMenuView isOnDuty={ isOnDuty }
|
||||
isHandlingGuideRequests={ isHandlingGuideRequests }
|
||||
@ -206,11 +335,30 @@ export const GuideToolView: FC<{}> = props =>
|
||||
guardiansOnDuty={ guardiansOnDuty }
|
||||
processAction={ processAction }
|
||||
/> }
|
||||
|
||||
{ sessionState === GuideSessionState.GUIDE_ACCEPT &&
|
||||
<GuideToolAcceptView helpRequestDescription={ helpRequestDescription } helpRequestCountdown={ helpRequestCountdown } processAction={ processAction } /> }
|
||||
{ [ GuideSessionState.GUIDE_ONGOING, GuideSessionState.USER_ONGOING].includes(sessionState) &&
|
||||
<GuideToolOngoingView isGuide={ isOnDuty } userId={ ongoingUserId } userName={ ongoingUsername } userFigure={ ongoingFigure } /> }
|
||||
{ sessionState === GuideSessionState.USER_CREATE && <GuildToolUserCreateRequestView /> }
|
||||
<GuideToolAcceptView helpRequestDescription={ helpRequestDescription } helpRequestAverageTime={ helpRequestAverageTime } /> }
|
||||
|
||||
{ [ GuideSessionState.GUIDE_ONGOING, GuideSessionState.USER_ONGOING ].includes(sessionState) &&
|
||||
<GuideToolOngoingView isGuide={ isOnDuty }
|
||||
userId={ ongoingUserId }
|
||||
userName={ ongoingUsername }
|
||||
userFigure={ ongoingFigure }
|
||||
isTyping={ ongoingIsTyping }
|
||||
messageGroups={ ongoingMessageGroups }
|
||||
/> }
|
||||
|
||||
{ sessionState === GuideSessionState.USER_CREATE &&
|
||||
<GuideToolUserCreateRequestView userRequest={ userRequest } setUserRequest={ setUserRequest } /> }
|
||||
|
||||
{ sessionState === GuideSessionState.USER_PENDING &&
|
||||
<GuideToolUserPendingView helpRequestDescription={ helpRequestDescription } helpRequestAverageTime={ helpRequestAverageTime } /> }
|
||||
|
||||
{ sessionState === GuideSessionState.USER_FEEDBACK &&
|
||||
<GuideToolUserFeedbackView userName={ ongoingUsername } /> }
|
||||
|
||||
{ sessionState === GuideSessionState.USER_THANKS &&
|
||||
<GuideToolUserThanksView /> }
|
||||
</NitroCardView>
|
||||
);
|
||||
};
|
||||
|
21
src/views/guide-tool/common/GuideToolMessage.ts
Normal file
21
src/views/guide-tool/common/GuideToolMessage.ts
Normal file
@ -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;
|
||||
}
|
||||
}
|
28
src/views/guide-tool/common/GuideToolMessageGroup.ts
Normal file
28
src/views/guide-tool/common/GuideToolMessageGroup.ts
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -1 +1,2 @@
|
||||
export * from './GuideSessionState';
|
||||
export * from './GuideToolMessageGroup';
|
||||
|
@ -7,7 +7,7 @@ import { GuideToolAcceptViewProps } from './GuideToolAcceptView.types';
|
||||
|
||||
export const GuideToolAcceptView: FC<GuideToolAcceptViewProps> = props =>
|
||||
{
|
||||
const { helpRequestDescription = null, helpRequestCountdown = 0, processAction = null } = props;
|
||||
const { helpRequestDescription = null, helpRequestAverageTime = 0 } = props;
|
||||
|
||||
const answerRequest = useCallback((response: boolean) =>
|
||||
{
|
||||
|
@ -1,6 +1,5 @@
|
||||
export interface GuideToolAcceptViewProps
|
||||
{
|
||||
helpRequestDescription: string;
|
||||
helpRequestCountdown: number;
|
||||
processAction: (action: string) => void;
|
||||
helpRequestAverageTime: number;
|
||||
}
|
||||
|
50
src/views/guide-tool/views/ongoing/GuideToolOngoingView.scss
Normal file
50
src/views/guide-tool/views/ongoing/GuideToolOngoingView.scss
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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<GuideToolOngoingViewProps> = 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<string>('');
|
||||
|
||||
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<HTMLInputElement>) =>
|
||||
{
|
||||
if(event.key !== 'Enter') return;
|
||||
|
||||
sendMessage();
|
||||
}, [ sendMessage ]);
|
||||
|
||||
return (
|
||||
<NitroCardContentView className="text-black flex flex-column gap-2">
|
||||
<div className="d-flex gap-2 align-items-center">
|
||||
{ isGuide && <button className="btn btn-primary btn-sm">{ LocalizeText('guide.help.request.guide.ongoing.visit.button') }</button> }
|
||||
{ isGuide && <button className="btn btn-primary btn-sm">{ LocalizeText('guide.help.request.guide.ongoing.invite.button') }</button> }
|
||||
<NitroCardContentView className="p-0">
|
||||
<div className="d-flex gap-2 align-items-center bg-secondary p-2 text-white">
|
||||
{ isGuide && <div className="btn-group">
|
||||
<button className="btn btn-light btn-sm" onClick={ visit }>{ LocalizeText('guide.help.request.guide.ongoing.visit.button') }</button>
|
||||
<button className="btn btn-light btn-sm" onClick={ invite }>{ LocalizeText('guide.help.request.guide.ongoing.invite.button') }</button>
|
||||
</div> }
|
||||
{ !isGuide && <div>
|
||||
<div className="fw-bold">{ userName }</div>
|
||||
<div>{ LocalizeText('guide.help.request.user.ongoing.guide.desc') }</div>
|
||||
</div> }
|
||||
<div className="ms-auto text-decoration-underline cursor-pointer text-nowrap">{ LocalizeText('guide.help.common.report.link') }</div>
|
||||
</div>
|
||||
<hr className="bg-dark m-0" />
|
||||
<div>chat</div>
|
||||
<hr className="bg-dark m-0" />
|
||||
<div className="btn btn-success btn-sm">{ LocalizeText('guide.help.request.' + (isGuide ? 'guide' : 'user') + '.ongoing.close.link') }</div>
|
||||
<div className="p-2 d-flex flex-column gap-1">
|
||||
<div className="text-black d-flex flex-column gap-2 p-2 chat-messages bg-muted rounded">
|
||||
{ messageGroups.map((group, index) =>
|
||||
{
|
||||
return (
|
||||
<NitroLayoutFlex className={ 'w-100 justify-content-' + (group.userId === 0 ? 'end' : 'start') } gap={ 2 }>
|
||||
{ (group.userId === userId) &&
|
||||
<NitroLayoutBase className="message-avatar flex-shrink-0">
|
||||
<AvatarImageView figure={ userFigure } direction={ 2 } />
|
||||
</NitroLayoutBase> }
|
||||
<NitroLayoutBase className={ 'bg-light text-black border-radius mb-2 rounded py-1 px-2 messages-group-' + (group.userId !== userId ? 'right' : 'left') }>
|
||||
{ group.messages.map((message, index) =>
|
||||
{
|
||||
return (
|
||||
<NitroLayoutBase key={ index } className="text-break">
|
||||
{ message.roomId > 0 ? LocalizeText('guide.help.request.user.ongoing.visit.guide.request.message', ['name', 'roomname'], [userName, message.message]) : message.message }
|
||||
</NitroLayoutBase>
|
||||
);
|
||||
}) }
|
||||
</NitroLayoutBase>
|
||||
{ (group.userId !== userId) &&
|
||||
<NitroLayoutBase className="message-avatar flex-shrink-0">
|
||||
<AvatarImageView figure={ GetSessionDataManager().figure } direction={ 4 } />
|
||||
</NitroLayoutBase> }
|
||||
</NitroLayoutFlex>
|
||||
);
|
||||
}) }
|
||||
</div>
|
||||
{ isTyping && <div className="text-muted">{ LocalizeText('guide.help.common.typing') }</div> }
|
||||
<NitroLayoutFlex gap={ 2 }>
|
||||
<input type="text" className="form-control form-control-sm" placeholder={ LocalizeText('guide.help.request.guide.ongoing.input.empty', [ 'name' ], [ userName ]) } value={ messageText } onChange={ event => setMessageText(event.target.value) } onKeyDown={ onKeyDown } />
|
||||
<NitroLayoutButton variant="success" size="sm" onClick={ sendMessage }>
|
||||
{ LocalizeText('widgets.chatinput.say') }
|
||||
</NitroLayoutButton>
|
||||
</NitroLayoutFlex>
|
||||
</div>
|
||||
<div className="d-flex flex-column gap-2 p-2 pt-0">
|
||||
<hr className="bg-dark m-0" />
|
||||
<div className="btn btn-success" onClick={ resolve }>{ LocalizeText('guide.help.request.' + (isGuide ? 'guide' : 'user') + '.ongoing.close.link') }</div>
|
||||
</div>
|
||||
</NitroCardContentView>
|
||||
);
|
||||
};
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { GuideToolMessageGroup } from '../../common';
|
||||
|
||||
export interface GuideToolOngoingViewProps
|
||||
{
|
||||
isGuide: boolean;
|
||||
userId: number;
|
||||
userName: string;
|
||||
userFigure: string;
|
||||
isTyping: boolean;
|
||||
messageGroups: GuideToolMessageGroup[];
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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<GuideToolUserCreateRequestViewProps> = props =>
|
||||
{
|
||||
const { userRequest = '', setUserRequest = null } = props;
|
||||
|
||||
const [ isPending, setIsPending ] = useState<boolean>(false);
|
||||
|
||||
const sendRequest = useCallback(() =>
|
||||
{
|
||||
setIsPending(true);
|
||||
SendMessageHook(new GuideSessionCreateMessageComposer(1, userRequest));
|
||||
}, [ userRequest ]);
|
||||
|
||||
return (
|
||||
<NitroCardContentView className="text-black flex flex-column gap-2">
|
||||
<div>{ LocalizeText('guide.help.request.user.create.help') }</div>
|
||||
<textarea className="request-message" maxLength={ 140 } value={ userRequest } onChange={ (e) => setUserRequest(e.target.value) } placeholder={ LocalizeText('guide.help.request.user.create.input.help') }></textarea>
|
||||
<button className="btn btn-success" disabled={ userRequest.length < MIN_REQUEST_LENGTH || isPending } onClick={ sendRequest }>{ LocalizeText('guide.help.request.user.create.input.button') }</button>
|
||||
</NitroCardContentView>
|
||||
);
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
export interface GuideToolUserCreateRequestViewProps
|
||||
{
|
||||
userRequest: string;
|
||||
setUserRequest: (value: string) => void;
|
||||
}
|
@ -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<GuideToolUserFeedbackViewProps> = props =>
|
||||
{
|
||||
const { userName = null } = props;
|
||||
|
||||
const giveFeedback = useCallback((recommend: boolean) =>
|
||||
{
|
||||
SendMessageHook(new GuideSessionFeedbackMessageComposer(recommend));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<NitroCardContentView className="p-0">
|
||||
<div className="d-flex gap-2 align-items-center bg-secondary p-2 text-white">
|
||||
<div>
|
||||
<div className="fw-bold">{ userName }</div>
|
||||
<div>{ LocalizeText('guide.help.request.user.feedback.guide.desc') }</div>
|
||||
</div>
|
||||
<div className="ms-auto text-decoration-underline cursor-pointer text-nowrap">{ LocalizeText('guide.help.common.report.link') }</div>
|
||||
</div>
|
||||
<div className="text-black d-flex flex-column gap-2 p-2 h-100">
|
||||
<div>
|
||||
<div className="fw-bold">{ LocalizeText('guide.help.request.user.feedback.closed.title') }</div>
|
||||
<div>{ LocalizeText('guide.help.request.user.feedback.closed.desc') }</div>
|
||||
</div>
|
||||
<hr className="bg-dark m-0 mt-auto" />
|
||||
<div className="fw-bold text-center">{ LocalizeText('guide.help.request.user.feedback.question') }</div>
|
||||
<div className="d-flex gap-2">
|
||||
<div className="btn btn-success w-100" onClick={ () => giveFeedback(true) }>{ LocalizeText('guide.help.request.user.feedback.positive.button') }</div>
|
||||
<div className="btn btn-danger w-100" onClick={ () => giveFeedback(false) }>{ LocalizeText('guide.help.request.user.feedback.negative.button') }</div>
|
||||
</div>
|
||||
</div>
|
||||
</NitroCardContentView>
|
||||
);
|
||||
};
|
@ -0,0 +1,4 @@
|
||||
export interface GuideToolUserFeedbackViewProps
|
||||
{
|
||||
userName: string;
|
||||
}
|
@ -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<GuideToolUserPendingViewProps> = props =>
|
||||
{
|
||||
const { helpRequestDescription = null, helpRequestAverageTime = 0 } = props;
|
||||
|
||||
const cancelRequest = useCallback(() =>
|
||||
{
|
||||
SendMessageHook(new GuideSessionRequesterCancelsMessageComposer());
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<NitroCardContentView className="text-black flex flex-column gap-2">
|
||||
<div className="duty-status py-2 px-3">
|
||||
<div className="fw-bold">{ LocalizeText('guide.help.request.guide.accept.request.title') }</div>
|
||||
<div className="text-muted">{ LocalizeText('guide.help.request.type.1') }</div>
|
||||
<div className="text-wrap text-break">{ helpRequestDescription }</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="fw-bold">{ LocalizeText('guide.help.request.user.pending.info.title') }</div>
|
||||
<div>{ LocalizeText('guide.help.request.user.pending.info.message') }</div>
|
||||
<div>{ LocalizeText('guide.help.request.user.pending.info.waiting', ['waitingtime'], [helpRequestAverageTime.toString()]) }</div>
|
||||
</div>
|
||||
<button className="btn btn-danger mt-auto" onClick={ cancelRequest }>{ LocalizeText('guide.help.request.user.pending.cancel.button') }</button>
|
||||
</NitroCardContentView>
|
||||
);
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
export interface GuideToolUserPendingViewProps
|
||||
{
|
||||
helpRequestDescription: string;
|
||||
helpRequestAverageTime: number;
|
||||
}
|
@ -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 (
|
||||
<NitroCardContentView className="text-black flex flex-column gap-2">
|
||||
<div className="duty-status p-2 text-center">
|
||||
{ LocalizeText('guide.help.request.user.create.help') }
|
||||
</div>
|
||||
|
||||
<div className="fw-bold">{ LocalizeText('guide.help.request.user.thanks.info.title') }</div>
|
||||
<div>{ LocalizeText('guide.help.request.user.thanks.info.desc') }</div>
|
||||
</NitroCardContentView>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue
Block a user