feat(polls): rework (#14645)

* feat(polls/web/native): rework polls to manage editing and saving before sending to other participants
This commit is contained in:
Calinteodor
2024-05-22 15:03:24 +03:00
committed by GitHub
parent ef387c939a
commit 3ecc16dc87
19 changed files with 379 additions and 110 deletions

View File

@@ -1,10 +1,14 @@
/* eslint-disable react/jsx-no-bind */
import React from 'react';
import { useDispatch } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
import { withPixelLineHeight } from '../../../base/styles/functions.web';
import Button from '../../../base/ui/components/web/Button';
import Checkbox from '../../../base/ui/components/web/Checkbox';
import { BUTTON_TYPES } from '../../../base/ui/constants.web';
import { editPoll } from '../../actions';
import { isSubmitAnswerDisabled } from '../../functions';
import AbstractPollAnswer, { AbstractProps } from '../AbstractPollAnswer';
@@ -53,13 +57,18 @@ const PollAnswer = ({
creatorName,
checkBoxStates,
poll,
pollId,
setCheckbox,
setCreateMode,
skipAnswer,
skipChangeVote,
sendPoll,
submitAnswer,
t
}: AbstractProps) => {
const { changingVote } = poll;
const { changingVote, saved: pollSaved } = poll;
const dispatch = useDispatch();
const { classes } = useStyles();
return (
@@ -80,26 +89,44 @@ const PollAnswer = ({
key = { index }>
<Checkbox
checked = { checkBoxStates[index] }
disabled = { poll.saved }
key = { index }
label = { answer.name }
// eslint-disable-next-line react/jsx-no-bind
label = { poll.saved ? answer : answer.name }
onChange = { ev => setCheckbox(index, ev.target.checked) } />
</li>
))
}
</ul>
<div className = { classes.footer } >
<Button
accessibilityLabel = { t('polls.answer.skip') }
className = { classes.buttonMargin }
labelKey = { 'polls.answer.skip' }
onClick = { changingVote ? skipChangeVote : skipAnswer }
type = { BUTTON_TYPES.SECONDARY } />
<Button
accessibilityLabel = { t('polls.answer.submit') }
disabled = { isSubmitAnswerDisabled(checkBoxStates) }
labelKey = { 'polls.answer.submit' }
onClick = { submitAnswer } />
{
pollSaved ? <>
<Button
accessibilityLabel = { t('polls.answer.edit') }
className = { classes.buttonMargin }
labelKey = { 'polls.answer.edit' }
onClick = { () => {
setCreateMode(true);
dispatch(editPoll(pollId, true));
} }
type = { BUTTON_TYPES.SECONDARY } />
<Button
accessibilityLabel = { t('polls.answer.send') }
labelKey = { 'polls.answer.send' }
onClick = { sendPoll } />
</> : <>
<Button
accessibilityLabel = { t('polls.answer.skip') }
className = { classes.buttonMargin }
labelKey = { 'polls.answer.skip' }
onClick = { changingVote ? skipChangeVote : skipAnswer }
type = { BUTTON_TYPES.SECONDARY } />
<Button
accessibilityLabel = { t('polls.answer.submit') }
disabled = { isSubmitAnswerDisabled(checkBoxStates) }
labelKey = { 'polls.answer.submit' }
onClick = { submitAnswer } />
</>
}
</div>
</div>
);

View File

@@ -1,10 +1,12 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useDispatch } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
import { withPixelLineHeight } from '../../../base/styles/functions.web';
import Button from '../../../base/ui/components/web/Button';
import Input from '../../../base/ui/components/web/Input';
import { BUTTON_TYPES } from '../../../base/ui/constants.web';
import { editPoll } from '../../actions';
import { ANSWERS_LIMIT, CHAR_LIMIT } from '../../constants';
import AbstractPollCreate, { AbstractProps } from '../AbstractPollCreate';
@@ -64,6 +66,8 @@ const useStyles = makeStyles()(theme => {
const PollCreate = ({
addAnswer,
answers,
editingPoll,
editingPollId,
isSubmitDisabled,
onSubmit,
question,
@@ -74,6 +78,7 @@ const PollCreate = ({
t
}: AbstractProps) => {
const { classes } = useStyles();
const dispatch = useDispatch();
/*
* This ref stores the Array of answer input fields, allowing us to focus on them.
@@ -201,7 +206,7 @@ const PollCreate = ({
value = { question } />
</div>
<ol className = { classes.answerList }>
{answers.map((answer: any, i: number) => {
{answers.map((answer: string, i: number) => {
const isIdenticalAnswer = answers.slice(0, i).length === 0 ? false
: answers.slice(0, i).some((prevAnswer: string) =>
@@ -252,13 +257,18 @@ const PollCreate = ({
accessibilityLabel = { t('polls.create.cancel') }
className = { classes.buttonMargin }
labelKey = { 'polls.create.cancel' }
onClick = { () => setCreateMode(false) }
onClick = { () => {
setCreateMode(false);
editingPollId
&& editingPoll?.editing
&& dispatch(editPoll(editingPollId, false));
} }
type = { BUTTON_TYPES.SECONDARY } />
<Button
accessibilityLabel = { t('polls.create.send') }
accessibilityLabel = { t('polls.create.save') }
disabled = { isSubmitDisabled }
isSubmit = { true }
labelKey = { 'polls.create.send' } />
labelKey = { 'polls.create.save' } />
</div>
</form>);
};

View File

@@ -14,9 +14,14 @@ interface IProps {
*/
pollId: string;
/**
* Create mode control.
*/
setCreateMode: (mode: boolean) => void;
}
const PollItem = React.forwardRef<HTMLDivElement, IProps>(({ pollId }: IProps, ref) => {
const PollItem = React.forwardRef<HTMLDivElement, IProps>(({ pollId, setCreateMode }: IProps, ref) => {
const showResults = useSelector(shouldShowResults(pollId));
return (
@@ -26,7 +31,8 @@ const PollItem = React.forwardRef<HTMLDivElement, IProps>(({ pollId }: IProps, r
key = { pollId }
pollId = { pollId } />
: <PollAnswer
pollId = { pollId } />
pollId = { pollId }
setCreateMode = { setCreateMode } />
}
</div>

View File

@@ -39,7 +39,11 @@ const useStyles = makeStyles()(theme => {
};
});
const PollsList = () => {
interface IPollListProps {
setCreateMode: (mode: boolean) => void;
}
const PollsList = ({ setCreateMode }: IPollListProps) => {
const { t } = useTranslation();
const { classes, theme } = useStyles();
@@ -80,7 +84,8 @@ const PollsList = () => {
<PollItem
key = { id }
pollId = { id }
ref = { listPolls.length - 1 === index ? pollListEndRef : null } />
ref = { listPolls.length - 1 === index ? pollListEndRef : null }
setCreateMode = { setCreateMode } />
))}
</>
);

View File

@@ -35,7 +35,7 @@ const PollsPane = ({ createMode, onCreate, setCreateMode, t }: AbstractProps) =>
? <PollCreate setCreateMode = { setCreateMode } />
: <div className = { classes.container }>
<div className = { classes.listContainer } >
<PollsList />
<PollsList setCreateMode = { setCreateMode } />
</div>
<div className = { classes.footer }>
<Button