5180 fichiers 38.5 Mo 0 téléchargements 288 vues mis à jour il y a 6 heures ui
nitro-v36-with-renderer-v36 / src / components / guide-tool / views / GuardianChatReviewVoteView.tsx
GuardianChatReviewVoteView.tsx 8 Ko Télécharger le fichier
import { FC, useEffect, useState } from 'react';
import { FriendlyTime, GUARDIAN_VOTE_BAD, GUARDIAN_VOTE_OK, GUARDIAN_VOTE_VERY_BAD, guardianText, IChatReviewRecord, secondsSinceIncident } from '../../../api';
import avatarAnonymous from '../../../assets/images/guide-tool/chat-review/avatar-anonymous.png';
import avatarPerpetrator from '../../../assets/images/guide-tool/chat-review/avatar-perpetrator.png';
import progress1 from '../../../assets/images/guide-tool/chat-review/progress-big-1.png';
import progress2 from '../../../assets/images/guide-tool/chat-review/progress-big-2.png';
import progress3 from '../../../assets/images/guide-tool/chat-review/progress-big-3.png';
import progress4 from '../../../assets/images/guide-tool/chat-review/progress-big-4.png';
import voteBad from '../../../assets/images/guide-tool/chat-review/vote-bad.png';
import voteBadDown from '../../../assets/images/guide-tool/chat-review/vote-bad-down.png';
import voteBadOver from '../../../assets/images/guide-tool/chat-review/vote-bad-over.png';
import voteOk from '../../../assets/images/guide-tool/chat-review/vote-ok.png';
import voteOkDown from '../../../assets/images/guide-tool/chat-review/vote-ok-down.png';
import voteOkOver from '../../../assets/images/guide-tool/chat-review/vote-ok-over.png';
import voteVeryBad from '../../../assets/images/guide-tool/chat-review/vote-very-bad.png';
import voteVeryBadDown from '../../../assets/images/guide-tool/chat-review/vote-very-bad-down.png';
import voteVeryBadOver from '../../../assets/images/guide-tool/chat-review/vote-very-bad-over.png';
import { Hint } from '../../../common/Tooltip';
import { BaseButton } from '../../../common/BaseButton';
import { GuardianAnimatedIcon } from './GuardianAnimatedIcon';
import { GuardianCountdownView } from './GuardianCountdownView';
import { NativeTextTree } from '../../../common/native-text/NativeTextTree';

const PROGRESS_FRAMES = [progress1, progress2, progress3, progress4];

const VOTES = [
    { code: GUARDIAN_VOTE_OK, key: 'ok', images: [voteOk, voteOkOver, voteOkDown] },
    { code: GUARDIAN_VOTE_BAD, key: 'bad', images: [voteBad, voteBadOver, voteBadDown] },
    { code: GUARDIAN_VOTE_VERY_BAD, key: 'very_bad', images: [voteVeryBad, voteVeryBadOver, voteVeryBadDown] }
];

interface GuardianVoteButtonProps {
    images: string[];
    label: string;
    tooltip: string;
    disabled: boolean;
    onVote: () => void;
}

/** One of the three vote regions: the picture follows hover and press like the AIR region does. */
const GuardianVoteButton: FC<GuardianVoteButtonProps> = ({ images, label, tooltip, disabled, onVote }) => {
    const [over, setOver] = useState(false);
    const [down, setDown] = useState(false);

    const image = !disabled && down && over ? images[2] : !disabled && over ? images[1] : images[0];

    return (
        <NativeTextTree>
            <div className="octane-guardian-vote__choice">
                <Hint content={tooltip} delay={0} disabled={disabled}>
                    <BaseButton
                        aria-label={label}
                        className="octane-guardian-vote__button"
                        disabled={disabled}
                        onClick={onVote}
                        onMouseDown={() => setDown(true)}
                        onMouseEnter={() => setOver(true)}
                        onMouseLeave={() => {
                            setOver(false);
                            setDown(false);
                        }}
                        onMouseUp={() => setDown(false)}
                    >
                        <img alt="" draggable={false} src={image} />
                    </BaseButton>
                </Hint>
                <div className="octane-guardian-vote__label">{label}</div>
            </div>
        </NativeTextTree>
    );
};

