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 =>
|
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 { simple = false } = useNitroCardContext();
|
||||||
|
|
||||||
const onMouseDown = useCallback((event: MouseEvent<HTMLDivElement>) =>
|
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="row nitro-card-header overflow-hidden">
|
||||||
<div className="d-flex justify-content-center align-items-center w-100 position-relative">
|
<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="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" />
|
<i className="fas fa-times" />
|
||||||
</div>
|
</div> }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,5 +4,6 @@ export interface NitroCardHeaderViewProps
|
|||||||
{
|
{
|
||||||
headerText: string;
|
headerText: string;
|
||||||
theme?: string;
|
theme?: string;
|
||||||
|
noCloseButton?: boolean;
|
||||||
onCloseClick: (event: MouseEvent) => void;
|
onCloseClick: (event: MouseEvent) => void;
|
||||||
}
|
}
|
||||||
|
@ -24,4 +24,8 @@
|
|||||||
height: 24px;
|
height: 24px;
|
||||||
background-image: url(../../assets/images/guide-tool/guide_tool_info_icon.png);
|
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 { 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 { GuideToolEvent, NotificationAlertEvent } from '../../events';
|
||||||
import { CreateMessageHook, dispatchUiEvent, SendMessageHook, useUiEvent } from '../../hooks';
|
import { CreateMessageHook, dispatchUiEvent, SendMessageHook, useUiEvent } from '../../hooks';
|
||||||
import { NitroCardHeaderView, NitroCardView } from '../../layout';
|
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 { GuideToolAcceptView } from './views/guide-accept/GuideToolAcceptView';
|
||||||
import { GuideToolMenuView } from './views/guide-tool-menu/GuideToolMenuView';
|
import { GuideToolMenuView } from './views/guide-tool-menu/GuideToolMenuView';
|
||||||
import { GuideToolOngoingView } from './views/ongoing/GuideToolOngoingView';
|
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 =>
|
export const GuideToolView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const [ isVisible, setIsVisible ] = useState<boolean>(false);
|
const [ isVisible, setIsVisible ] = useState<boolean>(false);
|
||||||
const [ headerText, setHeaderText ] = useState<string>(LocalizeText('guide.help.guide.tool.title'));
|
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 [ sessionState, setSessionState ] = useState<string>(GuideSessionState.GUIDE_TOOL_MENU);
|
||||||
|
|
||||||
const [ isOnDuty, setIsOnDuty ] = useState<boolean>(false);
|
const [ isOnDuty, setIsOnDuty ] = useState<boolean>(false);
|
||||||
@ -25,12 +30,58 @@ export const GuideToolView: FC<{}> = props =>
|
|||||||
const [ guidesOnDuty, setGuidesOnDuty ] = useState<number>(0);
|
const [ guidesOnDuty, setGuidesOnDuty ] = useState<number>(0);
|
||||||
const [ guardiansOnDuty, setGuardiansOnDuty ] = useState<number>(0);
|
const [ guardiansOnDuty, setGuardiansOnDuty ] = useState<number>(0);
|
||||||
|
|
||||||
|
const [ userRequest, setUserRequest ] = useState<string>('');
|
||||||
|
|
||||||
const [ helpRequestDescription, setHelpRequestDescription ] = useState<string>(null);
|
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 [ ongoingUserId, setOngoingUserId ] = useState<number>(0);
|
||||||
const [ ongoingUsername, setOngoingUsername ] = useState<string>(null);
|
const [ ongoingUsername, setOngoingUsername ] = useState<string>(null);
|
||||||
const [ ongoingFigure, setOngoingFigure ] = 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) =>
|
const onGuideToolEvent = useCallback((event: GuideToolEvent) =>
|
||||||
{
|
{
|
||||||
@ -46,12 +97,10 @@ export const GuideToolView: FC<{}> = props =>
|
|||||||
setIsVisible(value => !value);
|
setIsVisible(value => !value);
|
||||||
return;
|
return;
|
||||||
case GuideToolEvent.CREATE_HELP_REQUEST:
|
case GuideToolEvent.CREATE_HELP_REQUEST:
|
||||||
setSessionState(GuideSessionState.USER_CREATE);
|
updateSessionState(GuideSessionState.USER_CREATE);
|
||||||
setHeaderText(LocalizeText('guide.help.request.user.create.title'));
|
|
||||||
setIsVisible(true);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, []);
|
}, [ updateSessionState ]);
|
||||||
|
|
||||||
useUiEvent(GuideToolEvent.SHOW_GUIDE_TOOL, onGuideToolEvent);
|
useUiEvent(GuideToolEvent.SHOW_GUIDE_TOOL, onGuideToolEvent);
|
||||||
useUiEvent(GuideToolEvent.HIDE_GUIDE_TOOL, onGuideToolEvent);
|
useUiEvent(GuideToolEvent.HIDE_GUIDE_TOOL, onGuideToolEvent);
|
||||||
@ -87,24 +136,14 @@ export const GuideToolView: FC<{}> = props =>
|
|||||||
{
|
{
|
||||||
const parser = event.getParser();
|
const parser = event.getParser();
|
||||||
|
|
||||||
if(parser.asGuide)
|
|
||||||
{
|
|
||||||
if(!isOnDuty) return;
|
|
||||||
|
|
||||||
setSessionState(GuideSessionState.GUIDE_ACCEPT);
|
|
||||||
setHeaderText(LocalizeText('guide.help.request.guide.accept.title'));
|
|
||||||
setHelpRequestDescription(parser.helpRequestDescription);
|
setHelpRequestDescription(parser.helpRequestDescription);
|
||||||
setHelpRequestCountdown(parser.roleSpecificWaitTime);
|
setHelpRequestAverageTime(parser.roleSpecificWaitTime);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setSessionState(GuideSessionState.USER_PENDING);
|
|
||||||
setHeaderText(LocalizeText('guide.help.request.user.pending.title'));
|
|
||||||
setHelpRequestDescription(parser.helpRequestDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsVisible(true);
|
if(parser.asGuide && isOnDuty) updateSessionState(GuideSessionState.GUIDE_ACCEPT);
|
||||||
}, [ isOnDuty ]);
|
|
||||||
|
if(!parser.asGuide) updateSessionState(GuideSessionState.USER_PENDING);
|
||||||
|
|
||||||
|
}, [ isOnDuty, updateSessionState ]);
|
||||||
|
|
||||||
CreateMessageHook(GuideSessionAttachedMessageEvent, onGuideSessionAttachedMessageEvent);
|
CreateMessageHook(GuideSessionAttachedMessageEvent, onGuideSessionAttachedMessageEvent);
|
||||||
|
|
||||||
@ -114,26 +153,113 @@ export const GuideToolView: FC<{}> = props =>
|
|||||||
|
|
||||||
if(isOnDuty)
|
if(isOnDuty)
|
||||||
{
|
{
|
||||||
setSessionState(GuideSessionState.GUIDE_ONGOING);
|
|
||||||
setHeaderText(LocalizeText('guide.help.request.guide.ongoing.title', ['name'], [parser.requesterName]));
|
|
||||||
setOngoingUserId(parser.requesterUserId);
|
setOngoingUserId(parser.requesterUserId);
|
||||||
setOngoingUsername(parser.requesterName);
|
setOngoingUsername(parser.requesterName);
|
||||||
setOngoingFigure(parser.requesterFigure);
|
setOngoingFigure(parser.requesterFigure);
|
||||||
|
updateSessionState(GuideSessionState.GUIDE_ONGOING, parser.requesterName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
setSessionState(GuideSessionState.USER_ONGOING);
|
|
||||||
setHeaderText(LocalizeText('guide.help.request.user.ongoing.title', ['name'], [parser.guideName]));
|
|
||||||
setOngoingUserId(parser.guideUserId);
|
setOngoingUserId(parser.guideUserId);
|
||||||
setOngoingUsername(parser.guideName);
|
setOngoingUsername(parser.guideName);
|
||||||
setOngoingFigure(parser.guideFigure);
|
setOngoingFigure(parser.guideFigure);
|
||||||
|
updateSessionState(GuideSessionState.USER_ONGOING, parser.guideName);
|
||||||
}
|
}
|
||||||
|
}, [ isOnDuty, updateSessionState ]);
|
||||||
setIsVisible(true);
|
|
||||||
}, [ isOnDuty ]);
|
|
||||||
|
|
||||||
CreateMessageHook(GuideSessionStartedMessageEvent, onGuideSessionStartedMessageEvent);
|
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 linkReceived = useCallback((url: string) =>
|
||||||
{
|
{
|
||||||
const parts = url.split('/');
|
const parts = url.split('/');
|
||||||
@ -166,6 +292,8 @@ export const GuideToolView: FC<{}> = props =>
|
|||||||
{
|
{
|
||||||
case 'close':
|
case 'close':
|
||||||
setIsVisible(false);
|
setIsVisible(false);
|
||||||
|
setUserRequest('');
|
||||||
|
setSessionState(GuideSessionState.GUIDE_TOOL_MENU);
|
||||||
return;
|
return;
|
||||||
case 'toggle_duty':
|
case 'toggle_duty':
|
||||||
if(!isHandlingBullyReports && !isHandlingGuideRequests && !isHandlingHelpRequests)
|
if(!isHandlingBullyReports && !isHandlingGuideRequests && !isHandlingHelpRequests)
|
||||||
@ -192,7 +320,8 @@ export const GuideToolView: FC<{}> = props =>
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<NitroCardView className="nitro-guide-tool" simple={ true }>
|
<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 &&
|
{ sessionState === GuideSessionState.GUIDE_TOOL_MENU &&
|
||||||
<GuideToolMenuView isOnDuty={ isOnDuty }
|
<GuideToolMenuView isOnDuty={ isOnDuty }
|
||||||
isHandlingGuideRequests={ isHandlingGuideRequests }
|
isHandlingGuideRequests={ isHandlingGuideRequests }
|
||||||
@ -206,11 +335,30 @@ export const GuideToolView: FC<{}> = props =>
|
|||||||
guardiansOnDuty={ guardiansOnDuty }
|
guardiansOnDuty={ guardiansOnDuty }
|
||||||
processAction={ processAction }
|
processAction={ processAction }
|
||||||
/> }
|
/> }
|
||||||
|
|
||||||
{ sessionState === GuideSessionState.GUIDE_ACCEPT &&
|
{ sessionState === GuideSessionState.GUIDE_ACCEPT &&
|
||||||
<GuideToolAcceptView helpRequestDescription={ helpRequestDescription } helpRequestCountdown={ helpRequestCountdown } processAction={ processAction } /> }
|
<GuideToolAcceptView helpRequestDescription={ helpRequestDescription } helpRequestAverageTime={ helpRequestAverageTime } /> }
|
||||||
|
|
||||||
{ [ GuideSessionState.GUIDE_ONGOING, GuideSessionState.USER_ONGOING ].includes(sessionState) &&
|
{ [ GuideSessionState.GUIDE_ONGOING, GuideSessionState.USER_ONGOING ].includes(sessionState) &&
|
||||||
<GuideToolOngoingView isGuide={ isOnDuty } userId={ ongoingUserId } userName={ ongoingUsername } userFigure={ ongoingFigure } /> }
|
<GuideToolOngoingView isGuide={ isOnDuty }
|
||||||
{ sessionState === GuideSessionState.USER_CREATE && <GuildToolUserCreateRequestView /> }
|
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>
|
</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 './GuideSessionState';
|
||||||
|
export * from './GuideToolMessageGroup';
|
||||||
|
@ -7,7 +7,7 @@ import { GuideToolAcceptViewProps } from './GuideToolAcceptView.types';
|
|||||||
|
|
||||||
export const GuideToolAcceptView: FC<GuideToolAcceptViewProps> = props =>
|
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) =>
|
const answerRequest = useCallback((response: boolean) =>
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
export interface GuideToolAcceptViewProps
|
export interface GuideToolAcceptViewProps
|
||||||
{
|
{
|
||||||
helpRequestDescription: string;
|
helpRequestDescription: string;
|
||||||
helpRequestCountdown: number;
|
helpRequestAverageTime: number;
|
||||||
processAction: (action: string) => void;
|
|
||||||
}
|
}
|
||||||
|
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 { GuideSessionGetRequesterRoomMessageComposer, GuideSessionInviteRequesterMessageComposer, GuideSessionRequesterRoomMessageEvent, GuideSessionResolvedMessageComposer } from '@nitrots/nitro-renderer';
|
||||||
import { LocalizeText } from '../../../../api';
|
import { GuideSessionMessageMessageComposer } from '@nitrots/nitro-renderer/src';
|
||||||
import { NitroCardContentView } from '../../../../layout';
|
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';
|
import { GuideToolOngoingViewProps } from './GuideToolOngoingView.types';
|
||||||
|
|
||||||
export const GuideToolOngoingView: FC<GuideToolOngoingViewProps> = props =>
|
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 (
|
return (
|
||||||
<NitroCardContentView className="text-black flex flex-column gap-2">
|
<NitroCardContentView className="p-0">
|
||||||
<div className="d-flex gap-2 align-items-center">
|
<div className="d-flex gap-2 align-items-center bg-secondary p-2 text-white">
|
||||||
{ isGuide && <button className="btn btn-primary btn-sm">{ LocalizeText('guide.help.request.guide.ongoing.visit.button') }</button> }
|
{ isGuide && <div className="btn-group">
|
||||||
{ isGuide && <button className="btn btn-primary btn-sm">{ LocalizeText('guide.help.request.guide.ongoing.invite.button') }</button> }
|
<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>
|
{ !isGuide && <div>
|
||||||
<div className="fw-bold">{ userName }</div>
|
<div className="fw-bold">{ userName }</div>
|
||||||
<div>{ LocalizeText('guide.help.request.user.ongoing.guide.desc') }</div>
|
<div>{ LocalizeText('guide.help.request.user.ongoing.guide.desc') }</div>
|
||||||
</div> }
|
</div> }
|
||||||
<div className="ms-auto text-decoration-underline cursor-pointer text-nowrap">{ LocalizeText('guide.help.common.report.link') }</div>
|
<div className="ms-auto text-decoration-underline cursor-pointer text-nowrap">{ LocalizeText('guide.help.common.report.link') }</div>
|
||||||
</div>
|
</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" />
|
<hr className="bg-dark m-0" />
|
||||||
<div>chat</div>
|
<div className="btn btn-success" onClick={ resolve }>{ LocalizeText('guide.help.request.' + (isGuide ? 'guide' : 'user') + '.ongoing.close.link') }</div>
|
||||||
<hr className="bg-dark m-0" />
|
</div>
|
||||||
<div className="btn btn-success btn-sm">{ LocalizeText('guide.help.request.' + (isGuide ? 'guide' : 'user') + '.ongoing.close.link') }</div>
|
|
||||||
</NitroCardContentView>
|
</NitroCardContentView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
|
import { GuideToolMessageGroup } from '../../common';
|
||||||
|
|
||||||
export interface GuideToolOngoingViewProps
|
export interface GuideToolOngoingViewProps
|
||||||
{
|
{
|
||||||
isGuide: boolean;
|
isGuide: boolean;
|
||||||
userId: number;
|
userId: number;
|
||||||
userName: string;
|
userName: string;
|
||||||
userFigure: 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 { LocalizeText } from '../../../../api';
|
||||||
import { NitroCardContentView } from '../../../../layout';
|
import { NitroCardContentView } from '../../../../layout';
|
||||||
|
|
||||||
export const GuildToolUserCreateRequestView: FC<{}> = props =>
|
export const GuideToolUserThanksView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<NitroCardContentView className="text-black flex flex-column gap-2">
|
<NitroCardContentView className="text-black flex flex-column gap-2">
|
||||||
<div className="duty-status p-2 text-center">
|
<div className="fw-bold">{ LocalizeText('guide.help.request.user.thanks.info.title') }</div>
|
||||||
{ LocalizeText('guide.help.request.user.create.help') }
|
<div>{ LocalizeText('guide.help.request.user.thanks.info.desc') }</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
</NitroCardContentView>
|
</NitroCardContentView>
|
||||||
);
|
);
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user