Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Senghoung/edit review feature #426

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions api/src/controllers/reviews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,28 @@ router.delete('/clear', async function (req, res) {
res.json({ error: 'Can only clear on development environment' });
}
});
/**
* Updating the review
*/
router.patch('/updateReview', async function (req, res) {
if (req.session.passport) {
const updatedReviewBody = req.body;

const query = {
_id: new ObjectId(req.body._id),
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { _id, ...updateWithoutId } = updatedReviewBody;
await updateDocument(COLLECTION_NAMES.REVIEWS, query, { $set: updateWithoutId });
const responseWithId = {
_id: query._id,
...updateWithoutId,
};

res.json(responseWithId);
} else {
res.status(401).json({ error: 'Must be logged in to update a review.' });
}
});

export default router;
17 changes: 17 additions & 0 deletions site/src/component/Review/Review.scss
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,20 @@
}
}
}

/* Edit review icon */
.edit-pen-icon {
float: right;
font-size: 1.5rem;
width: 3rem;
text-align: center;
padding: 0.1rem;
border-radius: 55%;
}

.edit-pen-icon:hover {
transform: scale(1.1);
transition: transform 0.3s ease;
background: var(--peterportal-mid-gray);
color: white;
}
12 changes: 11 additions & 1 deletion site/src/component/Review/SubReview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@
import { PersonFill } from 'react-bootstrap-icons';
import { ReviewData, VoteRequest, CourseGQLData, ProfessorGQLData, VoteColor } from '../../types/types';
import ReportForm from '../ReportForm/ReportForm';
import { FaPen } from 'react-icons/fa';

interface SubReviewProps {
review: ReviewData;
course?: CourseGQLData;
professor?: ProfessorGQLData;
colors?: VoteColor;
colorUpdater?: () => void;
editable?: boolean;
editReview?: (review: ReviewData, course?: CourseGQLData, professor?: ProfessorGQLData) => void;
}

const SubReview: FC<SubReviewProps> = ({ review, course, professor, colors, colorUpdater }) => {
const SubReview: FC<SubReviewProps> = ({ review, course, professor, colors, colorUpdater, editable, editReview }) => {
const [score, setScore] = useState(review.score);
const [cookies] = useCookies(['user']);

//Edit Review
let upvoteClass;
let downvoteClass;
if (colors != undefined && colors.colors != undefined) {
Expand Down Expand Up @@ -91,6 +96,11 @@

return (
<div className="subreview">
{editable && editReview && (
<div className="edit-pen-icon" onClick={() => editReview(review, course, professor)}>

Check failure on line 100 in site/src/component/Review/SubReview.tsx

View workflow job for this annotation

GitHub Actions / Lint and check formatting

Visible, non-interactive elements with click handlers must have at least one keyboard listener

Check failure on line 100 in site/src/component/Review/SubReview.tsx

View workflow job for this annotation

GitHub Actions / Lint and check formatting

Avoid non-native interactive elements. If using native HTML is not possible, add an appropriate role and support for tabbing, mouse, keyboard, and touch inputs to an interactive content element
<FaPen />
</div>
Comment on lines +100 to +102
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should make this a button not a div for accessibility purposes and then style it appropriately. I agree with Ethan's comments on the button styling.

)}
<div>
<h3 className="subreview-identifier">
{professor && (
Expand Down
160 changes: 118 additions & 42 deletions site/src/component/ReviewForm/ReviewForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import RangeSlider from 'react-bootstrap-range-slider';
import Modal from 'react-bootstrap/Modal';
import ReCAPTCHA from 'react-google-recaptcha';

import { addReview } from '../../store/slices/reviewSlice';
import { useAppDispatch, useAppSelector } from '../../store/hooks';
import { ReviewProps } from '../Review/Review';
Expand All @@ -21,6 +20,8 @@

interface ReviewFormProps extends ReviewProps {
closeForm: () => void;
editable?: boolean;
review?: ReviewData;
}

const ReviewForm: FC<ReviewFormProps> = (props) => {
Expand All @@ -44,7 +45,7 @@
'Group projects',
'Gives good feedback',
];

const [reviewId, setReviewId] = useState<string | undefined>(props.review?._id); //edit review
const [professor, setProfessor] = useState(props.professor?.ucinetid || '');
const [course, setCourse] = useState(props.course?.id || '');
const [yearTaken, setYearTaken] = useState('');
Expand Down Expand Up @@ -82,19 +83,48 @@
if (cookies.user === undefined) {
alert('You must be logged in to add a review!');
props.closeForm();
} else {
setSubmitted(false);
}
}
}, [showForm, props, cookies]);
//If editable is true
if (props.review) {
const [year, quarter] = props.review.quarter.split(' ');
setReviewId(props.review?._id);
setQuarterTaken(quarter);
setYearTaken(year);
setGradeReceived(props.review.gradeReceived);
setDifficulty(props.review.difficulty);
setQuality(props.review.rating);
setContent(props.review?.reviewContent);
setSelectedTags(props.review?.tags);
setAttendance(props.review?.attendance);
setTakeAgain(props.review?.takeAgain);
setTextbook(props.review?.textbook);
setUserName(props.review?.userDisplay);
setProfessor(props.review?.professorID);
setCourse(props.review?.courseID);
}
}, [showForm]);

Check warning on line 108 in site/src/component/ReviewForm/ReviewForm.tsx

View workflow job for this annotation

GitHub Actions / Lint and check formatting

React Hook useEffect has missing dependencies: 'cookies.user' and 'props'. Either include them or remove the dependency array. However, 'props' will change when *any* prop changes, so the preferred fix is to destructure the 'props' object outside of the useEffect call and refer to those specific props inside useEffect
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the dependencies to clear the warning. The lint check will allow warnings but our goal should be to have none so let's make sure not to add anymore.

Suggested change
}, [showForm]);
}, [showForm, cookies.user, props]);


