Skip to content

Commit

Permalink
Create DropDownWithLabel component and revamped all pages with dropdo…
Browse files Browse the repository at this point in the history
…wn component to avoid repetitive code. Fixed dropdown styling to better match figma
  • Loading branch information
kea-roy committed Apr 9, 2024
1 parent 7c21aac commit 2c790ef
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 253 deletions.
114 changes: 56 additions & 58 deletions frontend/src/components/ApartmentCard/ApartmentCards.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { ReactElement, useState } from 'react';
import React, { ReactElement, useEffect, useState } from 'react';
import ApartmentCard from './ApartmentCard';
import { Grid, Link, makeStyles, Button, Typography } from '@material-ui/core';
import { Grid, Link, makeStyles, Button } from '@material-ui/core';
import { Link as RouterLink } from 'react-router-dom';
import { CardData } from '../../App';
import { loadingLength } from '../../constants/HomeConsts';
import DropDown from '../utils/DropDown';
import { ApartmentWithId } from '../../../../common/types/db-types';
import { sortApartments } from '../../utils/sortApartments';
import DropDownWithLabel from '../utils/DropDownWithLabel';

type Props = {
data: CardData[];
Expand Down Expand Up @@ -34,13 +34,6 @@ const useStyles = makeStyles({
borderRight: 'none',
borderBottom: 'none',
},
sortByButton: {
background: '#E8E8E8',
border: 'none',
borderRadius: '10px',
paddingRight: '5px',
paddingLeft: '5px',
},
});

/**
Expand All @@ -58,67 +51,72 @@ const useStyles = makeStyles({
* @returns {ReactElement} ApartmentCards component.
*/
const ApartmentCards = ({ data, user, setUser }: Props): ReactElement => {
const { boundingBox, showMoreButton, horizontalLine, sortByButton } = useStyles();

const { boundingBox, showMoreButton, horizontalLine } = useStyles();
const [isMobile, setIsMobile] = useState<boolean>(false);
const [resultsToShow, setResultsToShow] = useState<number>(loadingLength);

const handleShowMore = () => {
setResultsToShow(resultsToShow + loadingLength);
};

// Handle resizing of the window depending on mobile and if it is clicked.
useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth <= 600);
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);

type Fields = keyof CardData | keyof ApartmentWithId | 'originalOrder';
const [sortBy, setSortBy] = useState<Fields>('originalOrder');
const [orderLowToHigh, setOrderLowToHigh] = useState<boolean>(false);

