Skip to content

Commit

Permalink
Merge pull request #15 from builtbysuraj/filter-ui
Browse files Browse the repository at this point in the history
Filter with useSearchParams, Added husky
  • Loading branch information
builtbysuraj authored Jan 21, 2024
2 parents fcdcf88 + fd197d3 commit 6fe18a6
Show file tree
Hide file tree
Showing 33 changed files with 409 additions and 174 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
45 changes: 45 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

echo '
💅🛠️ Formatting and testing project before committing...
'

# Check tsconfig standards
npm run check-types ||
(
echo '
TypeScript Check Failed. ❌
Make the required changes listed above, add changes and try to commit again.
'
false;
)


# Check ESLint Standards
npm run check-lint ||
(
echo '
ESLint Check Failed. ❌
Make the required changes listed above, add changes and try to commit again.
'
false;
)


# Check Prettier standards
npm run check-format-client ||
(
echo '
Prettier Check Failed. ❌
Run npm run format, add changes and try commit again.';
false;
)

npm run check-format-server ||
(
echo '
Prettier Check Failed. ❌
Run npm run format, add changes and try commit again.';
false;
)
5 changes: 4 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
"build": "vite build",
"preview": "vite preview",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"check-lint": "eslint . --ext ts,tsx",
"check-types": "tsc --pretty --noEmit",
"test": "vitest",
"format": "prettier --write ./src"
"format": "prettier --write ./src",
"check-format": "prettier --check ./src"
},
"dependencies": {
"@emotion/react": "^11.11.3",
Expand Down
1 change: 0 additions & 1 deletion client/src/conf/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export const ENV = {
API_BASE_URL: String(import.meta.env.VITE_API_BASE_URL),

}
2 changes: 0 additions & 2 deletions client/src/constants/filterConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ export const SORT_TYPE = {
PRICE_HIGH_TO_LOW: 'priceHighToLow',
PRICE_LOW_TO_HIGH: 'priceLowToHigh',
RATING_HIGH_TO_LOW: 'ratingHighToLow',
RATING_LOW_TO_HIGH: 'ratingLowToHigh',
}

export const RATING_TYPE = {
Expand All @@ -11,4 +10,3 @@ export const RATING_TYPE = {
TWO_AND_UP: '2',
ONE_AND_UP: '1',
}

46 changes: 22 additions & 24 deletions client/src/hooks/useFilters.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,40 @@
import { SORT_TYPE } from '@/constants/filterConstants'
import { useGetAllProductsQuery } from '@/state/services/productApi'
import { useAppSelector } from '@/state/store'
import { ProductType } from '@/types'
import useGetParams from './useGetParams'

export default function useFilter() {
const stateData = useAppSelector((state) => state.filter)
const { data } = useGetAllProductsQuery()
const filteredData = data?.products
?.filter((item) => {
const { data, isLoading } = useGetAllProductsQuery(null)

const { q, category, rating, price, sort } = useGetParams()
const products = data?.products

const filteredData = products
?.filter((item: ProductType) => {
// Price filter
if (
stateData.priceRange &&
!(
item.price >= stateData.priceRange[0] &&
item.price <= stateData.priceRange[1]
)
)
if (price && !(item.price >= price[0] && item.price <= price[1]))
return false

// Rating filter
if (
stateData.stateRating &&
!(item.rating >= Number(stateData.stateRating))
)
return false
if (rating && !(item.rating >= Number(rating))) return false

// Search filter
if (
stateData.searchQuery &&
!item.title.toLowerCase().includes(stateData.searchQuery) &&
!item.category.toLowerCase().includes(stateData.searchQuery) &&
!item.brand.toLowerCase().includes(stateData.searchQuery)
q &&
!item.title.toLowerCase().includes(q.toLowerCase()) &&
!item.category.toLowerCase().includes(q.toLowerCase()) &&
!item.brand.toLowerCase().includes(q.toLowerCase())
)
return false

// category filter
if (category && !(item.category === category)) return false

// Add more filters as needed
return true
})
.sort((a, b) => {
switch (stateData.sort) {
.sort((a: ProductType, b: ProductType) => {
switch (sort) {
case SORT_TYPE.PRICE_HIGH_TO_LOW:
return b.price - a.price
case SORT_TYPE.PRICE_LOW_TO_HIGH:
Expand All @@ -49,5 +47,5 @@ export default function useFilter() {
}
})

return { filteredData }
return { filteredData, isLoading }
}
13 changes: 13 additions & 0 deletions client/src/hooks/useGetParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useSearchParams } from 'react-router-dom'

export default function useGetParams() {
const searchParams = useSearchParams()[0]

const q = searchParams.get('q') || ''
const category = searchParams.get('category') || ''
const rating = searchParams.get('rating') || ''
const price = searchParams.get('price')?.split('-').map(Number) || [10, 2000]
const sort = searchParams.get('sort')

return { category, price, q, rating, sort }
}
53 changes: 39 additions & 14 deletions client/src/hooks/useHandleDispatch.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,47 @@
import { useSearchParams } from 'react-router-dom'

import {
addToCart,
decrementCartItem,
removeFromCart,
} from '@/state/slices/cartSlice'
import {
clearFilters,
filterRating,
filterSearch,
priceRange,
sort,
} from '@/state/slices/filtersSlice'
import { useAppDispatch } from '@/state/store'
import { CartType } from '@/types'
import { CartType, ProductType } from '@/types'

export default function useHandleDispatch() {
const dispatch = useAppDispatch()
const setSearchParams = useSearchParams()[1]

const handlePriceRange = (event: Event, newValue: number | number[]) => {
dispatch(priceRange(newValue))
setSearchParams((prev) => {
// @ts-expect-error - MUI's fault?
prev.set('price', `${newValue[0]}-${newValue[1]}`)
return prev
})
}

const handleFilterRating = (filterValue: string) => {
dispatch(filterRating(filterValue))
setSearchParams((prev) => {
prev.set('rating', filterValue)
return prev
})
}

const handleSort = (sortType: string) => {
dispatch(sort(sortType))
setSearchParams((prev) => {
prev.set('sort', sortType)
return prev
})
}

const handleSearchQuery = (query: string) => {
dispatch(filterSearch(query))
setSearchParams((prev) => {
prev.set('q', query)
return prev
})
}

const handleAddToCart = (data: CartType) => {
const handleAddToCart = (data: ProductType) => {
dispatch(addToCart(data))
}

Expand All @@ -44,8 +53,23 @@ export default function useHandleDispatch() {
dispatch(removeFromCart(cartItemId))
}

const handleCategoryFilter = (category: string) => {
setSearchParams((prev) => {
prev.set('category', category)
prev.delete('q')
return prev
})
}

const handleClearFilter = () => {
dispatch(clearFilters())
setSearchParams((prev) => {
prev.delete('q')
prev.delete('category')
prev.delete('rating')
prev.delete('price')
prev.delete('sort')
return prev
})
}

return {
Expand All @@ -56,6 +80,7 @@ export default function useHandleDispatch() {
handleRemoveFromCart,
handlePriceRange,
handleSearchQuery,
handleCategoryFilter,
handleClearFilter,
}
}
26 changes: 14 additions & 12 deletions client/src/layouts/filters/SidebarFilters.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Box, Button, FormControl, Typography } from '@mui/material'
import { Box, FormControl, Typography } from '@mui/material'
import { useSearchParams } from 'react-router-dom'

import useHandleDispatch from '@/hooks/useHandleDispatch'
import { useAppSelector } from '@/state/store'
import CategoryFilter from './components/CategoryFilter'
import PriceSliderFilter from './components/PriceSliderFilter'
import SortProductsFilter from './components/SortProductsFilter'
import RatingFilter from './components/RatingFilter'
import CategoryFilter from './components/CategoryFilter'
import SortProductsFilter from './components/SortProductsFilter'

export default function SidebarFilters() {
const stateData = useAppSelector((state) => state.filter)
const searchParams = useSearchParams()[0]
const {
handleFilterRating,
handleSort,
Expand All @@ -23,28 +23,30 @@ export default function SidebarFilters() {
</Typography>
<Box display="flex" justifyContent="center" flexDirection="column">
{/* Clear Filters */}
<Button onClick={handleClearFilter} variant="outlined">
Clear Filters
</Button>
<button onClick={handleClearFilter}>Clear Filters</button>
<br />

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

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

{/* Category Filters */}
<CategoryFilter />
<CategoryFilter searchParams={searchParams} />
</Box>
</>
)
Expand Down
Loading

0 comments on commit 6fe18a6

Please sign in to comment.