const postReview = async (review: ReviewData) => {
const res = await axios.post<ReviewData>('/api/reviews', review).catch((err) => err.response);
if (res.status === 400) {
alert(res.data.error ?? 'You have already submitted a review for this course/professor');
} else if (res.data.error !== undefined) {
alert('You must be logged in to add a review!');
if (props.editable) {
const res = await axios.patch('/api/reviews/updateReview', review);
if (res.data.hasOwnProperty.call(res.data, 'error')) {
alert('You must be logged in to edit the review!');
} else {
setSubmitted(true);
}
} else {
setSubmitted(true);
dispatch(addReview(res.data));
const res = await axios.post<ReviewData>('/api/reviews', review).catch((err) => err.response);
if (res.status === 400) {
alert(res.data.error ?? 'You have already submitted a review for this course/professor');
} else if (res.data.error !== undefined) {
alert('You must be logged in to add a review!');
} else {
setSubmitted(true);
dispatch(addReview(res.data));
}
}
};

Expand All @@ -116,35 +146,69 @@
alert('Please complete the CAPTCHA');
return;
}

const date = new Date();
const year = date.getFullYear();
const month = (1 + date.getMonth()).toString();
const day = date.getDate().toString();
const review = {
professorID: professor,
courseID: course,
userID: userID,
userDisplay: userName,
reviewContent: content,
rating: quality,
difficulty: difficulty,
timestamp: month + '/' + day + '/' + year,
gradeReceived: gradeReceived,
forCredit: true,
quarter: yearTaken + ' ' + quarterTaken,
score: 0,
takeAgain: takeAgain,
textbook: textbook,
attendance: attendance,
tags: selectedTags,
captchaToken: captchaToken,
};
if (content.length > 500) {
setOverCharLimit(true);
if (props.editable === false) {
Copy link
Member

@js0mmer js0mmer Feb 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to specifically === false, or can we just:

Suggested change
if (props.editable === false) {
if (!props.editable) {

const date = new Date();
const year = date.getFullYear();
const month = (1 + date.getMonth()).toString();
const day = date.getDate().toString();
const review = {
professorID: professor,
courseID: course,
userID: userID,
userDisplay: userName,
reviewContent: content,
rating: quality,
difficulty: difficulty,
timestamp: month + '/' + day + '/' + year,
gradeReceived: gradeReceived,
forCredit: true,
quarter: yearTaken + ' ' + quarterTaken,
score: 0,
takeAgain: takeAgain,
textbook: textbook,
attendance: attendance,
tags: selectedTags,
captchaToken: captchaToken,
};
if (content.length > 500) {
setOverCharLimit(true);
} else {
setOverCharLimit(false);
postReview(review);
}
} else {
setOverCharLimit(false);
postReview(review);
const date = new Date();
const year = date.getFullYear();
const month = (1 + date.getMonth()).toString();
const day = date.getDate().toString();
const review = {
_id: reviewId,
professorID: professor,
courseID: course,
userID: userID,
userDisplay: userName,
reviewContent: content,
rating: quality,
difficulty: difficulty,
timestamp: month + '/' + day + '/' + year,
gradeReceived: gradeReceived,
forCredit: true,
quarter: yearTaken + ' ' + quarterTaken,
score: 0,
takeAgain: takeAgain,
textbook: textbook,
attendance: attendance,
tags: selectedTags,
verified: false,
captchaToken: captchaToken,
};
if (content.length > 500) {
setOverCharLimit(true);
} else {
setOverCharLimit(false);
postReview(review);
setSubmitted(true);
}
}
};

Expand Down Expand Up @@ -234,10 +298,14 @@
<Col>
<Row>
<Col>
<h1>
It's your turn to review{' '}
{props.course ? props.course?.department + ' ' + props.course?.courseNumber : props.professor?.name}
</h1>
{props.editable ? (
<h1>Edit your review for {props.review?.courseID + ' ' + props.review?.professorID}</h1>
) : (
<h1>
It's your turn to review{' '}
{props.course ? props.course?.department + ' ' + props.course?.courseNumber : props.professor?.name}
</h1>
)}
</Col>
</Row>
<Row className="mt-4" lg={2} md={1}>
Expand All @@ -254,6 +322,7 @@
defaultValue=""
required
onChange={(e) => setGradeReceived(e.target.value)}
value={gradeReceived}
>
<option disabled={true} value="">
Grade
Expand All @@ -278,6 +347,7 @@
defaultValue=""
required
onChange={(e) => setQuarterTaken(e.target.value)}
value={quarterTaken}
>
<option disabled={true} value="">
Quarter
Expand All @@ -296,6 +366,7 @@
defaultValue=""
required
onChange={(e) => setYearTaken(e.target.value)}
value={yearTaken}
>
<option disabled={true} value="">
Year
Expand Down Expand Up @@ -349,20 +420,23 @@
id="takeAgain"
label="Would Take Again"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setTakeAgain(e.target.checked)}
checked={takeAgain}
/>
<Form.Check
inline
type="switch"
id="textbook"
label="Use Textbook"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setTextbook(e.target.checked)}
checked={textbook}
/>
<Form.Check
inline
type="switch"
id="attendance"
label="Mandatory Attendance"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setAttendance(e.target.checked)}
checked={attendance}
/>
</Col>
</Row>
Expand Down Expand Up @@ -407,6 +481,7 @@
setOverCharLimit(false);
}
}}
value={props.editable ? content : props.review?.reviewContent}
/>
{/* <textarea rows={5} /> */}
<div className="char-limit">
Expand Down Expand Up @@ -444,6 +519,7 @@
setUserName(cookies.user.name);
}
}}
checked={userName === 'Anonymous Peter'}
/>
</Col>
</Row>
Expand Down
5 changes: 5 additions & 0 deletions site/src/component/UserReviews/UserReviews.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,8 @@
align-items: flex-end;
}
}

//Delete modal
.delete-review-modal {
text-align: center !important;
}
Loading
Loading