interface GuardianChatReviewVoteViewProps {
    /** True while waiting for the other guardians (no log yet, the vote is not open). */
    waiting: boolean;
    record: IChatReviewRecord | null;
    countdownSeconds: number;
    countdownId: number;
    onVote: (code: number) => void;
    onClose: () => void;
}

/**
 * AIR guardian_chat_review_vote and guardian_chat_review_wait_for_voters: the anonymous chat log of
 * the incident (the reported user as "SUSPECT", everyone else as "USER n"), how long ago it was,
 * the three votes and the "I can't decide" link.
 */
export const GuardianChatReviewVoteView: FC<GuardianChatReviewVoteViewProps> = ({ waiting, record, countdownSeconds, countdownId, onVote, onClose }) => {
    const [now, setNow] = useState(() => Date.now());

    useEffect(() => {
        const interval = window.setInterval(() => setNow(Date.now()), 10000);

        return () => window.clearInterval(interval);
    }, []);

    const incidentTime = waiting || !record ? null : `(${FriendlyTime.format(secondsSinceIncident(record.incidentTime, now), '.ago')})`;

    return (
        <NativeTextTree>
            <div className="octane-guardian-vote">
                <div className="octane-guardian-vote__countdown">
                    <GuardianCountdownView countdownId={countdownId} seconds={countdownSeconds} />
                </div>
                <div className="octane-guardian-vote__subtitle">
                    <span>{guardianText('guide.bully.request.guide.vote.subtitle')}</span>
                    {incidentTime && <span className="octane-guardian-vote__time">{incidentTime}</span>}
                </div>
                <div className="octane-guardian-vote__log">
                    {waiting && (
                        <div className="octane-guardian-vote__waiting">
                            <div>{guardianText('guide.bully.request.guide.vote.waiting')}</div>
                            <GuardianAnimatedIcon frames={PROGRESS_FRAMES} />
                        </div>
                    )}
                    {!waiting &&
                        record?.lines.map((line, index) => {
                            const isSuspect = line.userIndex === 0;
                            const name = isSuspect
                                ? guardianText('guide.bully.request.guide.vote.perpetrator')
                                : guardianText('guide.bully.request.guide.vote.anonymous', ['id'], [String(line.userIndex)]);

                            return (
                                <div key={index} className={`octane-guardian-vote__line${isSuspect ? ' is-suspect' : ''}`}>
                                    <img alt="" draggable={false} src={isSuspect ? avatarPerpetrator : avatarAnonymous} />
                                    <div className="octane-guardian-vote__message">
                                        <b>{name}:</b> {line.messages.join('\n')}
                                    </div>
                                </div>
                            );
                        })}
                </div>
                <div className={`octane-guardian-vote__panel${waiting ? ' is-waiting' : ''}`}>
                    <div className="octane-guardian-vote__question">{guardianText('guide.bully.request.guide.vote.question')}</div>
                    <div className="octane-guardian-vote__choices">
                        {VOTES.map((vote) => (
                            <GuardianVoteButton
                                key={vote.key}
                                disabled={waiting}
                                images={vote.images}
                                label={guardianText(`guide.bully.request.guide.vote.${vote.key}`)}
                                tooltip={guardianText(`guide.bully.request.guide.vote.${vote.key}.tooltip`)}
                                onVote={() => onVote(vote.code)}
                            />
                        ))}
                    </div>
                    <hr className="octane-guardian-separator" />
                    <BaseButton className="octane-guardian-link octane-guardian-vote__close" onClick={onClose}>
                        {guardianText('guide.bully.request.guide.vote.close')}
                    </BaseButton>
                </div>
            </div>
        </NativeTextTree>
    );
};
15Sujets
1Dépôts
20Membres
2En ligne
Profile
Inscrit
Dernière visite
Messages
0
Votes positifs
0
Votes négatifs
0

Nous utilisons des cookies pour assurer le bon fonctionnement du site et améliorer votre expérience. en savoir plus

Autoriser