import { GetPollResponse } from "api-client/get-poll"; import axios from "axios"; import { NextPage } from "next"; import Head from "next/head"; import { useRouter } from "next/router"; import { usePlausible } from "next-plausible"; import React from "react"; import toast from "react-hot-toast"; import { useMutation, useQueryClient } from "react-query"; import { useMount } from "react-use"; import { preventWidows } from "utils/prevent-widows"; import Button from "@/components/button"; import LocationMarker from "@/components/icons/location-marker.svg"; import LockClosed from "@/components/icons/lock-closed.svg"; import Share from "@/components/icons/share.svg"; import ManagePoll from "./poll/manage-poll"; import { useUpdatePollMutation } from "./poll/mutations"; import NotificationsToggle from "./poll/notifications-toggle"; import PollSubheader from "./poll/poll-subheader"; import TruncatedLinkify from "./poll/truncated-linkify"; import { UserAvatarProvider } from "./poll/user-avatar"; import { PollContextProvider, usePoll } from "./poll-context"; import Popover from "./popover"; import { useSession } from "./session"; import Sharing from "./sharing"; import StandardLayout from "./standard-layout"; const Discussion = React.lazy(() => import("@/components/discussion")); const DesktopPoll = React.lazy(() => import("@/components/poll/desktop-poll")); const MobilePoll = React.lazy(() => import("@/components/poll/mobile-poll")); const PollInner: NextPage = () => { const { poll } = usePoll(); const router = useRouter(); useMount(() => { const path = poll.role === "admin" ? "admin" : "p"; if (!new RegExp(`^/${path}`).test(router.asPath)) { router.replace(`/${path}/${poll.urlId}`, undefined, { shallow: true }); } }); const session = useSession(); const queryClient = useQueryClient(); const plausible = usePlausible(); const { mutate: updatePollMutation } = useUpdatePollMutation(); const { mutate: verifyEmail } = useMutation( async (verificationCode: string) => { await axios.post(`/api/poll/${poll.urlId}/verify`, { verificationCode, }); }, { onSuccess: () => { toast.success("Your poll has been verified"); queryClient.setQueryData(["getPoll", poll.urlId], { ...poll, verified: true, }); session.refresh(); plausible("Verified email"); }, onSettled: () => { router.replace(`/admin/${router.query.urlId}`, undefined, { shallow: true, }); }, onError: () => { toast.error("Your link has expired or is no longer valid"); }, }, ); React.useEffect(() => { // TODO (Luke Vella) [2022-03-29]: stop looking for "verificationCode". We switched to // "code" for compatability with v1 and it's generally better since it's more concise const verificationCode = router.query.verificationCode ?? router.query.code; if (typeof verificationCode === "string") { verifyEmail(verificationCode); } }, [router, verifyEmail]); React.useEffect(() => { if (router.query.unsubscribe) { updatePollMutation( { notifications: false }, { onSuccess: () => { toast.success("Notifications have been disabled"); plausible("Unsubscribed from notifications"); }, }, ); router.replace(`/admin/${router.query.urlId}`, undefined, { shallow: true, }); } }, [plausible, router, updatePollMutation]); const checkIfWideScreen = () => window.innerWidth > 640; const [isWideScreen, setIsWideScreen] = React.useState(checkIfWideScreen); React.useEffect(() => { const listener = () => setIsWideScreen(checkIfWideScreen()); window.addEventListener("resize", listener); return () => { window.removeEventListener("resize", listener); }; }, []); const PollComponent = isWideScreen ? DesktopPoll : MobilePoll; let highScore = 1; // set to one because we don't want to highlight poll.options.forEach((option) => { if (option.votes.length > highScore) { highScore = option.votes.length; } }); const names = React.useMemo( () => poll.participants.map(({ name }) => name), [poll.participants], ); return (
{poll.title}

{preventWidows(poll.title)}

{poll.role === "admin" ? (
}> Share } placement={isWideScreen ? "bottom-end" : undefined} >
) : null}
{poll.description ? (
{preventWidows(poll.description)}
) : null} {poll.location ? (
{poll.location}
) : null}
{poll.closed ? (
This poll has been locked (voting is disabled)
) : null} Loading…
}>
); }; const PollPage = ({ poll }: { poll: GetPollResponse }) => { return ( ); }; export default PollPage;