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

Updating Apartment Page UI/Functionality V3 #309

Merged
merged 11 commits into from
Nov 13, 2023
1 change: 1 addition & 0 deletions frontend/src/colors.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const colors = {
gray1: '#5D5D5D',
gray2: '#898989',
gray3: '#F9F9F9',
gray4: '#C4C4C4',
white: '#FFFFFF',
landlordCardRed: '#F3664B',
green1: '#68BB59',
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Review/ReviewHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function ReviewHeader({ aveRatingInfo }: Props): ReactElement {
{feature.charAt(0).toUpperCase() + feature.slice(1)}
</Typography>
</Grid>
<Grid item xs={7} md={7} lg={7}>
<Grid item xs={7} style={{ marginLeft: '-10%' }}>
<LabeledLinearProgress value={rating} />
</Grid>
</Grid>
Expand Down
69 changes: 51 additions & 18 deletions frontend/src/components/utils/LabeledLinearProgress.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,67 @@
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 = {
readonly value: number;
};

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 * 2;
rating_value = Math.round(rating_value);
rating_value = rating_value / 2 - 1;
console.log(rating_value);
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.
*/
<div
key={index}
className={barSegment}
style={{
background:
index <= rating_value
? colors.red1
: index > rating_value && rating_value + 0.5 === index
? `linear-gradient(to right, ${colors.red1} 0%, ${colors.red1} 50%, ${colors.gray4} 50%, ${colors.gray4} 100%)`
: colors.gray4,
}}
></div>
));

return (
<Box className={styles.barContainer} display="flex" alignItems="center">
<Box width="90%" mr={1}>
<LinearProgress className={bar} variant="determinate" value={value * 20} />
</Box>
<Box minWidth={35}>
<Typography
className={styles.aveRating}
variant="body2"
color="textSecondary"
>{`${value.toFixed(1)}`}</Typography>
</Box>
</Box>
<div className={barContainer}>
{segments}
<Typography className={aveRating} variant="body2" color="textSecondary">
{`${value.toFixed(1)}`}
</Typography>
</div>
);
}
179 changes: 92 additions & 87 deletions frontend/src/pages/ApartmentPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,9 @@ 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);
};
// const handleShowMore = () => {
// setResultsToShow(resultsToShow + 5);
// };

