Guide tool updates

This commit is contained in:
Bill 2022-02-23 01:40:36 -05:00
parent be47f5670f
commit 4205bccb4f
12 changed files with 185 additions and 222 deletions

View File

@ -1 +1 @@
export type ColorVariantType = 'primary' | 'success' | 'danger' | 'secondary' | 'link' | 'black' | 'white' | 'dark' | 'warning' | 'muted'; export type ColorVariantType = 'primary' | 'success' | 'danger' | 'secondary' | 'link' | 'black' | 'white' | 'dark' | 'warning' | 'muted' | 'light';

View File

@ -1,13 +1,6 @@
.nitro-guide-tool { .nitro-guide-tool {
width: 250px; width: 250px;
.duty-status {
border-radius: 0.25rem;
border-color: #B6BEC5 !important;
background-color: #CDD3D9;
border: 2px solid;
}
.duty-switch { .duty-switch {
width: 38px; width: 38px;
height: 21px; height: 21px;
@ -26,9 +19,6 @@
} }
.chat-messages { .chat-messages {
height: 200px;
min-height: 200px;
overflow-y: auto;
.message-avatar { .message-avatar {
position: relative; position: relative;

View File

@ -3,9 +3,10 @@ import { FC, useCallback, useEffect, useState } from 'react';
import { AddEventLinkTracker, GetConfiguration, GetSessionDataManager, 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 { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../layout';
import { GuideSessionState, GuideToolMessageGroup } from './common'; import { GuideSessionState } from './common/GuideSessionState';
import { GuideToolMessage } from './common/GuideToolMessage'; import { GuideToolMessage } from './common/GuideToolMessage';
import { GuideToolMessageGroup } from './common/GuideToolMessageGroup';
import { GuideToolAcceptView } from './views/GuideToolAcceptView'; import { GuideToolAcceptView } from './views/GuideToolAcceptView';
import { GuideToolMenuView } from './views/GuideToolMenuView'; import { GuideToolMenuView } from './views/GuideToolMenuView';
import { GuideToolOngoingView } from './views/GuideToolOngoingView'; import { GuideToolOngoingView } from './views/GuideToolOngoingView';
@ -319,46 +320,24 @@ export const GuideToolView: FC<{}> = props =>
if(!isVisible) return null; if(!isVisible) return null;
return ( return (
<NitroCardView className="nitro-guide-tool" simple={ true }> <NitroCardView className="nitro-guide-tool" simple>
<NitroCardHeaderView headerText={ headerText } onCloseClick={ () => processAction('close') } noCloseButton={ noCloseButton } /> <NitroCardHeaderView headerText={ headerText } onCloseClick={ event => processAction('close') } noCloseButton={ noCloseButton } />
<NitroCardContentView className="text-black">
{ sessionState === GuideSessionState.GUIDE_TOOL_MENU && { (sessionState === GuideSessionState.GUIDE_TOOL_MENU) &&
<GuideToolMenuView isOnDuty={ isOnDuty } <GuideToolMenuView isOnDuty={ isOnDuty } isHandlingGuideRequests={ isHandlingGuideRequests } setIsHandlingGuideRequests={ setIsHandlingGuideRequests } isHandlingHelpRequests={ isHandlingHelpRequests } setIsHandlingHelpRequests={ setIsHandlingHelpRequests } isHandlingBullyReports={ isHandlingBullyReports } setIsHandlingBullyReports={ setIsHandlingBullyReports } guidesOnDuty={ guidesOnDuty } helpersOnDuty={ helpersOnDuty } guardiansOnDuty={ guardiansOnDuty } processAction={ processAction } /> }
isHandlingGuideRequests={ isHandlingGuideRequests } { (sessionState === GuideSessionState.GUIDE_ACCEPT) &&
setIsHandlingGuideRequests={ setIsHandlingGuideRequests } <GuideToolAcceptView helpRequestDescription={ helpRequestDescription } helpRequestAverageTime={ helpRequestAverageTime } /> }
isHandlingHelpRequests={ isHandlingHelpRequests } { [ GuideSessionState.GUIDE_ONGOING, GuideSessionState.USER_ONGOING ].includes(sessionState) &&
setIsHandlingHelpRequests={ setIsHandlingHelpRequests } <GuideToolOngoingView isGuide={ isOnDuty } userId={ ongoingUserId } userName={ ongoingUsername } userFigure={ ongoingFigure } isTyping={ ongoingIsTyping } messageGroups={ ongoingMessageGroups } /> }
isHandlingBullyReports={ isHandlingBullyReports } { (sessionState === GuideSessionState.USER_CREATE) &&
setIsHandlingBullyReports={ setIsHandlingBullyReports } <GuideToolUserCreateRequestView userRequest={ userRequest } setUserRequest={ setUserRequest } /> }
guidesOnDuty={ guidesOnDuty } { (sessionState === GuideSessionState.USER_PENDING) &&
helpersOnDuty={ helpersOnDuty } <GuideToolUserPendingView helpRequestDescription={ helpRequestDescription } helpRequestAverageTime={ helpRequestAverageTime } /> }
guardiansOnDuty={ guardiansOnDuty } { (sessionState === GuideSessionState.USER_FEEDBACK) &&
processAction={ processAction } <GuideToolUserFeedbackView userName={ ongoingUsername } /> }
/> } { (sessionState === GuideSessionState.USER_THANKS) &&
<GuideToolUserThanksView /> }
{ sessionState === GuideSessionState.GUIDE_ACCEPT && </NitroCardContentView>
<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> </NitroCardView>
); );
}; };

View File

@ -1,2 +0,0 @@
export * from './GuideSessionState';
export * from './GuideToolMessageGroup';

View File

@ -1,8 +1,8 @@
import { GuideSessionGuideDecidesMessageComposer } from '@nitrots/nitro-renderer'; import { GuideSessionGuideDecidesMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react'; import { FC } from 'react';
import { LocalizeText } from '../../../api'; import { LocalizeText } from '../../../api';
import { Button, Column, Text } from '../../../common';
import { SendMessageHook } from '../../../hooks'; import { SendMessageHook } from '../../../hooks';
import { NitroCardContentView } from '../../../layout';
interface GuideToolAcceptViewProps interface GuideToolAcceptViewProps
{ {
@ -14,22 +14,23 @@ export const GuideToolAcceptView: FC<GuideToolAcceptViewProps> = props =>
{ {
const { helpRequestDescription = null, helpRequestAverageTime = 0 } = props; const { helpRequestDescription = null, helpRequestAverageTime = 0 } = props;
const answerRequest = useCallback((response: boolean) => const answerRequest = (response: boolean) => SendMessageHook(new GuideSessionGuideDecidesMessageComposer(response));
{
SendMessageHook(new GuideSessionGuideDecidesMessageComposer(response));
}, []);
return ( return (
<NitroCardContentView className="text-black flex flex-column gap-2"> <Column>
<div className="duty-status py-2 px-3"> <Column gap={ 0 } className="bg-muted p-2 rounded">
<div className="fw-bold">{ LocalizeText('guide.help.request.guide.accept.request.title') }</div> <Text bold>{ LocalizeText('guide.help.request.guide.accept.request.title') }</Text>
<div className="text-muted">{ LocalizeText('guide.help.request.type.1') }</div> <Text variant="muted">{ LocalizeText('guide.help.request.type.1') }</Text>
<div className="text-wrap text-break">{ helpRequestDescription }</div> <Text wrap textBreak>{ helpRequestDescription }</Text>
</div> </Column>
<div className="d-flex flex-column gap-2 w-100"> <Column gap={ 1 }>
<button className="btn btn-success btn-sm" onClick={ () => answerRequest(true) }>{ LocalizeText('guide.help.request.guide.accept.accept.button') }</button> <Button variant="success" onClick={ event => answerRequest(true) }>
<button className="btn btn-danger btn-sm" onClick={ () => answerRequest(false) }>{ LocalizeText('guide.help.request.guide.accept.skip.link') }</button> { LocalizeText('guide.help.request.guide.accept.accept.button') }
</div> </Button>
</NitroCardContentView> <Button variant="danger" onClick={ event => answerRequest(false) }>
{ LocalizeText('guide.help.request.guide.accept.skip.link') }
</Button>
</Column>
</Column>
); );
}; };

View File

@ -1,6 +1,6 @@
import { FC } from 'react'; import { FC } from 'react';
import { LocalizeText } from '../../../api'; import { LocalizeText } from '../../../api';
import { NitroCardContentView } from '../../../layout'; import { Base, Button, Column, Flex, Text } from '../../../common';
interface GuideToolMenuViewProps interface GuideToolMenuViewProps
{ {
@ -34,47 +34,43 @@ export const GuideToolMenuView: FC<GuideToolMenuViewProps> = props =>
} = props; } = props;
return ( return (
<> <Column>
<NitroCardContentView className="text-black flex flex-column gap-2"> <Flex alignItems="center" gap={ 2 } className="bg-muted p-2 rounded">
<div className="duty-status py-2 px-3 d-flex gap-2 align-items-center"> <Base className={ 'duty-switch' + (isOnDuty ? '' : ' off') } onClick={ event => processAction('toggle_duty') } />
<div> <Column gap={ 0 }>
<div className={ 'duty-switch' + (isOnDuty ? '' : ' off') } onClick={ () => processAction('toggle_duty') } /> <Text bold>{ LocalizeText('guide.help.guide.tool.yourstatus') }</Text>
</div> <Text>{ LocalizeText(`guide.help.guide.tool.duty.${ (isOnDuty ? 'on' : 'off') }`) }</Text>
<div> </Column>
<div className="fw-bold">{ LocalizeText('guide.help.guide.tool.yourstatus') }</div> </Flex>
<div>{ LocalizeText(`guide.help.guide.tool.duty.${(isOnDuty ? 'on' : 'off')}`) }</div> <Column gap={ 1 }>
</div> <Text bold>{ LocalizeText('guide.help.guide.tool.tickettypeselection.caption') }</Text>
</div> <Flex alignItems="center" gap={ 1 }>
<div> <input className="form-check-input" disabled={ isOnDuty } type="checkbox" checked={ isHandlingGuideRequests } onChange={ event => setIsHandlingGuideRequests(event.target.checked) } />
<div className="fw-bold">{ LocalizeText('guide.help.guide.tool.tickettypeselection.caption') }</div> <Text>{ LocalizeText('guide.help.guide.tool.tickettypeselection.guiderequests') }</Text>
<div className="form-check"> </Flex>
<input className="form-check-input" disabled={ isOnDuty } type="checkbox" checked={ isHandlingGuideRequests } onChange={ e => { setIsHandlingGuideRequests(e.target.checked) } } /> <Flex alignItems="center" gap={ 1 }>
<label className="form-check-label">{ LocalizeText('guide.help.guide.tool.tickettypeselection.guiderequests') }</label> <input className="form-check-input" disabled={ isOnDuty } type="checkbox" checked={ isHandlingHelpRequests } onChange={ event => setIsHandlingHelpRequests(event.target.checked) } />
</div> <Text>{ LocalizeText('guide.help.guide.tool.tickettypeselection.onlyhelprequests') }</Text>
<div className="form-check"> </Flex>
<input className="form-check-input" disabled={ isOnDuty } type="checkbox" checked={ isHandlingHelpRequests } onChange={ e => { setIsHandlingHelpRequests(e.target.checked) } } /> <Flex alignItems="center" gap={ 1 }>
<label className="form-check-label">{ LocalizeText('guide.help.guide.tool.tickettypeselection.onlyhelprequests') }</label> <input className="form-check-input" disabled={ isOnDuty } type="checkbox" checked={ isHandlingBullyReports } onChange={ event => setIsHandlingBullyReports(event.target.checked) } />
</div> <Text>{ LocalizeText('guide.help.guide.tool.tickettypeselection.bullyreports') }</Text>
<div className="form-check"> </Flex>
<input className="form-check-input" disabled={ isOnDuty } type="checkbox" checked={ isHandlingBullyReports } onChange={ e => { setIsHandlingBullyReports(e.target.checked) } } /> </Column>
<label className="form-check-label">{ LocalizeText('guide.help.guide.tool.tickettypeselection.bullyreports') }</label> <hr className="bg-dark m-0" />
</div> <Flex center gap={ 2 }>
</div> <Base className="info-icon" />
<hr className="bg-dark m-0" /> <Column gap={ 1 }>
<div className="d-flex align-items-center justify-content-center gap-2"> <Base dangerouslySetInnerHTML={ { __html: LocalizeText('guide.help.guide.tool.guidesonduty', [ 'amount' ], [ guidesOnDuty.toString() ]) } } />
<div className="info-icon" /> <Base dangerouslySetInnerHTML={ { __html: LocalizeText('guide.help.guide.tool.helpersonduty', [ 'amount' ], [ helpersOnDuty.toString() ]) } } />
<div> <Base dangerouslySetInnerHTML={ { __html: LocalizeText('guide.help.guide.tool.guardiansonduty', [ 'amount' ], [ guardiansOnDuty.toString() ]) } } />
<div dangerouslySetInnerHTML={ { __html: LocalizeText('guide.help.guide.tool.guidesonduty', ['amount'], [guidesOnDuty.toString()]) } } /> </Column>
<div dangerouslySetInnerHTML={ { __html: LocalizeText('guide.help.guide.tool.helpersonduty', ['amount'], [helpersOnDuty.toString()]) } } /> </Flex>
<div dangerouslySetInnerHTML={ { __html: LocalizeText('guide.help.guide.tool.guardiansonduty', ['amount'], [guardiansOnDuty.toString()]) } } /> <hr className="bg-dark m-0" />
</div> <Flex justifyContent="between" gap={ 2 }>
</div> <Button onClick={ event => processAction('forum_link') }>{ LocalizeText('guide.help.guide.tool.forum.link') }</Button>
<hr className="bg-dark m-0 mt-auto" /> <Button disabled>{ LocalizeText('guide.help.guide.tool.skill.link') }</Button>
<div className="d-flex gap-2 w-100"> </Flex>
<button className="btn btn-primary btn-sm w-100 text-nowrap" onClick={ () => processAction('forum_link') }>{ LocalizeText('guide.help.guide.tool.forum.link') }</button> </Column>
<button className="btn btn-primary btn-sm w-100 text-nowrap" disabled>{ LocalizeText('guide.help.guide.tool.skill.link') }</button>
</div>
</NitroCardContentView>
</>
); );
} }

View File

@ -2,11 +2,11 @@ import { GuideSessionGetRequesterRoomMessageComposer, GuideSessionInviteRequeste
import { GuideSessionMessageMessageComposer } from '@nitrots/nitro-renderer/src'; import { GuideSessionMessageMessageComposer } from '@nitrots/nitro-renderer/src';
import { FC, KeyboardEvent, useCallback, useState } from 'react'; import { FC, KeyboardEvent, useCallback, useState } from 'react';
import { GetSessionDataManager, LocalizeText, TryVisitRoom } from '../../../api'; import { GetSessionDataManager, LocalizeText, TryVisitRoom } from '../../../api';
import { Base, Button, ButtonGroup, Column, Flex, Text } from '../../../common';
import { CreateMessageHook, SendMessageHook } from '../../../hooks'; import { CreateMessageHook, SendMessageHook } from '../../../hooks';
import { NitroCardContentView, NitroLayoutButton, NitroLayoutFlex } from '../../../layout';
import { NitroLayoutBase } from '../../../layout/base'; import { NitroLayoutBase } from '../../../layout/base';
import { AvatarImageView } from '../../../views/shared/avatar-image/AvatarImageView'; import { AvatarImageView } from '../../../views/shared/avatar-image/AvatarImageView';
import { GuideToolMessageGroup } from '../common'; import { GuideToolMessageGroup } from '../common/GuideToolMessageGroup';
interface GuideToolOngoingViewProps interface GuideToolOngoingViewProps
{ {
@ -69,56 +69,59 @@ export const GuideToolOngoingView: FC<GuideToolOngoingViewProps> = props =>
}, []); }, []);
return ( return (
<NitroCardContentView className="p-0"> <Column fullHeight>
<div className="d-flex gap-2 align-items-center bg-secondary p-2 text-white"> <Flex alignItems="center" justifyContent="between" gap={ 1 } className="bg-muted p-2 rounded">
{ isGuide && <div className="btn-group"> { isGuide &&
<button className="btn btn-light btn-sm" onClick={ visit }>{ LocalizeText('guide.help.request.guide.ongoing.visit.button') }</button> <ButtonGroup>
<button className="btn btn-light btn-sm" disabled onClick={ invite }>{ LocalizeText('guide.help.request.guide.ongoing.invite.button') }</button> <Button onClick={ visit }>{ LocalizeText('guide.help.request.guide.ongoing.visit.button') }</Button>
</div> } <Button disabled onClick={ invite }>{ LocalizeText('guide.help.request.guide.ongoing.invite.button') }</Button>
{ !isGuide && <div> </ButtonGroup> }
<div className="fw-bold">{ userName }</div> { !isGuide &&
<div>{ LocalizeText('guide.help.request.user.ongoing.guide.desc') }</div> <Column gap={ 0 }>
</div> } <Text bold>{ userName }</Text>
<div className="ms-auto text-decoration-underline cursor-pointer text-nowrap text-muted">{ LocalizeText('guide.help.common.report.link') }</div> <Text>{ LocalizeText('guide.help.request.user.ongoing.guide.desc') }</Text>
</div> </Column> }
<div className="p-2 d-flex flex-column gap-1"> <Button variant="danger" disabled>{ LocalizeText('guide.help.common.report.link') }</Button>
<div className="text-black d-flex flex-column gap-2 p-2 chat-messages bg-muted rounded"> </Flex>
<Column fullHeight overflow="hidden" gap={ 1 } className="bg-muted rounded chat-messages p-2">
<Column overflow="auto">
{ messageGroups.map((group, index) => { messageGroups.map((group, index) =>
{ {
return ( return (
<NitroLayoutFlex className={ 'w-100 justify-content-' + (isOwnChat(group.userId) ? 'end' : 'start') } gap={ 2 }> <Flex fullWidth justifyContent={ isOwnChat(group.userId) ? 'end' : 'start' } gap={ 2 }>
<NitroLayoutBase className="message-avatar flex-shrink-0"> <Base shrink className="message-avatar">
{ (!isOwnChat(group.userId)) && { (!isOwnChat(group.userId)) &&
<AvatarImageView figure={ userFigure } direction={ 2 } /> <AvatarImageView figure={ userFigure } direction={ 2 } /> }
} </Base>
</NitroLayoutBase> <Base className={ 'bg-light text-black border-radius mb-2 rounded py-1 px-2 messages-group-' + (isOwnChat(group.userId) ? 'right' : 'left') }>
<NitroLayoutBase className={ 'bg-light text-black border-radius mb-2 rounded py-1 px-2 messages-group-' + (isOwnChat(group.userId) ? 'right' : 'left') }> <Text bold>
<NitroLayoutBase className='fw-bold'> { (isOwnChat(group.userId)) && GetSessionDataManager().userName }
{ (isOwnChat(group.userId)) && GetSessionDataManager().userName } { (!isOwnChat(group.userId)) && userName }
{ (!isOwnChat(group.userId)) && userName } </Text>
</NitroLayoutBase> { group.messages.map((chat, index) => <Base key={ index } className="text-break">{ chat.message }</Base>) }
{ group.messages.map((chat, index) =><NitroLayoutBase key={ index } className="text-break">{ chat.message }</NitroLayoutBase>) } </Base>
</NitroLayoutBase> { (isOwnChat(group.userId)) &&
{ (isOwnChat(group.userId)) && <NitroLayoutBase className="message-avatar flex-shrink-0">
<NitroLayoutBase className="message-avatar flex-shrink-0"> <AvatarImageView figure={ GetSessionDataManager().figure } direction={ 4 } />
<AvatarImageView figure={ GetSessionDataManager().figure } direction={ 4 } /> </NitroLayoutBase> }
</NitroLayoutBase> } </Flex>
</NitroLayoutFlex> );
); }) }
}) } </Column>
</div> </Column>
{ isTyping && <div className="text-muted">{ LocalizeText('guide.help.common.typing') }</div> } <Column gap={ 1 }>
<NitroLayoutFlex gap={ 2 }> <Flex gap={ 1 }>
<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 } /> <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 }> <Button variant="success" onClick={ sendMessage }>
{ LocalizeText('widgets.chatinput.say') } { LocalizeText('widgets.chatinput.say') }
</NitroLayoutButton> </Button>
</NitroLayoutFlex> </Flex>
</div> { isTyping &&
<div className="d-flex flex-column gap-2 p-2 pt-0"> <Text variant="muted">{ LocalizeText('guide.help.common.typing') }</Text> }
<hr className="bg-dark m-0" /> </Column>
<div className="btn btn-success" onClick={ resolve }>{ LocalizeText('guide.help.request.' + (isGuide ? 'guide' : 'user') + '.ongoing.close.link') }</div> <Button fullWidth variant="success" onClick={ resolve }>
</div> { LocalizeText('guide.help.request.' + (isGuide ? 'guide' : 'user') + '.ongoing.close.link') }
</NitroCardContentView> </Button>
</Column>
); );
}; };

View File

@ -1,8 +1,8 @@
import { GuideSessionCreateMessageComposer } from '@nitrots/nitro-renderer'; import { GuideSessionCreateMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react'; import { FC, useState } from 'react';
import { LocalizeText } from '../../../api'; import { LocalizeText } from '../../../api';
import { Button, Column, Text } from '../../../common';
import { SendMessageHook } from '../../../hooks'; import { SendMessageHook } from '../../../hooks';
import { NitroCardContentView } from '../../../layout';
interface GuideToolUserCreateRequestViewProps interface GuideToolUserCreateRequestViewProps
{ {
@ -15,20 +15,19 @@ const MIN_REQUEST_LENGTH: number = 15;
export const GuideToolUserCreateRequestView: FC<GuideToolUserCreateRequestViewProps> = props => export const GuideToolUserCreateRequestView: FC<GuideToolUserCreateRequestViewProps> = props =>
{ {
const { userRequest = '', setUserRequest = null } = props; const { userRequest = '', setUserRequest = null } = props;
const [ isPending, setIsPending ] = useState<boolean>(false); const [ isPending, setIsPending ] = useState<boolean>(false);
const sendRequest = useCallback(() => const sendRequest = () =>
{ {
setIsPending(true); setIsPending(true);
SendMessageHook(new GuideSessionCreateMessageComposer(1, userRequest)); SendMessageHook(new GuideSessionCreateMessageComposer(1, userRequest));
}, [ userRequest ]); }
return ( return (
<NitroCardContentView className="text-black flex flex-column gap-2"> <Column>
<div>{ LocalizeText('guide.help.request.user.create.help') }</div> <Text>{ LocalizeText('guide.help.request.user.create.help') }</Text>
<textarea className="request-message" maxLength={ 140 } value={ userRequest } onChange={ (e) => setUserRequest(e.target.value) } placeholder={ LocalizeText('guide.help.request.user.create.input.help') }></textarea> <textarea className="request-message" maxLength={ 140 } value={ userRequest } onChange={ event => setUserRequest(event.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> <Button fullWidth variant="success" disabled={ (userRequest.length < MIN_REQUEST_LENGTH) || isPending } onClick={ sendRequest }>{ LocalizeText('guide.help.request.user.create.input.button') }</Button>
</NitroCardContentView> </Column>
); );
}; };

View File

@ -1,8 +1,8 @@
import { GuideSessionFeedbackMessageComposer } from '@nitrots/nitro-renderer'; import { GuideSessionFeedbackMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { LocalizeText } from '../../../api'; import { LocalizeText } from '../../../api';
import { Button, Column, Flex, Text } from '../../../common';
import { SendMessageHook } from '../../../hooks'; import { SendMessageHook } from '../../../hooks';
import { NitroCardContentView } from '../../../layout';
interface GuideToolUserFeedbackViewProps interface GuideToolUserFeedbackViewProps
{ {
@ -19,26 +19,26 @@ export const GuideToolUserFeedbackView: FC<GuideToolUserFeedbackViewProps> = pro
}, []); }, []);
return ( return (
<NitroCardContentView className="p-0"> <Column>
<div className="d-flex gap-2 align-items-center bg-secondary p-2 text-white"> <Flex justifyContent="between" gap={ 1 } className="bg-muted p-2 rounded">
<div> <Column gap={ 0 }>
<div className="fw-bold">{ userName }</div> <Text bold>{ userName }</Text>
<div>{ LocalizeText('guide.help.request.user.feedback.guide.desc') }</div> <Text>{ LocalizeText('guide.help.request.user.feedback.guide.desc') }</Text>
</div> </Column>
<div className="ms-auto text-decoration-underline cursor-pointer text-nowrap">{ LocalizeText('guide.help.common.report.link') }</div> <Button variant="danger" disabled>{ LocalizeText('guide.help.common.report.link') }</Button>
</div> </Flex>
<div className="text-black d-flex flex-column gap-2 p-2 h-100"> <Column gap={ 1 }>
<div> <Text bold>{ LocalizeText('guide.help.request.user.feedback.closed.title') }</Text>
<div className="fw-bold">{ LocalizeText('guide.help.request.user.feedback.closed.title') }</div> <Text>{ LocalizeText('guide.help.request.user.feedback.closed.desc') }</Text>
<div>{ LocalizeText('guide.help.request.user.feedback.closed.desc') }</div> </Column>
</div> <hr className="bg-dark m-0 mt-auto" />
<hr className="bg-dark m-0 mt-auto" /> <Column>
<div className="fw-bold text-center">{ LocalizeText('guide.help.request.user.feedback.question') }</div> <Text center bold>{ LocalizeText('guide.help.request.user.feedback.question') }</Text>
<div className="d-flex gap-2"> <Flex gap={ 1 }>
<div className="btn btn-success w-100" onClick={ () => giveFeedback(true) }>{ LocalizeText('guide.help.request.user.feedback.positive.button') }</div> <Button fullWidth variant="success" onClick={ event => giveFeedback(true) }>{ LocalizeText('guide.help.request.user.feedback.positive.button') }</Button>
<div className="btn btn-danger w-100" onClick={ () => giveFeedback(false) }>{ LocalizeText('guide.help.request.user.feedback.negative.button') }</div> <Button fullWidth variant="danger" onClick={ event => giveFeedback(false) }>{ LocalizeText('guide.help.request.user.feedback.negative.button') }</Button>
</div> </Flex>
</div> </Column>
</NitroCardContentView> </Column>
); );
}; };

View File

@ -1,8 +1,8 @@
import { GuideSessionRequesterCancelsMessageComposer } from '@nitrots/nitro-renderer'; import { GuideSessionRequesterCancelsMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react'; import { FC } from 'react';
import { LocalizeText } from '../../../api'; import { LocalizeText } from '../../../api';
import { Button, Column, Text } from '../../../common';
import { SendMessageHook } from '../../../hooks'; import { SendMessageHook } from '../../../hooks';
import { NitroCardContentView } from '../../../layout';
interface GuideToolUserPendingViewProps interface GuideToolUserPendingViewProps
{ {
@ -14,24 +14,21 @@ export const GuideToolUserPendingView: FC<GuideToolUserPendingViewProps> = props
{ {
const { helpRequestDescription = null, helpRequestAverageTime = 0 } = props; const { helpRequestDescription = null, helpRequestAverageTime = 0 } = props;
const cancelRequest = useCallback(() => const cancelRequest = () => SendMessageHook(new GuideSessionRequesterCancelsMessageComposer());
{
SendMessageHook(new GuideSessionRequesterCancelsMessageComposer());
}, []);
return ( return (
<NitroCardContentView className="text-black flex flex-column gap-2"> <Column>
<div className="duty-status py-2 px-3"> <Column gap={ 0 } className="bg-muted rounded p-2">
<div className="fw-bold">{ LocalizeText('guide.help.request.guide.accept.request.title') }</div> <Text bold>{ LocalizeText('guide.help.request.guide.accept.request.title') }</Text>
<div className="text-muted">{ LocalizeText('guide.help.request.type.1') }</div> <Text variant="muted">{ LocalizeText('guide.help.request.type.1') }</Text>
<div className="text-wrap text-break">{ helpRequestDescription }</div> <Text wrap textBreak>{ helpRequestDescription }</Text>
</div> </Column>
<div> <Column gap={ 1 }>
<div className="fw-bold">{ LocalizeText('guide.help.request.user.pending.info.title') }</div> <Text bold>{ LocalizeText('guide.help.request.user.pending.info.title') }</Text>
<div>{ LocalizeText('guide.help.request.user.pending.info.message') }</div> <Text>{ LocalizeText('guide.help.request.user.pending.info.message') }</Text>
<div>{ LocalizeText('guide.help.request.user.pending.info.waiting', ['waitingtime'], [helpRequestAverageTime.toString()]) }</div> <Text>{ LocalizeText('guide.help.request.user.pending.info.waiting', [ 'waitingtime' ], [ helpRequestAverageTime.toString() ]) }</Text>
</div> </Column>
<button className="btn btn-danger mt-auto" onClick={ cancelRequest }>{ LocalizeText('guide.help.request.user.pending.cancel.button') }</button> <Button variant="danger" onClick={ cancelRequest }>{ LocalizeText('guide.help.request.user.pending.cancel.button') }</Button>
</NitroCardContentView> </Column>
); );
}; };

View File

@ -1,13 +1,13 @@
import { FC } from 'react'; import { FC } from 'react';
import { LocalizeText } from '../../../api'; import { LocalizeText } from '../../../api';
import { NitroCardContentView } from '../../../layout'; import { Column, Text } from '../../../common';
export const GuideToolUserThanksView: FC<{}> = props => export const GuideToolUserThanksView: FC<{}> = props =>
{ {
return ( return (
<NitroCardContentView className="text-black flex flex-column gap-2"> <Column gap={ 1 }>
<div className="fw-bold">{ LocalizeText('guide.help.request.user.thanks.info.title') }</div> <Text bold>{ LocalizeText('guide.help.request.user.thanks.info.title') }</Text>
<div>{ LocalizeText('guide.help.request.user.thanks.info.desc') }</div> <Text>{ LocalizeText('guide.help.request.user.thanks.info.desc') }</Text>
</NitroCardContentView> </Column>
); );
}; };

View File

@ -5,7 +5,7 @@ import { NitroCardHeaderViewProps } from './NitroCardHeaderView.types';
export const NitroCardHeaderView: FC<NitroCardHeaderViewProps> = props => export const NitroCardHeaderView: FC<NitroCardHeaderViewProps> = props =>
{ {
const { headerText = null, onCloseClick = null } = props; const { headerText = null, noCloseButton = false, onCloseClick = null } = props;
const { theme = 'primary', simple = false } = useNitroCardContext(); const { theme = 'primary', simple = false } = useNitroCardContext();
const onMouseDown = useCallback((event: MouseEvent<HTMLDivElement>) => const onMouseDown = useCallback((event: MouseEvent<HTMLDivElement>) =>