diff --git a/frontend/src/components/Candidate-Decider/CandidateDecider.module.css b/frontend/src/components/Candidate-Decider/CandidateDecider.module.css index a0db72b87..b3c76b22d 100644 --- a/frontend/src/components/Candidate-Decider/CandidateDecider.module.css +++ b/frontend/src/components/Candidate-Decider/CandidateDecider.module.css @@ -39,3 +39,7 @@ .showOtherVotes { margin-left: 1%; } + +.previousNextButtonContainer { + margin-right: 0.5% !important; +} diff --git a/frontend/src/components/Candidate-Decider/CandidateDecider.tsx b/frontend/src/components/Candidate-Decider/CandidateDecider.tsx index 479ac9df7..c8812d474 100644 --- a/frontend/src/components/Candidate-Decider/CandidateDecider.tsx +++ b/frontend/src/components/Candidate-Decider/CandidateDecider.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { Button, Dropdown, Checkbox } from 'semantic-ui-react'; import CandidateDeciderAPI from '../../API/CandidateDeciderAPI'; import ResponsesPanel from './ResponsesPanel'; @@ -18,7 +18,7 @@ const CandidateDecider: React.FC = ({ uuid }) => { const [showOtherVotes, setShowOtherVotes] = useState(false); const userInfo = useSelf(); - const instance = useCandidateDeciderInstance(uuid); + const [instance, setInstance] = useCandidateDeciderInstance(uuid); const getRating = () => { const rating = instance.candidates[currentCandidate].ratings.find( @@ -36,6 +36,17 @@ const CandidateDecider: React.FC = ({ uuid }) => { return ''; }; + const [currentRating, setCurrentRating] = useState(0); + const [currentComment, setCurrentComment] = useState(''); + + useEffect(() => { + if (instance.candidates[currentCandidate]) { + setCurrentRating(getRating()); + setCurrentComment(getComment()); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [currentCandidate, instance.candidates]); + const next = () => { if (currentCandidate === instance.candidates.length - 1) return; setCurrentCandidate((prev) => prev + 1); @@ -48,10 +59,52 @@ const CandidateDecider: React.FC = ({ uuid }) => { const handleRatingChange = (id: number, rating: Rating) => { CandidateDeciderAPI.updateRating(instance.uuid, id, rating); + if (userInfo) { + setInstance((instance) => ({ + ...instance, + candidates: instance.candidates.map((candidate) => + candidate.id === id + ? { + ...candidate, + ratings: candidate.ratings.find( + (currRating) => currRating.reviewer.email === userInfo.email + ) + ? candidate.ratings.map((currRating) => + currRating.reviewer.email === userInfo.email + ? { rating, reviewer: userInfo } + : currRating + ) + : [...candidate.ratings, { rating, reviewer: userInfo }] + } + : candidate + ) + })); + } }; const handleCommentChange = (id: number, comment: string) => { CandidateDeciderAPI.updateComment(instance.uuid, id, comment); + if (userInfo) { + setInstance((instance) => ({ + ...instance, + candidates: instance.candidates.map((candidate) => + candidate.id === id + ? { + ...candidate, + comments: candidate.comments.find( + (currComment) => currComment.reviewer.email === userInfo.email + ) + ? candidate.comments.map((currComment) => + currComment.reviewer.email === userInfo.email + ? { comment, reviewer: userInfo } + : currComment + ) + : [...candidate.comments, { comment, reviewer: userInfo }] + } + : candidate + ) + })); + } }; return instance.candidates.length === 0 ? ( @@ -76,7 +129,7 @@ const CandidateDecider: React.FC = ({ uuid }) => { onChange={(_, data) => setCurrentCandidate(data.value as number)} /> of {instance.candidates.length} - + @@ -89,6 +142,16 @@ const CandidateDecider: React.FC = ({ uuid }) => { NEXT + = ({ uuid }) => {
diff --git a/frontend/src/components/Candidate-Decider/ResponsesPanel.tsx b/frontend/src/components/Candidate-Decider/ResponsesPanel.tsx index d0dbb1a64..b8c4c0bcd 100644 --- a/frontend/src/components/Candidate-Decider/ResponsesPanel.tsx +++ b/frontend/src/components/Candidate-Decider/ResponsesPanel.tsx @@ -1,15 +1,14 @@ -import { useEffect, useState } from 'react'; -import { Form, Radio, Button } from 'semantic-ui-react'; +import { Dispatch, SetStateAction } from 'react'; +import { Form, Radio } from 'semantic-ui-react'; import styles from './ResponsesPanel.module.css'; type Props = { headers: string[]; responses: string[]; - rating: Rating; - handleRatingChange: (id: number, rating: Rating) => void; - comment: string; - handleCommentChange: (id: number, comment: string) => void; - currentCandidate: number; + currentRating: Rating; + setCurrentRating: Dispatch>; + currentComment: string; + setCurrentComment: Dispatch>; }; const ratings = [ @@ -24,11 +23,10 @@ const ratings = [ const ResponsesPanel: React.FC = ({ headers, responses, - rating, - handleRatingChange, - currentCandidate, - handleCommentChange, - comment + currentRating, + setCurrentRating, + currentComment, + setCurrentComment }) => (
@@ -40,17 +38,13 @@ const ResponsesPanel: React.FC = ({ name="rating-group" value={rt.value} color={rt.color} - checked={rt.value === rating} - onChange={() => handleRatingChange(currentCandidate, rt.value as Rating)} + checked={rt.value === currentRating} + onClick={() => setCurrentRating(rt.value as Rating)} /> ))} - + {headers.map((header, i) => (
@@ -62,40 +56,20 @@ const ResponsesPanel: React.FC = ({ ); type CommentEditorProps = { - comment: string; - handleCommentChange: (id: number, comment: string) => void; - currentCandidate: number; + currentComment: string; + setCurrentComment: Dispatch>; }; -const CommentEditor: React.FC = ({ - handleCommentChange, - comment, - currentCandidate -}) => { - const [currentComment, setCurrentComment] = useState(comment); - - useEffect(() => setCurrentComment(comment), [comment]); - - return ( -
- - setCurrentComment(data.value)} - value={currentComment} - /> - - -
- ); -}; +const CommentEditor: React.FC = ({ currentComment, setCurrentComment }) => ( +
+ + setCurrentComment(data.value)} + value={currentComment} + /> + +
+); export default ResponsesPanel; diff --git a/frontend/src/components/Candidate-Decider/useCandidateDeciderInstance.tsx b/frontend/src/components/Candidate-Decider/useCandidateDeciderInstance.tsx index f7aa316b3..1c5f19ad8 100644 --- a/frontend/src/components/Candidate-Decider/useCandidateDeciderInstance.tsx +++ b/frontend/src/components/Candidate-Decider/useCandidateDeciderInstance.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, Dispatch, SetStateAction } from 'react'; import { onSnapshot, doc, collection, getDoc, DocumentReference } from 'firebase/firestore'; import { db } from '../../firebase'; @@ -28,7 +28,9 @@ export type DBCandidateDeciderInstance = { readonly authorizedRoles: Role[]; isOpen: boolean; }; -const useCandidateDeciderInstance = (uuid: string): CandidateDeciderInstance => { +const useCandidateDeciderInstance = ( + uuid: string +): [CandidateDeciderInstance, Dispatch>] => { const [instance, setInstance] = useState(blankInstance); useEffect(() => { @@ -67,7 +69,7 @@ const useCandidateDeciderInstance = (uuid: string): CandidateDeciderInstance => return unsubscribe; }, [uuid]); - return instance; + return [instance, setInstance]; }; const blankInstance: CandidateDeciderInstance = {