Skip to content

Commit 82c69bf

Browse files
committed
Implemented HomePage Sortings
- Implemented most loved and most reviewed sorting apartment functionalities - Implemented HomePage dummy apartment card rows
1 parent 02fda0c commit 82c69bf

File tree

6 files changed

+117
-41
lines changed

6 files changed

+117
-41
lines changed

frontend/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import ProfilePage from './pages/ProfilePage';
99
import BookmarksPage from './pages/BookmarksPage';
1010
import { ThemeProvider } from '@material-ui/core';
1111
import { createTheme } from '@material-ui/core/styles';
12-
import NavBar, { NavbarButton } from './components/utils/NavBar';
12+
import NavBar, { NavbarButton } from './components/utils/NavBar/index';
1313
import NotFoundPage from './pages/NotFoundPage';
1414
import { ApartmentWithId } from '../../common/types/db-types';
1515
import Footer from './components/utils/Footer';

frontend/src/components/ApartmentCard/ApartmentCard.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { Link as RouterLink } from 'react-router-dom';
2525
type Props = {
2626
buildingData: ApartmentWithId;
2727
numReviews: number;
28+
avgRating: number;
2829
company?: string;
2930
user: firebase.User | null;
3031
setUser: React.Dispatch<React.SetStateAction<firebase.User | null>>;
@@ -84,12 +85,14 @@ const useStyles = makeStyles({
8485
* @param {Object} props - Component properties.
8586
* @param {ApartmentWithId} props.buildingData - The data for the apartment.
8687
* @param {number} props.numReviews - The number of reviews for the apartment.
88+
* @param {number} props.avgRating - The average rating for the apartment.
8789
* @param {string} [props.company] - The company associated with the apartment (optional).
8890
* @returns {ReactElement} ApartmentCard component.
8991
*/
9092
const ApartmentCard = ({
9193
buildingData,
9294
numReviews,
95+
avgRating,
9396
company,
9497
user,
9598
setUser,
@@ -330,6 +333,13 @@ const ApartmentCard = ({
330333
>
331334
{numReviews + (numReviews !== 1 ? ' Reviews' : ' Review')}
332335
</Typography>
336+
<Typography
337+
variant="h6"
338+
className={reviewNum}
339+
style={{ fontSize: '10px', lineHeight: 'normal' }}
340+
>
341+
{`Rating: ${avgRating.toFixed(1)}`}
342+
</Typography>
333343
</Grid>
334344
)}
335345
{/* Sample Review */}

frontend/src/components/ApartmentCard/ApartmentCards.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,32 @@ const ApartmentCards = ({
132132
setOrderLowToHigh(false);
133133
},
134134
},
135+
{
136+
item: 'Most Loved',
137+
callback: () => {
138+
setSortBy('avgRating');
139+
setOrderLowToHigh(false);
140+
},
141+
},
142+
{
143+
item: 'Most Reviewed',
144+
callback: () => {
145+
setSortBy('numReviews');
146+
setOrderLowToHigh(false);
147+
},
148+
},
135149
]}
136150
isMobile={isMobile}
137151
/>
138152
</Grid>
139153
<Grid container spacing={3} className={boundingBox}>
140154
{data &&
141155
sortApartments(data, sortBy, orderLowToHigh)
142-
.slice(0, resultsToShow)
143-
.map(({ buildingData, numReviews, company }, index) => {
156+
.slice(0, Math.min(3, resultsToShow))
157+
.map(({ buildingData, numReviews, company, avgRating }, index) => {
144158
const { id } = buildingData;
145159
return (
146-
<Grid item md={12} key={index}>
160+
<Grid item md={4} key={index}>
147161
<Link
148162
{...{
149163
to: `/apartment/${id}`,
@@ -154,6 +168,7 @@ const ApartmentCards = ({
154168
<ApartmentCard
155169
key={index}
156170
numReviews={numReviews}
171+
avgRating={avgRating ?? 0}
157172
buildingData={buildingData}
158173
company={company}
159174
user={user}
@@ -164,7 +179,7 @@ const ApartmentCards = ({
164179
);
165180
})}
166181

167-
{data && data.length > resultsToShow && (
182+
{data && data.length > 3 && resultsToShow > 3 && (
168183
<>
169184
<Grid item xs={12}>
170185
<hr className={horizontalLine} />

frontend/src/components/Search/Autocomplete.tsx

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,15 @@ const Autocomplete = ({ drawerOpen }: Props): ReactElement => {
194194
setOpen(false);
195195
};
196196

197+
const handleClickAway = () => {
198+
setOpen(false);
199+
setOpenFilter(false);
200+
};
201+
197202
const handleOnChange = (query: string) => {
198203
setQuery(query);
199204
setSelected(null);
205+
setOpenFilter(false);
200206
if (query !== '') {
201207
setLoading(true);
202208
} else {
@@ -214,7 +220,6 @@ const Autocomplete = ({ drawerOpen }: Props): ReactElement => {
214220
<ClickAwayListener
215221
onClickAway={() => {
216222
setOpen(false);
217-
setOpenFilter(false);
218223
}}
219224
>
220225
<div>
@@ -354,33 +359,48 @@ const Autocomplete = ({ drawerOpen }: Props): ReactElement => {
354359

355360
return (
356361
<div style={{ position: 'relative', width: drawerOpen ? '100%' : '65%' }}>
357-
<div className={searchBarRow}>
358-
<TextField
359-
fullWidth
360-
ref={inputRef}
361-
value={query}
362-
placeholder={placeholderText}
363-
className={text}
364-
variant="outlined"
365-
style={{
366-
borderRadius: '10px',
367-
width: !isMobile ? '100%' : '98%',
368-
}}
369-
onKeyDown={textFieldHandleListKeyDown}
370-
onChange={(event) => {
371-
const value = event.target.value;
372-
if (value !== '' || value !== null) {
373-
handleOnChange(value);
374-
}
375-
}}
376-
InputProps={getInputProps()}
377-
/>
378-
<IconButton onClick={handleToggleFilter} className={filterIconBackground} disableRipple>
379-
<img src={filterIcon} alt={'filter-icon'} style={{ width: '21.4px', height: '21.4px' }} />
380-
</IconButton>
381-
</div>
382-
<Menu />
383-
<FilterSection filters={filters} onChange={handleFilterChange} open={openFilter} />
362+
<ClickAwayListener onClickAway={handleClickAway}>
363+
<div>
364+
<div className={searchBarRow}>
365+
<TextField
366+
fullWidth
367+
ref={inputRef}
368+
value={query}
369+
placeholder={placeholderText}
370+
className={text}
371+
variant="outlined"
372+
style={{
373+
borderRadius: '10px',
374+
width: !isMobile ? '100%' : '98%',
375+
}}
376+
onKeyDown={textFieldHandleListKeyDown}
377+
onChange={(event) => {
378+
const value = event.target.value;
379+
if (value !== '' || value !== null) {
380+
handleOnChange(value);
381+
}
382+
}}
383+
InputProps={getInputProps()}
384+
/>
385+
<IconButton
386+
onClick={(e) => {
387+
e.stopPropagation(); // Prevent click from triggering ClickAwayListener
388+
handleToggleFilter();
389+
}}
390+
className={filterIconBackground}
391+
disableRipple
392+
>
393+
<img
394+
src={filterIcon}
395+
alt={'filter-icon'}
396+
style={{ width: '21.4px', height: '21.4px' }}
397+
/>
398+
</IconButton>
399+
</div>
400+
<Menu />
401+
<FilterSection filters={filters} onChange={handleFilterChange} open={openFilter} />
402+
</div>
403+
</ClickAwayListener>
384404
</div>
385405
);
386406
};

frontend/src/components/Search/FilterSection.tsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@ const useStyles = makeStyles({
1515
container: {
1616
position: 'absolute',
1717
zIndex: 1,
18-
width: '100%',
18+
minWidth: '100%',
1919
backgroundColor: 'white',
2020
borderRadius: '10px',
2121
marginTop: '5px',
2222
display: 'flex',
2323
flexDirection: 'row',
24+
boxShadow: '0px 0px 10px 0px rgba(0, 0, 0, 0.1)',
2425
},
2526
section: {
2627
marginBottom: '1rem',
2728
backgroundColor: 'white',
28-
borderRadius: '10px',
2929
padding: '1rem',
30-
border: '1px solid rgb(255, 8, 8)',
30+
minWidth: '210px',
3131
},
3232
sectionTitle: {
3333
fontWeight: 'bold',
@@ -99,6 +99,12 @@ const FilterSection: React.FC<FilterSectionProps> = ({ filters, onChange, open }
9999
onChange({ ...filters, [field]: newValue });
100100
};
101101

102+
const handlePriceChange = (field: 'minPrice' | 'maxPrice', value: string) => {
103+
if (value === '' || /^\d+$/.test(value)) {
104+
onChange({ ...filters, [field]: value });
105+
}
106+
};
107+
102108
return (
103109
<div>
104110
{open && (
@@ -128,21 +134,25 @@ const FilterSection: React.FC<FilterSectionProps> = ({ filters, onChange, open }
128134
<TextField
129135
placeholder="No Min"
130136
value={filters.minPrice}
131-
onChange={(e) => onChange({ ...filters, minPrice: e.target.value })}
137+
onChange={(e) => handlePriceChange('minPrice', e.target.value)}
132138
variant="outlined"
133139
size="small"
134-
InputProps={{
140+
type="text"
141+
inputProps={{
142+
pattern: '\\d*',
135143
className: classes.filterText,
136144
}}
137145
/>
138146
<span className={classes.filterText}>-</span>
139147
<TextField
140148
placeholder="No Max"
141149
value={filters.maxPrice}
142-
onChange={(e) => onChange({ ...filters, maxPrice: e.target.value })}
150+
onChange={(e) => handlePriceChange('maxPrice', e.target.value)}
143151
variant="outlined"
144152
size="small"
145-
InputProps={{
153+
type="text"
154+
inputProps={{
155+
pattern: '\\d*',
146156
className: classes.filterText,
147157
}}
148158
/>

frontend/src/pages/HomePage.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,28 @@ const HomePage = ({ user, setUser }: Props): ReactElement => {
132132
</Typography>
133133
<LocationCards />
134134
</Box>
135-
{!isMobile && <ApartmentCards user={user} setUser={setUser} data={data.buildingData} />}
135+
{!isMobile && (
136+
<>
137+
<Box mb={4}>
138+
<Typography variant="h5" style={{ fontWeight: 600 }}>
139+
Close to Central Campus
140+
</Typography>
141+
<ApartmentCards user={user} setUser={setUser} data={data.buildingData} />
142+
</Box>
143+
<Box mb={4}>
144+
<Typography variant="h5" style={{ fontWeight: 600 }}>
145+
Most Reviewed
146+
</Typography>
147+
<ApartmentCards user={user} setUser={setUser} data={data.buildingData} />
148+
</Box>
149+
<Box mb={4}>
150+
<Typography variant="h5" style={{ fontWeight: 600 }}>
151+
Most Loved
152+
</Typography>
153+
<ApartmentCards user={user} setUser={setUser} data={data.buildingData} />
154+
</Box>
155+
</>
156+
)}
136157
</Container>
137158
</Box>
138159
</>

0 commit comments

Comments
 (0)