import { usePoll } from "@/components/use-poll"; import { Listbox } from "@headlessui/react"; import { Participant, Vote } from "@prisma/client"; import clsx from "clsx"; import { useTranslation } from "next-i18next"; import * as React from "react"; import { Controller, useForm } from "react-hook-form"; import { decodeDateOption } from "../../../utils/date-time-utils"; import { requiredString } from "../../../utils/form-validation"; import Button from "../../button"; import DateCard from "../../date-card"; import ChevronDown from "../../icons/chevron-down.svg"; import Pencil from "../../icons/pencil.svg"; import PlusCircle from "../../icons/plus-circle.svg"; import Save from "../../icons/save.svg"; import Trash from "../../icons/trash.svg"; import { styleMenuItem } from "../../menu-styles"; import NameInput from "../../name-input"; import TimeZonePicker from "../../time-zone-picker"; import { TransitionPopInOut } from "../../transitions"; import { useUserName } from "../../user-name-context"; import { useAddParticipantMutation, useUpdateParticipantMutation, } from "../mutations"; import TimeRange from "../time-range"; import { ParticipantForm, PollProps } from "../types"; import { useDeleteParticipantModal } from "../use-delete-participant-modal"; import UserAvater from "../user-avatar"; import VoteIcon from "../vote-icon"; const MobilePoll: React.VoidFunctionComponent = ({ pollId, timeZone, options, participants, highScore, targetTimeZone, onChangeTargetTimeZone, role, }) => { const [, setUserName] = useUserName(); const participantById = participants.reduce< Record >((acc, curr) => { acc[curr.id] = { ...curr }; return acc; }, {}); const { register, setValue, reset, handleSubmit, control, formState } = useForm({ defaultValues: { name: "", votes: [], }, }); const [selectedParticipantId, setSelectedParticipantId] = React.useState(); const selectedParticipant = selectedParticipantId ? participantById[selectedParticipantId] : undefined; const selectedParticipantVotedOption = selectedParticipant ? selectedParticipant.votes.map((vote) => vote.optionId) : undefined; const [mode, setMode] = React.useState<"edit" | "default">(() => participants.length > 0 ? "default" : "edit", ); const { t } = useTranslation("app"); const { mutate: updateParticipantMutation } = useUpdateParticipantMutation(pollId); const { mutate: addParticipantMutation } = useAddParticipantMutation(pollId); const [deleteParticipantModal, confirmDeleteParticipant] = useDeleteParticipantModal(pollId, selectedParticipantId ?? ""); // TODO (Luke Vella) [2022-03-14]: Figure out a better way to deal with these modals // This hack is necessary because when there is only one checkbox, // react-hook-form does not know to format the value into an array. // See: https://github.com/react-hook-form/react-hook-form/issues/7834 const checkboxGroupHack = ( ); const poll = usePoll(); return (
{ return new Promise((resolve, reject) => { if (selectedParticipant) { updateParticipantMutation( { participantId: selectedParticipant.id, pollId, ...data, }, { onSuccess: () => { setMode("default"); resolve(data); }, onError: reject, }, ); } else { addParticipantMutation(data, { onSuccess: (newParticipant) => { setMode("default"); setSelectedParticipantId(newParticipant.id); resolve(data); }, onError: reject, }); } }); })} > {checkboxGroupHack}
{mode === "default" ? (
{selectedParticipant ? (
{selectedParticipant.name}
) : ( t("participantCount", { count: participants.length }) )}
Show all {participants.map((participant) => (
{participant.name}
))}
{!poll.closed ? ( selectedParticipant ? (
{role === "admin" ? (
) : ( ) ) : null}
) : null} {mode === "edit" ? ( ( )} /> ) : null} {timeZone ? ( ) : null}
{options.map((option) => { const parsedOption = decodeDateOption( option.value, timeZone, targetTimeZone, ); const numVotes = option.votes.length; return (
{parsedOption.type === "timeSlot" ? ( ) : null}
{t("voteCount", { count: numVotes })}
{option.votes.length ? (
{option.votes .slice(0, option.votes.length <= 6 ? 6 : 5) .map((vote) => { const participant = participantById[vote.participantId]; return ( ); })} {option.votes.length > 6 ? ( +{option.votes.length - 5} ) : null}
) : null}
{mode === "edit" ? ( ) : selectedParticipantVotedOption ? ( selectedParticipantVotedOption.includes(option.id) ? ( ) : ( ) ) : null}
); })}
{mode === "edit" ? (
) : null} ); }; export default MobilePoll;