Add ability to change participant's name (#577)

This commit is contained in:
Luke Vella 2023-03-17 19:00:14 +00:00 committed by GitHub
parent 05d2c7b1d0
commit cb52adab01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 406 additions and 261 deletions

View file

@ -2,6 +2,7 @@ import { VoteType } from "@rallly/database";
import clsx from "clsx";
import { useTranslation } from "next-i18next";
import { useForm } from "react-hook-form";
import { useMount } from "react-use";
import { useFormValidation } from "../utils/form-validation";
import { Button } from "./button";
@ -26,52 +27,60 @@ const VoteSummary = ({
votes,
className,
}: {
className: string;
className?: string;
votes: { optionId: string; type: VoteType }[];
}) => {
const { t } = useTranslation("app");
const voteByType = votes.reduce<Record<VoteType, number>>(
const voteByType = votes.reduce<Record<VoteType, string[]>>(
(acc, vote) => {
acc[vote.type] = acc[vote.type] ? acc[vote.type] + 1 : 1;
acc[vote.type] = [...acc[vote.type], vote.optionId];
return acc;
},
{ yes: 0, ifNeedBe: 0, no: 0 },
{ yes: [], ifNeedBe: [], no: [] },
);
const voteTypes = Object.keys(voteByType) as VoteType[];
return (
<div className={clsx("space-y-1", className)}>
<div className="flex items-center gap-2">
<VoteIcon type="yes" />
<div>{t("yes")}</div>
<div className="rounded bg-white px-2 text-sm shadow-sm">
{voteByType["yes"]}
</div>
</div>
<div className="flex items-center gap-2">
<VoteIcon type="ifNeedBe" />
<div>{t("ifNeedBe")}</div>
<div className="rounded bg-white px-2 text-sm shadow-sm">
{voteByType["ifNeedBe"]}
</div>
</div>
<div className="flex items-center gap-2">
<VoteIcon type="no" />
<div>{t("no")}</div>
<div className="rounded bg-white px-2 text-sm shadow-sm">
{voteByType["no"]}
</div>
</div>
<div
className={clsx("flex flex-wrap gap-1.5 rounded border p-1.5", className)}
>
{voteTypes.map((voteType) => {
const votes = voteByType[voteType];
const count = votes.length;
if (count === 0) {
return null;
}
return (
<div
key={voteType}
className="flex h-8 select-none divide-x rounded border bg-gray-50 text-sm"
>
<div className="flex items-center gap-2 pl-2 pr-3">
<VoteIcon type={voteType} />
<div>{t(voteType)}</div>
</div>
<div className="flex h-full items-center justify-center px-2 text-sm font-semibold text-slate-800">
{voteByType[voteType].length}
</div>
</div>
);
})}
</div>
);
};
export const NewParticipantModal = (props: NewParticipantModalProps) => {
const { t } = useTranslation("app");
const { register, formState, handleSubmit } =
const { register, formState, setFocus, handleSubmit } =
useForm<NewParticipantFormData>();
const { requiredString, validEmail } = useFormValidation();
const { poll } = usePoll();
const addParticipant = useAddParticipantMutation();
useMount(() => {
setFocus("name");
});
return (
<div className="max-w-full p-4">
<div className="text-lg font-semibold text-slate-800">
@ -96,7 +105,6 @@ export const NewParticipantModal = (props: NewParticipantModalProps) => {
</label>
<TextInput
className="w-full"
autoFocus={true}
error={!!formState.errors.name}
disabled={formState.isSubmitting}
placeholder={t("namePlaceholder")}
@ -132,10 +140,7 @@ export const NewParticipantModal = (props: NewParticipantModalProps) => {
</fieldset>
<fieldset>
<label className="text-slate-500">{t("response")}</label>
<VoteSummary
votes={props.votes}
className="rounded border bg-gray-50 py-2 px-3"
/>
<VoteSummary votes={props.votes} />
</fieldset>
<div className="flex gap-2">
<Button onClick={props.onCancel}>{t("cancel")}</Button>
@ -157,6 +162,8 @@ export const useNewParticipantModal = () => {
const showNewParticipantModal = (props: NewParticipantModalProps) => {
return modalContext.render({
showClose: true,
overlayClosable: true,
content: function Content({ close }) {
return (
<NewParticipantModal