// Set 'notFound' to true when a page is not found.
const handlePageNotFound = () => {
Expand All @@ -176,7 +175,6 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => {
container,
expand,
expandOpen,
horizontalLine,
} = useStyles();

// Set the page title based on whether apartment data is loaded.
Expand Down Expand Up @@ -364,9 +362,11 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => {
);

const Header = (
// Header section with review count, average rating, and leave review button

<>
<Grid container alignItems="center">
<Grid container spacing={1}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item>
<Typography variant="h6">Reviews ({reviewData.length})</Typography>
{reviewData.length === 0 && (
Expand All @@ -375,7 +375,7 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => {
</Grid>

{reviewData.length > 0 && (
<Grid item>
<Grid item style={{ paddingLeft: '20px' }}>
<Grid container alignItems="center">
<Grid item className={heartRating}>
<HeartRating value={getAverageRating(reviewData)} precision={0.5} readOnly />
Expand All @@ -388,6 +388,18 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => {
</Grid>
</Grid>
)}

<Grid item style={{ marginLeft: 'auto' }}>
<Button
color="primary"
className={reviewButton}
variant="contained"
disableElevation
onClick={openReviewModal}
>
Leave a Review
</Button>
</Grid>
</Grid>

{landlordData && landlordData.photos.length > 0 && (
Expand All @@ -403,42 +415,8 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => {

<Grid item className={leaveReviewContainer} xs={12}>
<Grid container spacing={1} alignItems="center" justifyContent="space-between">
<Grid item>
<Button
color="primary"
className={reviewButton}
variant="contained"
disableElevation
onClick={openReviewModal}
>
Leave a Review
</Button>
</Grid>
<Grid item>
<Grid container spacing={1} direction="row" alignItems="center">
<Grid item>
<Typography>Sort by:</Typography>
</Grid>
<Grid item className={sortByButton}>
<DropDown
menuItems={[
{
item: 'Recent',
callback: () => {
setSortBy('date');
},
},
{
item: 'Helpful',
callback: () => {
setSortBy('likes');
},
},
]}
/>
</Grid>
</Grid>
</Grid>
<Grid item></Grid>
<Grid item></Grid>
</Grid>
</Grid>
</Grid>
Expand Down Expand Up @@ -560,9 +538,8 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => {
</Grid>
</>
);

const InfoSection = landlordData && (
<Grid item xs={12} sm={4}>
<Grid item xs={12}>
<AptInfo
landlord={landlordData.name}
contact={landlordData.contact}
Expand All @@ -573,10 +550,13 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => {
);

return notFound ? (
// Display Not Found page if the apartment is not found
<NotFoundPage />
) : !loaded ? (
// Display Not Found page if the apartment is not found
<LinearProgress />
) : (
// Display Not Found page if the apartment is not found
<>
{landlordData && (
<Container>
Expand All @@ -591,7 +571,7 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => {

<Container className={container}>
<Grid container spacing={5} justifyContent="center" style={{ marginBottom: '20px' }}>
<Grid item xs={12} sm={8}>
<Grid item xs={12}>
{isMobile ? MobileHeader : Header}
{!isMobile && <Hidden smUp>{InfoSection}</Hidden>}
{showConfirmation && (
Expand All @@ -610,51 +590,76 @@ const ApartmentPage = ({ user, setUser }: Props): ReactElement => {
time={toastTime}
/>
)}
<Grid container item spacing={3}>
{sortReviews(reviewData, sortBy)
.slice(0, resultsToShow)
.map((review, index) => (
<Grid item xs={12} key={index}>
<ReviewComponent
review={review}
liked={likedReviews[review.id]}
likeLoading={likeStatuses[review.id]}
addLike={addLike}
removeLike={removeLike}
setToggle={setToggle}
user={user}
setUser={setUser}
/>
<Grid container alignItems="flex-start" justifyContent="center" spacing={3}>
<Grid item xs={12} sm={8}>
{!isMobile && (
<Grid
container
spacing={1}
direction="row"
alignItems="center"
justifyContent="flex-end"
style={{ paddingBottom: '10px' }}
>
<Grid item>
<Typography>Sort by:</Typography>
</Grid>
<Grid item className={sortByButton}>
<DropDown
menuItems={[
{
item: 'Recent',
callback: () => {
setSortBy('date');
},
},
{
item: 'Helpful',
callback: () => {
setSortBy('likes');
},
},
]}
/>
</Grid>
</Grid>
))}
</Grid>

{isMobile && reviewData.length > resultsToShow && (
<Box textAlign="center">
<Grid item xs={12}>
<hr className={horizontalLine} />
)}
{/* Rest of your Review List content */}
<Grid container spacing={3}>
{sortReviews(reviewData, sortBy)
.slice(0, resultsToShow)
.map((review, index) => (
<Grid item xs={12} key={index}>
<ReviewComponent
review={review}
liked={likedReviews[review.id]}
likeLoading={likeStatuses[review.id]}
addLike={addLike}
removeLike={removeLike}
setToggle={setToggle}
user={user}
setUser={setUser}
/>
</Grid>
))}
</Grid>
<Grid item style={{ padding: '30px' }}>
<Button
style={{
backgroundColor: 'white',
border: '1px solid #A3A3A3',
borderRadius: '9px',
width: '10em',
textTransform: 'initial',
}}
variant="contained"
disableElevation
onClick={handleShowMore}
>
Show More
</Button>
</Grid>

{/* Second Grid item (InfoSection) */}
{isMobile && (
<Hidden smUp>
<Grid item xs={12}>
{InfoSection}
</Grid>
</Hidden>
)}
<Hidden xsDown>
<Grid item xs={4}>
{InfoSection}
</Grid>
</Box>
)}
</Hidden>
</Grid>
</Grid>
{isMobile && <Hidden smUp>{InfoSection}</Hidden>}
<Hidden xsDown>{InfoSection}</Hidden>
</Grid>
</Container>
{Modals}
Expand Down
Loading