diff --git a/frontend/src/colors.js b/frontend/src/colors.js index 3569e748..d8447c4d 100644 --- a/frontend/src/colors.js +++ b/frontend/src/colors.js @@ -9,6 +9,7 @@ export const colors = { gray1: '#5D5D5D', gray2: '#898989', gray3: '#F9F9F9', + gray4: '#C4C4C4', white: '#FFFFFF', landlordCardRed: '#F3664B', green1: '#68BB59', diff --git a/frontend/src/components/Review/ReviewHeader.tsx b/frontend/src/components/Review/ReviewHeader.tsx index 4e75c1d5..a81a1d5e 100644 --- a/frontend/src/components/Review/ReviewHeader.tsx +++ b/frontend/src/components/Review/ReviewHeader.tsx @@ -3,12 +3,24 @@ import { Grid, Typography } from '@material-ui/core'; import styles from './Review.module.scss'; import LabeledLinearProgress from '../utils/LabeledLinearProgress'; import { RatingInfo } from '../../pages/LandlordPage'; +import { useEffect, useState } from 'react'; type Props = { readonly aveRatingInfo: RatingInfo[]; }; export default function ReviewHeader({ aveRatingInfo }: Props): ReactElement { + const [isMobile, setIsMobile] = useState(false); + + useEffect(() => { + const handleResize = () => { + setIsMobile(window.innerWidth <= 750); + }; + handleResize(); + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); + return (
@@ -20,7 +32,7 @@ export default function ReviewHeader({ aveRatingInfo }: Props): ReactElement { {feature.charAt(0).toUpperCase() + feature.slice(1)} - + diff --git a/frontend/src/components/utils/LabeledLinearProgress.tsx b/frontend/src/components/utils/LabeledLinearProgress.tsx index a9f10ec8..c6c835a7 100644 --- a/frontend/src/components/utils/LabeledLinearProgress.tsx +++ b/frontend/src/components/utils/LabeledLinearProgress.tsx @@ -1,8 +1,6 @@ import React, { ReactElement } from 'react'; -import Box from '@material-ui/core/Box'; -import LinearProgress from '@material-ui/core/LinearProgress'; +import { colors } from '../../colors'; import Typography from '@material-ui/core/Typography'; -import styles from '../Review/Review.module.scss'; import { makeStyles } from '@material-ui/core'; type Props = { @@ -10,25 +8,63 @@ type Props = { }; const useStyles = makeStyles((theme) => ({ - bar: { - width: '90%', + barContainer: { + display: 'flex', + alignItems: 'center', + }, + barSegment: { + flex: 1, + height: '8px', // Adjust the height as needed + borderRadius: '4px', // Adjust the border radius as needed + marginRight: '4px', // Add a small gap between segments + }, + aveRating: { + marginLeft: '8px', // Add spacing between the segments and the rating }, })); export default function LabeledLinearProgress({ value }: Props): ReactElement { - const { bar } = useStyles(); + const { barContainer, barSegment, aveRating } = useStyles(); + let rating_value = value - 1; + + const segments = Array.from({ length: 5 }, (_, index) => ( + /** + * This JSX code represents a rendering of a bar segment for a rating display. The rating value is used to determine the visual appearance of the segment. + * + * @param {number} index - The index of the segment within the rating bar. + * @param {string} barSegment - The CSS class name for styling the segment. + * @param {number} rating_value - The rating value to be displayed. + * + * The background style of the div is set based on the index and rating value: + * - If the index is less than or equal to the rating_value, the background is set to colors.red1. + * - If the index is greater than the rating_value and is exactly 0.5 more than the rating_value, a gradient background is applied. The gradient transitions from colors.red1 to colors.gray4, creating a partial fill effect. + * - For all other cases, the background is set to colors.gray4. + */ + /** + * Make it so the segments fill, and when there is a decimal leftover, the segment gets filled to that decimal. + */ +
rating_value && index - 1 < rating_value + ? `linear-gradient(to right, ${colors.red1} ${(rating_value - index + 1 / 1) * 100}%, ${ + colors.gray4 + } 0%)` + : colors.gray4, + }} + >
+ )); + return ( - - - - - - {`${value.toFixed(1)}`} - - +
+ {segments} + + {value !== null && value !== undefined ? value.toFixed(1) : ''} + +
); } diff --git a/frontend/src/pages/ApartmentPage.tsx b/frontend/src/pages/ApartmentPage.tsx index f20483db..a08afffb 100644 --- a/frontend/src/pages/ApartmentPage.tsx +++ b/frontend/src/pages/ApartmentPage.tsx @@ -156,11 +156,6 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => { } }, [isMobile, reviewData.length]); - // Increase the number of results to show when the "Show More" button is clicked. - const handleShowMore = () => { - setResultsToShow(resultsToShow + 5); - }; - // Set 'notFound' to true when a page is not found. const handlePageNotFound = () => { setNotFound(true); @@ -176,7 +171,6 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => { container, expand, expandOpen, - horizontalLine, } = useStyles(); // Set the page title based on whether apartment data is loaded. @@ -364,9 +358,11 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => { ); const Header = ( + // Header section with review count, average rating, and leave review button + <> - + Reviews ({reviewData.length}) {reviewData.length === 0 && ( @@ -375,7 +371,7 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => { {reviewData.length > 0 && ( - + @@ -388,6 +384,18 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => { )} + + + + {landlordData && landlordData.photos.length > 0 && ( @@ -403,48 +411,14 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => { - - - - - - - Sort by: - - - { - setSortBy('date'); - }, - }, - { - item: 'Helpful', - callback: () => { - setSortBy('likes'); - }, - }, - ]} - /> - - - + + {reviewData && reviewData.length > 0 && ( - + )} @@ -560,9 +534,8 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => { ); - const InfoSection = landlordData && ( - + Landlord @@ -595,7 +568,7 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => { - + {isMobile ? MobileHeader : Header} {!isMobile && {InfoSection}} {showConfirmation && ( @@ -614,52 +587,78 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => { time={toastTime} /> )} - - {sortReviews(reviewData, sortBy) - .slice(0, resultsToShow) - .map((review, index) => ( - - - - ))} - - {isMobile && reviewData.length > resultsToShow && ( - - -
-
- - + + Sort by: + + + { + setSortBy('date'); + }, + }, + { + item: 'Helpful', + callback: () => { + setSortBy('likes'); + }, + }, + ]} + /> + + + )} + + + {sortReviews(reviewData, sortBy) + .slice(0, resultsToShow) + .map((review, index) => ( + + + + ))} -
- )} +
+ + {/* Second Grid item (InfoSection) */} + {isMobile && ( + + + {InfoSection} + + + )} + + + {InfoSection} + + +
- {isMobile && {InfoSection}} - {InfoSection}
{Modals}