return (
<>
<Grid item style={{ marginRight: '8px' }}>
<Grid container spacing={1} direction="row" alignItems="center" justifyContent="flex-end">
<Grid item>
<Typography style={{ fontSize: '15px' }}>Sort by:</Typography>
</Grid>
<Grid item className={sortByButton}>
<DropDown
menuItems={[
{
item: 'Recommended',
callback: () => {
setSortBy('originalOrder');
setOrderLowToHigh(false);
},
},
{
item: 'Lowest Price',
callback: () => {
setSortBy('avgPrice');
setOrderLowToHigh(true);
},
},
{
item: 'Highest Price',
callback: () => {
setSortBy('avgPrice');
setOrderLowToHigh(false);
},
},
{
item: 'Lowest Rating',
callback: () => {
setSortBy('avgRating');
setOrderLowToHigh(true);
},
},
{
item: 'Highest Rating',
callback: () => {
setSortBy('avgRating');
setOrderLowToHigh(false);
},
},
]}
/>
</Grid>
</Grid>
<DropDownWithLabel
label="Sort by"
menuItems={[
{
item: 'Recommended',
callback: () => {
setSortBy('originalOrder');
setOrderLowToHigh(false);
},
},
{
item: 'Lowest Price',
callback: () => {
setSortBy('avgPrice');
setOrderLowToHigh(true);
},
},
{
item: 'Highest Price',
callback: () => {
setSortBy('avgPrice');
setOrderLowToHigh(false);
},
},
{
item: 'Lowest Rating',
callback: () => {
setSortBy('avgRating');
setOrderLowToHigh(true);
},
},
{
item: 'Highest Rating',
callback: () => {
setSortBy('avgRating');
setOrderLowToHigh(false);
},
},
]}
isMobile={isMobile}
/>
</Grid>
<Grid container spacing={3} className={boundingBox}>
{data &&
Expand Down
35 changes: 31 additions & 4 deletions frontend/src/components/utils/DropDown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,22 @@
import React, { useState } from 'react';
import { Button, Menu, MenuItem } from '@material-ui/core';
import { makeStyles } from '@material-ui/styles';
import { ArrowDropDown, ArrowDropUp } from '@material-ui/icons';
import SvgIcon from '@material-ui/core/SvgIcon';

const expandArrow = (direction: boolean) => {
return (
<div style={{ paddingLeft: '10px', transform: direction ? 'rotate(180deg)' : 'none' }}>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="12"
viewBox="0 0 20 12"
fill="none"
>
<path d="M1 1L10 10L19 1" stroke="black" strokeWidth="2" />
</svg>
</div>
);
};

type MenuElement = {
item: string;
Expand All @@ -37,6 +51,7 @@ type MenuElement = {

type Props = {
menuItems: MenuElement[];
isMobile?: boolean;
};

const useStyles = makeStyles({
Expand All @@ -47,7 +62,7 @@ const useStyles = makeStyles({
},
});

export default function DropDown({ menuItems }: Props) {
export default function DropDown({ menuItems, isMobile }: Props) {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selected, setSelected] = useState<string>(menuItems[0].item || '-');
const { button } = useStyles();
Expand All @@ -69,9 +84,21 @@ export default function DropDown({ menuItems }: Props) {
aria-expanded={open ? 'true' : undefined}
onClick={handleClick}
className={button}
style={{
textTransform: 'none',
fontSize: '22px',
lineHeight: 'normal',
fontWeight: 'normal',
height: '51px',
paddingLeft: '18px',
paddingRight: '18px',
borderRadius: '10px',
backgroundColor: '#E8E8E8',
scale: isMobile ? '0.75' : '1',
}}
>
{selected}
<SvgIcon component={open ? ArrowDropUp : ArrowDropDown} />
{expandArrow(open)}
</Button>
<Menu
id="basic-menu"
Expand Down
60 changes: 60 additions & 0 deletions frontend/src/components/utils/DropDownWithLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* A dropdown component with a label.
*
* @component
* @example
* // Usage:
* const menuItems = [
* { item: 'Item 1', callback: () => console.log('Item 1 selected') },
* { item: 'Item 2', callback: () => console.log('Item 2 selected') },
* { item: 'Item 3', callback: () => console.log('Item 3 selected') },
* ];
*
* <DropDownWithLabel label="Select an item" menuItems={menuItems} isMobile={true} />
*/
import React from 'react';
import { Typography, Grid } from '@material-ui/core';
import DropDown from './DropDown';

type MenuElement = {
item: string;
callback: () => void;
};

interface DropDownWithLabelProps {
label: string;
menuItems: MenuElement[];
labelStyle?: React.CSSProperties;
isMobile: boolean;
}

const DropDownWithLabel: React.FC<DropDownWithLabelProps> = ({
label,
menuItems,
labelStyle,
isMobile,
}) => {
return (
<div>
<Grid container spacing={0} direction="row" alignItems="center" justifyContent="flex-end">
<Grid item>
<Typography
variant="body1"
style={{
fontSize: isMobile ? '15px' : '23.157px',
paddingRight: isMobile ? '0px' : '11px',
...labelStyle,
}}
>
{label}
</Typography>
</Grid>
<Grid item>
<DropDown menuItems={menuItems} isMobile={isMobile} />
</Grid>
</Grid>
</div>
);
};

export default DropDownWithLabel;
Loading

0 comments on commit 2c790ef

Please sign in to comment.