{shouldShowNewParticipantForm || editingParticipantId ? (
-
@@ -141,7 +142,7 @@ const Poll: React.FunctionComponent = () => {
)}
-
+
{t("optionCount", { count: options.length })}
{maxScrollPosition > 0 ? (
@@ -182,111 +183,91 @@ const Poll: React.FunctionComponent = () => {
-
-
+
+
{shouldShowNewParticipantForm &&
!poll.closed &&
!editingParticipantId ? (
-
- {
- showNewParticipantModal({
- votes,
- onSubmit: () => {
- setShouldShowNewParticipantForm(false);
- },
- });
- }}
- />
-
- ) : null}
-
- {participants.map((participant, i) => {
- return (
-
{
- if (isEditing) {
- setShouldShowNewParticipantForm(false);
- setEditingParticipantId(participant.id);
- }
- }}
+ {
- await updateParticipant.mutateAsync({
- participantId: participant.id,
- pollId: poll.id,
+ showNewParticipantModal({
votes,
+ onSubmit: () => {
+ setShouldShowNewParticipantForm(false);
+ },
});
- setEditingParticipantId(null);
}}
/>
- );
- })}
-
-
- {!poll.closed &&
- (shouldShowNewParticipantForm || editingParticipantId) ? (
-
-
-
-
+ ) : null}
+ {participants.length > 0 ? (
+
+ {participants.map((participant, i) => {
+ return (
+
{
+ if (isEditing) {
+ setShouldShowNewParticipantForm(false);
+ setEditingParticipantId(participant.id);
+ }
+ }}
+ onSubmit={async ({ votes }) => {
+ await updateParticipant.mutateAsync({
+ participantId: participant.id,
+ pollId: poll.id,
+ votes,
+ });
+ setEditingParticipantId(null);
+ }}
+ />
+ );
+ })}
-
- ) : null}
-
+ ) : null}
+
+
+
+ {!poll.closed &&
+ (shouldShowNewParticipantForm || editingParticipantId) ? (
+
+
+
+
+
+
+ ) : null}
diff --git a/apps/web/src/components/poll/desktop-poll/participant-row.tsx b/apps/web/src/components/poll/desktop-poll/participant-row.tsx
index e6464474e..4dc7d33d8 100644
--- a/apps/web/src/components/poll/desktop-poll/participant-row.tsx
+++ b/apps/web/src/components/poll/desktop-poll/participant-row.tsx
@@ -1,17 +1,12 @@
import { Participant, Vote, VoteType } from "@rallly/database";
import clsx from "clsx";
-import { useTranslation } from "next-i18next";
import * as React from "react";
-import DotsVertical from "@/components/icons/dots-vertical.svg";
-import Pencil from "@/components/icons/pencil-alt.svg";
-import Trash from "@/components/icons/trash.svg";
+import { ParticipantDropdown } from "@/components/participant-dropdown";
import { usePoll } from "@/components/poll-context";
import { useUser } from "@/components/user-provider";
-import Dropdown, { DropdownItem } from "../../dropdown";
import { ParticipantFormSubmitted } from "../types";
-import { useDeleteParticipantModal } from "../use-delete-participant-modal";
import UserAvatar from "../user-avatar";
import VoteIcon from "../vote-icon";
import ControlledScrollArea from "./controlled-scroll-area";
@@ -29,11 +24,9 @@ export interface ParticipantRowProps {
export const ParticipantRowView: React.FunctionComponent<{
name: string;
- editable?: boolean;
+ action?: React.ReactNode;
color?: string;
votes: Array
;
- onEdit?: () => void;
- onDelete?: () => void;
columnWidth: number;
className?: string;
sidebarWidth: number;
@@ -41,18 +34,15 @@ export const ParticipantRowView: React.FunctionComponent<{
participantId: string;
}> = ({
name,
- editable,
+ action,
votes,
- onEdit,
className,
- onDelete,
sidebarWidth,
columnWidth,
isYou,
color,
participantId,
}) => {
- const { t } = useTranslation("app");
return (
- {editable ? (
-
-
-
-
- }
- >
-
-
-
-
- ) : null}
+ {action}
{votes.map((vote, i) => {
@@ -97,7 +66,7 @@ export const ParticipantRowView: React.FunctionComponent<{
>
@@ -120,8 +89,6 @@ const ParticipantRow: React.FunctionComponent
= ({
}) => {
const { columnWidth, sidebarWidth } = usePollContext();
- const confirmDeleteParticipant = useDeleteParticipantModal();
-
const session = useUser();
const { poll, getVote, options, admin } = usePoll();
@@ -153,24 +120,27 @@ const ParticipantRow: React.FunctionComponent = ({
}
return (
- {
- return getVote(participant.id, optionId);
- })}
- participantId={participant.id}
- editable={canEdit}
- isYou={isYou}
- onEdit={() => {
- onChangeEditMode?.(true);
- }}
- onDelete={() => {
- confirmDeleteParticipant(participant.id);
- }}
- />
+ <>
+ {
+ return getVote(participant.id, optionId);
+ })}
+ participantId={participant.id}
+ action={
+ canEdit ? (
+ onChangeEditMode?.(true)}
+ />
+ ) : null
+ }
+ isYou={isYou}
+ />
+ >
);
};
diff --git a/apps/web/src/components/poll/mobile-poll.tsx b/apps/web/src/components/poll/mobile-poll.tsx
index 22aec1525..21be22972 100644
--- a/apps/web/src/components/poll/mobile-poll.tsx
+++ b/apps/web/src/components/poll/mobile-poll.tsx
@@ -6,9 +6,8 @@ import { FormProvider, useForm } from "react-hook-form";
import smoothscroll from "smoothscroll-polyfill";
import ChevronDown from "@/components/icons/chevron-down.svg";
-import Pencil from "@/components/icons/pencil-alt.svg";
import PlusCircle from "@/components/icons/plus-circle.svg";
-import Trash from "@/components/icons/trash.svg";
+import { ParticipantDropdown } from "@/components/participant-dropdown";
import { usePoll } from "@/components/poll-context";
import { You } from "@/components/you";
@@ -21,7 +20,6 @@ import { isUnclaimed, useUser } from "../user-provider";
import GroupedOptions from "./mobile-poll/grouped-options";
import { normalizeVotes, useUpdateParticipantMutation } from "./mutations";
import { ParticipantForm } from "./types";
-import { useDeleteParticipantModal } from "./use-delete-participant-modal";
import UserAvatar from "./user-avatar";
if (typeof window !== "undefined") {
@@ -57,8 +55,10 @@ const MobilePoll: React.FunctionComponent = () => {
const [selectedParticipantId, setSelectedParticipantId] = React.useState<
string | undefined
>(() => {
- const participant = participants.find((p) => session.ownsObject(p));
- return participant?.id;
+ if (!admin) {
+ const participant = participants.find((p) => session.ownsObject(p));
+ return participant?.id;
+ }
});
const selectedParticipant = selectedParticipantId
@@ -75,8 +75,6 @@ const MobilePoll: React.FunctionComponent = () => {
const updateParticipant = useUpdateParticipantMutation();
- const confirmDeleteParticipant = useDeleteParticipantModal();
-
const showNewParticipantModal = useNewParticipantModal();
return (
@@ -178,52 +176,28 @@ const MobilePoll: React.FunctionComponent = () => {
{t("cancel")}
) : selectedParticipant ? (
-
- }
- disabled={
- poll.closed ||
- // if user is participant (not admin)
- (!admin &&
- // and does not own this participant
- !session.ownsObject(selectedParticipant) &&
- // and the participant has been claimed by a different user
- !isUnclaimed(selectedParticipant))
- // not allowed to edit
- }
- onClick={() => {
- setIsEditing(true);
- reset({
- votes: optionIds.map((optionId) => ({
- optionId,
- type: getVote(selectedParticipant.id, optionId),
- })),
- });
- }}
- >
- {t("edit")}
-
- }
- disabled={
- poll.closed ||
- // if user is participant (not admin)
- (!admin &&
- // and does not own this participant
- !session.ownsObject(selectedParticipant) &&
- // or the participant has been claimed by a different user
- !isUnclaimed(selectedParticipant))
- // not allowed to edit
- }
- data-testid="delete-participant-button"
- type="danger"
- onClick={() => {
- if (selectedParticipant) {
- confirmDeleteParticipant(selectedParticipant.id);
- }
- }}
- />
-
+ {
+ setIsEditing(true);
+ reset({
+ votes: optionIds.map((optionId) => ({
+ optionId,
+ type: getVote(selectedParticipant.id, optionId),
+ })),
+ });
+ }}
+ />
) : (