import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { api, errMsg } from "../api"; import type { VoteMode, VoteTally } from "../types"; // toggled rechnet vor, was der Server aus einer Stimme macht (siehe // handleVote): gleiche Stimme zieht sie zurück, andere wechselt. Damit // schaltet der Knopf sofort um; die Serverantwort überschreibt danach. function toggled(t: VoteTally, mode: VoteMode): VoteTally { const next = { ...t }; if (t.selected !== "none") next[t.selected]--; if (t.selected === mode) { next.selected = "none"; } else { next[mode]++; next.selected = mode; } return next; } export function Votes({ pid }: { pid: number }) { const qc = useQueryClient(); const key = ["votes", pid]; const tally = useQuery({ queryKey: key, queryFn: () => api.get(`/entry/${pid}/votes`), }); const vote = useMutation({ mutationFn: (mode: VoteMode) => { const fd = new FormData(); fd.append("mode", mode); return api.post(`/entry/${pid}/vote`, fd); }, onMutate: async (mode) => { await qc.cancelQueries({ queryKey: key }); const prev = qc.getQueryData(key); if (prev) qc.setQueryData(key, toggled(prev, mode)); return { prev }; }, onError: (_err, _mode, ctx) => { if (ctx?.prev) qc.setQueryData(key, ctx.prev); }, onSuccess: (data) => qc.setQueryData(key, data), }); const t = tally.data; let counts = "– / –"; if (vote.isError) counts = errMsg(vote.error, "Fehler"); else if (tally.isError) counts = errMsg(tally.error, "Fehler"); else if (t) counts = `${t.left} / ${t.right}`; const button = (mode: VoteMode, label: string) => ( ); return (
{button("left", "Links")} {counts} {button("right", "Rechts")}
); }