Skip to content

Commit

Permalink
474 comment page button to save votes does not work (#477)
Browse files Browse the repository at this point in the history
* Update type

* Add author and co authors & update type

* Add missing attrs back

* Current state (fixing voting)

* simplify and refactor comments page and voting mechanism

---------

Co-authored-by: Diego Alzate <[email protected]>
  • Loading branch information
camilovegag and diegoalzate authored May 16, 2024
1 parent bc0431b commit a159a82
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 127 deletions.
22 changes: 17 additions & 5 deletions packages/api/src/types/OptionUsersType.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import { GetGroupsResponse } from './GroupType';
import { GetUserResponse } from './UserType';

export type GetOptionUsersResponse = {
optionId: string;
registrationId: string | null;
userId: string | null;
user: GetUserResponse | null;
user: {
id: string;
username: string;
firstName: string;
lastName: string;
} | null;
groupId: string | null;
group: GetGroupsResponse | null;
group: {
id: null;
users:
| {
id: string;
username: string;
firstName: string;
lastName: string;
}[]
| null;
} | null;
};
6 changes: 3 additions & 3 deletions packages/berlin/src/components/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,14 @@ function Header() {
)
);
})}
<NavButton to={`/events/${events?.[0].id}/register`} $color="secondary">
My proposals
</NavButton>
<NavButton to={`/events/${events?.[0].id}/cycles`} $color="secondary">
Agenda
</NavButton>
</>
)}
<NavButton to={`/events/${events?.[0].id}/register`} $color="secondary">
My proposals
</NavButton>
<Button onClick={() => mutateLogout()}>Log out</Button>
<IconButton
onClick={() => navigate('/account')}
Expand Down
6 changes: 3 additions & 3 deletions packages/berlin/src/components/option-card/OptionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ type OptionCardProps = {
option: QuestionOption;
numOfVotes: number;
onVote: () => void;
onUnvote: () => void;
onUnVote: () => void;
};
function OptionCard({ option, numOfVotes, onVote, onUnvote }: OptionCardProps) {
function OptionCard({ option, numOfVotes, onVote, onUnVote }: OptionCardProps) {
const { eventId, cycleId } = useParams();
const theme = useAppStore((state) => state.theme);
const navigate = useNavigate();
Expand Down Expand Up @@ -67,7 +67,7 @@ function OptionCard({ option, numOfVotes, onVote, onUnvote }: OptionCardProps) {
$padding={0}
$color="secondary"
icon={{ src: `/icons/downvote-${theme}.svg`, alt: 'Downvote arrow' }}
onClick={onUnvote}
onClick={onUnVote}
$width={16}
$height={16}
disabled={numOfVotes === 0}
Expand Down
100 changes: 50 additions & 50 deletions packages/berlin/src/pages/Comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,19 @@ import {
fetchUserVotes,
fetchComments,
postComment,
// fetchOptionUsers,
fetchOptionUsers,
} from 'api';

// Hooks
import useUser from '../hooks/useUser';

// Utils
import { handleSaveVotes, handleUnvote, handleVote } from '../utils/voting';
import {
handleSaveVotes,
handleAvailableHearts,
handleLocalUnVote,
handleLocalVote,
} from '../utils/voting';

// Types
import { ResponseUserVotesType } from '../types/CycleType';
Expand All @@ -40,15 +45,16 @@ import CommentsColumns from '../components/columns/comments-columns';
import IconButton from '../components/icon-button';
import Textarea from '../components/textarea';

type LocalUserVotes = ResponseUserVotesType | { optionId: string; numOfVotes: number }[];

function Comments() {
const theme = useAppStore((state) => state.theme);
const queryClient = useQueryClient();
const { cycleId, optionId } = useParams();
const { user } = useUser();
const { availableHearts, setAvailableHearts } = useAppStore((state) => state);
const [localUserVotes, setLocalUserVotes] = useState<
ResponseUserVotesType | { optionId: string; numOfVotes: number }[]
>([]);
const availableHearts = useAppStore((state) => state.availableHearts);
const setAvailableHearts = useAppStore((state) => state.setAvailableHearts);
const [localUserVotes, setLocalUserVotes] = useState<LocalUserVotes>([]);
const [localOptionHearts, setLocalOptionHearts] = useState(0);
const [comment, setComment] = useState('');
const [sortOrder, setSortOrder] = useState('desc'); // 'asc' for ascending, 'desc' for descending
Expand All @@ -66,17 +72,17 @@ function Comments() {
retry: false,
});

// const { data: optionUsers } = useQuery({
// queryKey: ['optionUsers', optionId],
// queryFn: () => fetchOptionUsers(optionId || ''),
// enabled: !!optionId,
// });
const { data: optionUsers } = useQuery({
queryKey: ['option', optionId, 'users'],
queryFn: () => fetchOptionUsers(optionId || ''),
enabled: !!optionId,
});

const { data: comments } = useQuery({
queryKey: ['comments', optionId],
queryKey: ['option', optionId, 'comments'],
queryFn: () => fetchComments({ optionId: optionId || '' }),
enabled: !!optionId,
refetchInterval: 5000, // Poll every 5 seconds
// refetchInterval: 5000, // Poll every 5 seconds
});

const sortedComments = useMemo(() => {
Expand All @@ -97,52 +103,45 @@ function Comments() {
}
}, [optionId, userVotes]);

const { mutate: mutateVotes } = useMutation({
mutationFn: postVotes,
onSuccess: (body) => {
if (body?.errors?.length) {
toast.error(`Failed to save votes, ${body?.errors[0].message}`);
} else if (body?.data.length) {
queryClient.invalidateQueries({ queryKey: ['votes', cycleId] });
// this is to update the plural scores in each option
queryClient.invalidateQueries({ queryKey: ['cycles', cycleId] });
toast.success('Votes saved successfully!');
}
},
});

const { mutate: mutateComments } = useMutation({
mutationFn: postComment,
onSuccess: (body) => {
if (body?.value) {
queryClient.invalidateQueries({ queryKey: ['comments', optionId] });
queryClient.invalidateQueries({ queryKey: ['option', optionId, 'comments'] });
}
},
});

const handleVoteWrapper = (optionId: string) => {
setLocalOptionHearts((prevLocalOptionHearts) => prevLocalOptionHearts + 1);
handleVote(optionId, availableHearts, setAvailableHearts, setLocalUserVotes);
setLocalUserVotes((prevLocalUserVotes) => handleLocalVote(optionId, prevLocalUserVotes));
setAvailableHearts(handleAvailableHearts(availableHearts, 'vote'));
};

const handleUnvoteWrapper = (optionId: string) => {
const handleUnVoteWrapper = (optionId: string) => {
setLocalOptionHearts((prevLocalOptionHearts) => Math.max(0, prevLocalOptionHearts - 1));
handleUnvote(optionId, availableHearts, setAvailableHearts, setLocalUserVotes);
setLocalUserVotes((prevLocalUserVotes) => handleLocalUnVote(optionId, prevLocalUserVotes));
setAvailableHearts(handleAvailableHearts(availableHearts, 'unVote'));
};

const handleSaveVotesWrapper = () => {
const { mutate: mutateVotes } = useMutation({
mutationFn: postVotes,
onSuccess: (body) => {
if (body?.errors?.length) {
toast.error(`Failed to save votes, ${body?.errors[0].message}`);
} else if (body?.data.length) {
queryClient.invalidateQueries({ queryKey: ['votes', cycleId] });
// this is to update the plural scores in each option
queryClient.invalidateQueries({ queryKey: ['cycles', cycleId] });
toast.success('Votes saved successfully!');
}
},
});

const handleSaveVoteWrapper = () => {
handleSaveVotes(userVotes, localUserVotes, mutateVotes);
};

const votesAreDifferent = useMemo(() => {
if (localUserVotes && userVotes) {
return (
localUserVotes[0]?.numOfVotes !==
userVotes?.find((vote) => vote.optionId === optionId)?.numOfVotes
);
}
}, [localUserVotes, optionId, userVotes]);

const handlePostComment = () => {
if (optionId && comment) {
mutateComments({ questionOptionId: optionId, value: comment });
Expand Down Expand Up @@ -173,7 +172,7 @@ function Comments() {
$padding={0}
$color="secondary"
icon={{ src: `/icons/downvote-${theme}.svg`, alt: 'Downvote arrow' }}
onClick={() => handleUnvoteWrapper(option?.id ?? '')}
onClick={() => handleUnVoteWrapper(option?.id ?? '')}
$width={16}
$height={16}
disabled={localOptionHearts === 0}
Expand All @@ -183,17 +182,18 @@ function Comments() {
</FlexRow>
<Subtitle>{option?.optionTitle}</Subtitle>
<Body>{option?.optionSubTitle}</Body>
{/* <Body>
<Bold>Lead author: {option?.user}</Bold> [// TODO]
</Body>
<Body>
<Bold>Co-authors:</Bold> [// TODO]
</Body> */}
<Bold>Lead author:</Bold> {optionUsers?.user?.firstName} {optionUsers?.user?.lastName}
</Body>
{optionUsers?.group?.users && (
<Body>
<Bold>Co-authors:</Bold>{' '}
{optionUsers.group.users.map((user) => `${(user.firstName, user.lastName)}`)}
</Body>
)}
</FlexColumn>

<Button onClick={handleSaveVotesWrapper} disabled={!votesAreDifferent}>
Save votes
</Button>
<Button onClick={handleSaveVoteWrapper}>Save votes</Button>
<Form>
<Textarea
label="Leave a comment:"
Expand Down
17 changes: 12 additions & 5 deletions packages/berlin/src/pages/Cycle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import useCountdown from '../hooks/useCountdown';
import useUser from '../hooks/useUser';

// Utils
import { handleSaveVotes, handleUnvote, handleVote } from '../utils/voting';
import {
handleSaveVotes,
handleAvailableHearts,
handleLocalUnVote,
handleLocalVote,
} from '../utils/voting';

// Types
import { ResponseUserVotesType } from '../types/CycleType';
Expand Down Expand Up @@ -137,11 +142,13 @@ function Cycle() {
});

const handleVoteWrapper = (optionId: string) => {
handleVote(optionId, availableHearts, setAvailableHearts, setLocalUserVotes);
setLocalUserVotes((prevLocalUserVotes) => handleLocalVote(optionId, prevLocalUserVotes));
setAvailableHearts(handleAvailableHearts(availableHearts, 'vote'));
};

const handleUnvoteWrapper = (optionId: string) => {
handleUnvote(optionId, availableHearts, setAvailableHearts, setLocalUserVotes);
const handleUnVoteWrapper = (optionId: string) => {
setLocalUserVotes((prevLocalUserVotes) => handleLocalUnVote(optionId, prevLocalUserVotes));
setAvailableHearts(handleAvailableHearts(availableHearts, 'unVote'));
};

const handleSaveVotesWrapper = () => {
Expand Down Expand Up @@ -243,7 +250,7 @@ function Cycle() {
option={option}
numOfVotes={numOfVotes}
onVote={() => handleVoteWrapper(option.id)}
onUnvote={() => handleUnvoteWrapper(option.id)}
onUnVote={() => handleUnVoteWrapper(option.id)}
/>
);
})}
Expand Down
Loading

0 comments on commit a159a82

Please sign in to comment.