soapbox/app/soapbox/components/polls/poll.tsx

101 wiersze
2.5 KiB
TypeScript

import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { openModal } from 'soapbox/actions/modals';
import { vote } from 'soapbox/actions/polls';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { Stack, Text } from '../ui';
import PollFooter from './poll-footer';
import PollOption from './poll-option';
export type Selected = Record<number, boolean>;
interface IPoll {
id: string
status?: string
}
const messages = defineMessages({
multiple: { id: 'poll.choose_multiple', defaultMessage: 'Choose as many as you\'d like.' },
});
const Poll: React.FC<IPoll> = ({ id, status }): JSX.Element | null => {
const dispatch = useAppDispatch();
const intl = useIntl();
const isLoggedIn = useAppSelector((state) => state.me);
const poll = useAppSelector((state) => state.polls.get(id));
const [selected, setSelected] = useState({} as Selected);
const openUnauthorizedModal = () =>
dispatch(openModal('UNAUTHORIZED', {
action: 'POLL_VOTE',
ap_id: status,
}));
const handleVote = (selectedId: number) => dispatch(vote(id, [String(selectedId)]));
const toggleOption = (value: number) => {
if (isLoggedIn) {
if (poll?.multiple) {
const tmp = { ...selected };
if (tmp[value]) {
delete tmp[value];
} else {
tmp[value] = true;
}
setSelected(tmp);
} else {
const tmp: Selected = {};
tmp[value] = true;
setSelected(tmp);
handleVote(value);
}
} else {
openUnauthorizedModal();
}
};
if (!poll) return null;
const showResults = poll.voted || poll.expired;
return (
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
<div onClick={e => e.stopPropagation()}>
{!showResults && poll.multiple && (
<Text theme='muted' size='sm'>
{intl.formatMessage(messages.multiple)}
</Text>
)}
<Stack space={4} className='mt-4'>
<Stack space={2}>
{poll.options.map((option, i) => (
<PollOption
key={i}
poll={poll}
option={option}
index={i}
showResults={showResults}
active={!!selected[i]}
onToggle={toggleOption}
/>
))}
</Stack>
<PollFooter
poll={poll}
showResults={showResults}
selected={selected}
/>
</Stack>
</div>
);
};
export default Poll;