pl-fe: 'show results' button, only use voters_count when appropriate

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2025-10-17 20:06:12 +02:00
parent 1ea518376c
commit 43450ba545
5 changed files with 46 additions and 6 deletions

View File

@ -8,6 +8,7 @@ import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
import Tooltip from 'pl-fe/components/ui/tooltip';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useStatusMetaStore } from 'pl-fe/stores/status-meta';
import RelativeTimestamp from '../relative-timestamp';
@ -23,12 +24,15 @@ interface IPollFooter {
poll: Poll;
showResults: boolean;
selected: Selected;
statusId: string;
}
const PollFooter: React.FC<IPollFooter> = ({ poll, showResults, selected }): JSX.Element => {
const PollFooter: React.FC<IPollFooter> = ({ poll, showResults, selected, statusId }): JSX.Element => {
const dispatch = useAppDispatch();
const intl = useIntl();
const { toggleShowPollResults } = useStatusMetaStore();
const handleVote = () => dispatch(vote(poll.id, Object.keys(selected) as any as number[]));
const handleRefresh: React.EventHandler<React.MouseEvent> = (e) => {
@ -45,7 +49,7 @@ const PollFooter: React.FC<IPollFooter> = ({ poll, showResults, selected }): JSX
let votesCount = null;
if (poll.voters_count !== null && poll.voters_count !== undefined) {
if (poll.multiple && poll.voters_count !== null) {
votesCount = <FormattedMessage id='poll.total_people' defaultMessage='{count, plural, one {# person} other {# people}}' values={{ count: poll.voters_count }} />;
} else {
votesCount = <FormattedMessage id='poll.total_votes' defaultMessage='{count, plural, one {# vote} other {# votes}}' values={{ count: poll.votes_count }} />;
@ -84,6 +88,22 @@ const PollFooter: React.FC<IPollFooter> = ({ poll, showResults, selected }): JSX
</>
)}
{(!poll.voted && !poll.expired) && (
<>
<button className='text-gray-600 underline' onClick={() => toggleShowPollResults(statusId)} data-testid='poll-refresh'>
<Text theme='muted' weight='medium'>
{showResults ? (
<FormattedMessage id='poll.hide_results' defaultMessage='Hide results' />
) : (
<FormattedMessage id='poll.show_results' defaultMessage='Show results' />
)}
</Text>
</button>
<Text theme='muted'>&middot;</Text>
</>
)}
<Text theme='muted' weight='medium'>
{votesCount}
</Text>

View File

@ -114,7 +114,7 @@ const PollOption: React.FC<IPollOption> = (props): JSX.Element | null => {
if (!poll) return null;
const pollVotesCount = poll.voters_count || poll.votes_count;
const pollVotesCount = (poll.multiple && poll.voters_count) || poll.votes_count;
const percent = pollVotesCount === 0 ? 0 : (option.votes_count / pollVotesCount) * 100;
const voted = poll.own_votes?.includes(index);
const message = intl.formatMessage(messages.votes, { votes: option.votes_count });

View File

@ -7,6 +7,7 @@ import Text from 'pl-fe/components/ui/text';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useModalsStore } from 'pl-fe/stores/modals';
import { useStatusMetaStore } from 'pl-fe/stores/status-meta';
import PollFooter from './poll-footer';
import PollOption from './poll-option';
@ -17,7 +18,7 @@ type Selected = Record<number, boolean>;
interface IPoll {
id: string;
status?: Pick<Status, 'url'>;
status: Pick<Status, 'id' | 'url'>;
language?: string;
truncate?: boolean;
}
@ -34,6 +35,10 @@ const Poll: React.FC<IPoll> = ({ id, status, language, truncate }): JSX.Element
const isLoggedIn = useAppSelector((state) => state.me);
const poll = useAppSelector((state) => state.polls[id]);
const { statuses: statusesMeta } = useStatusMetaStore();
const showPollResults = !!statusesMeta[status.id]?.showPollResults;
const [selected, setSelected] = useState({} as Selected);
const openUnauthorizedModal = () =>
@ -67,7 +72,7 @@ const Poll: React.FC<IPoll> = ({ id, status, language, truncate }): JSX.Element
if (!poll) return null;
const showResults = poll.voted || poll.expired;
const showResults = poll.voted || poll.expired || !!showPollResults;
return (
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
@ -99,6 +104,7 @@ const Poll: React.FC<IPoll> = ({ id, status, language, truncate }): JSX.Element
poll={poll}
showResults={showResults}
selected={selected}
statusId={status.id}
/>
</Stack>
</div>

View File

@ -1354,9 +1354,11 @@
"plfe_config.tile_server_label": "Map tile server",
"poll.choose_multiple": "Choose as many as you'd like.",
"poll.closed": "Closed",
"poll.hide_results": "Hide results",
"poll.non_anonymous": "Public poll",
"poll.non_anonymous.label": "Other instances may display the options you voted for",
"poll.refresh": "Refresh",
"poll.show_results": "Show results",
"poll.total_people": "{count, plural, one {# person} other {# people}}",
"poll.total_votes": "{count, plural, one {# vote} other {# votes}}",
"poll.vote": "Submit Vote",

View File

@ -2,7 +2,13 @@ import { create } from 'zustand';
import { mutative } from 'zustand-mutative';
type State = {
statuses: Record<string, { expanded?: boolean; mediaVisible?: boolean; currentLanguage?: string; targetLanguage?: string }>;
statuses: Record<string, {
expanded?: boolean;
mediaVisible?: boolean;
currentLanguage?: string;
targetLanguage?: string;
showPollResults?: boolean;
}>;
expandStatuses: (statusIds: Array<string>) => void;
collapseStatuses: (statusIds: Array<string>) => void;
revealStatusesMedia: (statusIds: Array<string>) => void;
@ -11,6 +17,7 @@ type State = {
fetchTranslation: (statusId: string, targetLanguage: string) => void;
hideTranslation: (statusId: string) => void;
setStatusLanguage: (statusId: string, language: string) => void;
toggleShowPollResults: (statusId: string) => void;
};
const useStatusMetaStore = create<State>()(mutative((set) => ({
@ -65,6 +72,11 @@ const useStatusMetaStore = create<State>()(mutative((set) => ({
state.statuses[statusId].currentLanguage = language;
}),
toggleShowPollResults: (statusId) => set((state: State) => {
if (!state.statuses[statusId]) state.statuses[statusId] = {};
state.statuses[statusId].showPollResults = !state.statuses[statusId].showPollResults;
}),
})));
export { useStatusMetaStore };