Skip to content

Commit

Permalink
refactor: Memoized components, Split product listing page
Browse files Browse the repository at this point in the history
  • Loading branch information
builtbysuraj committed Jan 24, 2024
1 parent 3629ad8 commit 6bec812
Show file tree
Hide file tree
Showing 26 changed files with 258 additions and 259 deletions.
2 changes: 1 addition & 1 deletion client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<!-- <link rel="icon" type="image/svg+xml" href="./public/favicon.ico" /> -->
<link rel="icon" type="image/svg+xml" href="./public/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>
Online Shopping Site for Mobiles, Electronics, Furniture, Grocery,
Expand Down
26 changes: 26 additions & 0 deletions client/src/assets/css/reset.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ html {
font-family: system-ui, sans-serif;
}

html,
body {
height: 100%;
}

body {
line-height: 1.5;
min-height: 100vh;
Expand All @@ -30,6 +35,27 @@ select {
font: inherit;
}

button {
/* all: unset; */
}

input[type='radio'],
label[for] {
cursor: pointer;
}

input[type='text'],
input[type='number'],
select,
textarea {
font-size: 16px;
}

button:disabled {
opacity: 0.5;
pointer-events: none;
}

/* responsive images/videos */
img,
picture,
Expand Down
File renamed without changes.
File renamed without changes.
17 changes: 17 additions & 0 deletions client/src/components/loader/Loader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { CircularProgress } from '@mui/material'

export default function Loader() {
return (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: '100vh',
maxWidth: '100vw',
}}
>
<CircularProgress size="3rem" />
</div>
)
}
3 changes: 3 additions & 0 deletions client/src/components/ui/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
type InputProps = {
type: string
name?: string
placeholder?: string
id?: string
value: string
onChange: React.ChangeEventHandler<HTMLInputElement> | undefined
Expand All @@ -12,6 +13,7 @@ type InputProps = {
function Input({
type,
name,
placeholder,
id,
value,
onChange,
Expand All @@ -24,6 +26,7 @@ function Input({
<input
type={type}
name={name}
placeholder={placeholder}
id={id}
value={value}
onChange={onChange}
Expand Down
59 changes: 23 additions & 36 deletions client/src/layouts/filters/SidebarFilters.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,40 @@
import { Box, FormControl, Typography } from '@mui/material'
import { useSearchParams } from 'react-router-dom'
import { memo } from 'react'

import useHandleDispatch from '@/hooks/useHandleDispatch'
import CategoryFilter from './components/CategoryFilter'
import ClearFilter from './components/ClearFilter'
import PriceSliderFilter from './components/PriceSliderFilter'
import RatingFilter from './components/RatingFilter'
import SortProductsFilter from './components/SortProductsFilter'

export default function SidebarFilters() {
const searchParams = useSearchParams()[0]
const {
handleFilterRating,
handleSort,
handlePriceRange,
handleClearFilter,
} = useHandleDispatch()

function SidebarFilters() {
console.log('SidebarFilters')
return (
<>
<Typography component="h1" variant="h5" fontWeight="bold">
Filters
</Typography>
<Box display="flex" justifyContent="center" flexDirection="column">
<h2>Filters</h2>
<div
style={{
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
}}
>
{/* Clear Filters */}
<button onClick={handleClearFilter}>Clear Filters</button>
<br />
<ClearFilter />

{/* Price Filter */}
<PriceSliderFilter
searchParams={searchParams}
handlePriceRange={handlePriceRange}
/>
<FormControl>
{/* Sort products */}
<SortProductsFilter
searchParams={searchParams}
handleSort={handleSort}
/>
<PriceSliderFilter />
{/* Sort products */}
<SortProductsFilter />

{/* Ratings filter */}
<RatingFilter
searchParams={searchParams}
handleFilterRating={handleFilterRating}
/>
</FormControl>
{/* Ratings filter */}
<RatingFilter />

{/* Category Filters */}
<CategoryFilter searchParams={searchParams} />
</Box>
<CategoryFilter />
</div>
</>
)
}

const MemoizedSidebarFilters = memo(SidebarFilters)
export default MemoizedSidebarFilters
64 changes: 25 additions & 39 deletions client/src/layouts/filters/components/CategoryFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { memo } from 'react'

import Input from '@/components/ui/Input'
import useGetParams from '@/hooks/useGetParams'
import useHandleDispatch from '@/hooks/useHandleDispatch'
import { FormControlLabel, Radio, RadioGroup, Typography } from '@mui/material'

const data = {
type CategoryType = Record<string, string>

const data: CategoryType = {
Smartphones: 'smartphones',
Laptops: 'laptops',
Fragrances: 'fragrances',
Expand All @@ -24,47 +29,28 @@ const data = {
Lighting: 'lighting',
}

type Props = {
searchParams: URLSearchParams
}

export default function CategoryFilter({ searchParams }: Props) {
// const formattedCategories = categories.map((category) =>
// category.includes('-')
// ? category
// .split('-')
// .map(
// (splitedWord) =>
// splitedWord.charAt(0).toUpperCase() + splitedWord.slice(1)
// )
// .join(' ')
// : category.charAt(0).toUpperCase() + category.slice(1)
// )
// console.log(formattedCategories)
function CategoryFilter() {
const { handleCategoryFilter } = useHandleDispatch()
const category = searchParams.get('category') || ''

const { category: categoryParam } = useGetParams()
console.log('CategoryFilter')
return (
<>
<Typography component="label" fontWeight="bold" id="category">
Categories
</Typography>
<RadioGroup
aria-labelledby="category"
name="categories"
value={category}
onChange={(e) => handleCategoryFilter(e.target.value)}
>
{Object.keys(data).map((category, index) => (
<FormControlLabel
// @ts-expect-error - type 'string' can't be used to index type
<section>
<h4>Categories</h4>
{Object.keys(data).map((category) => (
<div key={category}>
<Input
type="radio"
value={data[category]}
key={index}
control={<Radio />}
label={category}
id={category}
onChange={(e) => handleCategoryFilter(e.target.value)}
checked={categoryParam === data[category]}
/>
))}
</RadioGroup>
</>
</div>
))}
</section>
)
}

const MemoizedCategoryFilter = memo(CategoryFilter)
export default MemoizedCategoryFilter
11 changes: 11 additions & 0 deletions client/src/layouts/filters/components/ClearFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import useHandleDispatch from '@/hooks/useHandleDispatch'

export default function ClearFilter() {
const { handleClearFilter } = useHandleDispatch()
console.log('ClearFilter')
return (
<section>
<button onClick={handleClearFilter}>Clear Filters</button>
</section>
)
}
37 changes: 17 additions & 20 deletions client/src/layouts/filters/components/PriceSliderFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import { Box, Slider, Typography } from '@mui/material'
import Slider from '@mui/material/Slider'
import { memo } from 'react'

type Props = {
searchParams: URLSearchParams
handlePriceRange: (arg0: Event, arg1: number | number[]) => void
}

export default function PriceSliderFilter({
searchParams,
handlePriceRange,
}: Props) {
const price = searchParams.get('price')?.split('-').map(Number) || [10, 2000]
import useGetParams from '@/hooks/useGetParams'
import useHandleDispatch from '@/hooks/useHandleDispatch'

function PriceSliderFilter() {
const { handlePriceRange } = useHandleDispatch()
const { price } = useGetParams()
console.log('PriceSliderFilter')
return (
<>
<Typography fontWeight="bold">Price</Typography>
<Typography fontWeight="bold">
<br />
{`$${price[0]} - $${price[1]}`}
</Typography>
<Box sx={{ m: 2 }}>
<section>
<h4>Price</h4>
<h4>{`$${price[0]} - $${price[1]}`}</h4>
<div style={{ margin: '1rem' }}>
<Slider
value={price}
onChange={handlePriceRange}
Expand All @@ -27,7 +21,10 @@ export default function PriceSliderFilter({
min={10}
step={100}
/>
</Box>
</>
</div>
</section>
)
}

const MemoizedPriceSliderFilter = memo(PriceSliderFilter)
export default MemoizedPriceSliderFilter
36 changes: 18 additions & 18 deletions client/src/layouts/filters/components/RatingFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
import { memo } from 'react'

import Input from '@/components/ui/Input'
import { RATING_TYPE } from '@/constants/filterConstants'
import useGetParams from '@/hooks/useGetParams'
import useHandleDispatch from '@/hooks/useHandleDispatch'

type Props = {
searchParams: URLSearchParams
handleFilterRating: (arg0: string) => void
}

export default function RatingFilter({
searchParams,
handleFilterRating,
}: Props) {
const rating = searchParams.get('rating') || ''

const ratingItems = [
{ value: RATING_TYPE.FOUR_AND_UP, label: '4 & Up' },
{ value: RATING_TYPE.THREE_AND_UP, label: '3 & Up' },
{ value: RATING_TYPE.TWO_AND_UP, label: '2 & Up' },
{ value: RATING_TYPE.ONE_AND_UP, label: '1 & Up' },
]
const ratingItems = [
{ value: RATING_TYPE.FOUR_AND_UP, label: '4 & Up' },
{ value: RATING_TYPE.THREE_AND_UP, label: '3 & Up' },
{ value: RATING_TYPE.TWO_AND_UP, label: '2 & Up' },
{ value: RATING_TYPE.ONE_AND_UP, label: '1 & Up' },
]

function RatingFilter() {
const { rating } = useGetParams()
const { handleFilterRating } = useHandleDispatch()
console.log('RatingFilter')
return (
<section>
<h4>Customer Review</h4>
Expand All @@ -29,7 +26,7 @@ export default function RatingFilter({
id={item.label}
checked={rating === item.value}
onChange={(event) => handleFilterRating(event.target.value)}
name="sort"
name="rating"
label={item.label}
value={item.value}
/>
Expand All @@ -39,3 +36,6 @@ export default function RatingFilter({
</section>
)
}

const MemoizedRatingFilter = memo(RatingFilter)
export default MemoizedRatingFilter
Loading

0 comments on commit 6bec812

Please sign in to comment.