Skip to content

Commit

Permalink
feat(search): implement page with search using categories
Browse files Browse the repository at this point in the history
  • Loading branch information
danilych committed Feb 13, 2024
1 parent c92b528 commit b165e02
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 6 deletions.
30 changes: 30 additions & 0 deletions app/data/navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export const categories = [
{
"key": 1,
"value": "Web development"
},
{
"key": 2,
"value": "DevOps"
},
{
"key": 3,
"value": "Back-end development"
},
{
"key": 4,
"value": "Game development"
},
{
"key": 5,
"value": "UX/UI"
},
{
"key": 6,
"value": "Fitness"
},
{
"key": 7,
"value": "Marketing"
}
]
25 changes: 25 additions & 0 deletions app/redux/slices/courses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ export const fetchAuthorCourse = createAsyncThunk(
}
)

export const searchCourses = createAsyncThunk(
'course/searchCourses',
async (params: any) => {
const { data } = await instance.post('/Course/Table', params)

return data
}
)

const initialState = {
courses: {
items: [],
Expand Down Expand Up @@ -119,6 +128,22 @@ const coursesSlice = createSlice({
builder.addCase(fetchAuthorCourse.rejected, (state, action) => {
state.courses.status = 'error'

// @ts-ignore
state.courses.items = null
})
builder.addCase(searchCourses.pending, (state, action) => {
state.courses.status = 'loading'

// @ts-ignore
state.courses.items = null
})
builder.addCase(searchCourses.fulfilled, (state, action) => {
state.courses.status = 'loaded'
state.courses.items = action.payload.data.courses
})
builder.addCase(searchCourses.rejected, (state, action) => {
state.courses.status = 'error'

// @ts-ignore
state.courses.items = null
})
Expand Down
2 changes: 1 addition & 1 deletion app/routes/courses.$course.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function Course() {

if (course.data != null) {
let authorFormData = new FormData()
authorFormData.append('encriptId', (course.data.authorId).toString() as string)
authorFormData.append('encriptId', course.data.authorEncryptedId as string)

dispatch(fetchAuthor(authorFormData))
}
Expand Down
78 changes: 78 additions & 0 deletions app/routes/courses._index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type { ThunkDispatch } from '@reduxjs/toolkit'
import { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { searchCourses } from '~/redux/slices/courses'
import { Header3 } from '~/shared'
import { Spinner } from 'flowbite-react'
import { CourseCard } from '~/entities'

export default function Courses() {
const dispatch = useDispatch<ThunkDispatch<any, any, any>>()

const [categoryValue, setCategoryValue] = useState('Loading')

// @ts-ignore
const { courses } = useSelector(state => state.courses)

const [isCoursesLoading, setIsCoursesLoading] = useState(true)

useEffect(() => {
const value = window.localStorage.getItem('categoryValue')
const key = window.localStorage.getItem('CategoryID')

setCategoryValue(value!)

const requestValue = {
CategoryID: key,
SearchText: '',
LanguageID: '-1',
Rate: '-1',
Level: '-1',
PriceFrom: '0',
PriceTo: '500',
CurrentPage: '0',
}

console.log(courses.items)

dispatch(searchCourses(requestValue))
}, [])

Check warning on line 39 in app/routes/courses._index.tsx

View workflow job for this annotation

GitHub Actions / pipeline (21.x)

React Hook useEffect has missing dependencies: 'courses.items' and 'dispatch'. Either include them or remove the dependency array

useEffect(() => {

Check warning on line 41 in app/routes/courses._index.tsx

View workflow job for this annotation

GitHub Actions / pipeline (21.x)

React Hook useEffect contains a call to 'setIsCoursesLoading'. Without a list of dependencies, this can lead to an infinite chain of updates. To fix this, pass [courses.status] as a second argument to the useEffect Hook
if (courses.status === 'loaded') setIsCoursesLoading(false)

if (courses.status === 'loading') setIsCoursesLoading(true)
})

return (
<div className="py-12 my-[56px] max-w-[1500px] mx-auto">
{isCoursesLoading ? (
<div className="w-full h-[570px]">
<Spinner
className="absolute top-1/2 left-1/2 mt-[-50px] ml-[-50px]"
aria-label="Default status example"
size="lg"
/>
</div>
) : (
<div className="w-full">
<Header3>Pезультати за запитом “{categoryValue}</Header3>

<div className="grid grid-cols-3 mt-4 gap-2 w-[1500px]">
{/* @ts-ignore */}
{courses.items.map((course: any) => (
<CourseCard
key={course.id}
id={course.id}
picturePath={course.picturePath}
name={course.name}
price={course.price}
rating={course.rating}
/>
))}
</div>
</div>
)}
</div>
)
}
23 changes: 18 additions & 5 deletions app/widgets/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ import { useSelector } from 'react-redux'
import { selectIsAuth } from '~/redux/slices/auth'
import { Dropdown } from 'flowbite-react'
import { useEffect } from 'react'
import { categories } from '~/data/navigation'

export default function Navigation() {
const isAuth = useSelector(selectIsAuth)

useEffect(() => {

}, [])
useEffect(() => {}, [])

async function storeCategory(id: any, value: any) {
if (typeof window !== 'undefined') {
window.localStorage.setItem('CategoryID', id)
window.localStorage.setItem('categoryValue', value)
}
}

console.log('isAuth: ', isAuth)
return (
Expand All @@ -32,8 +38,15 @@ export default function Navigation() {
}
inline
>
<Dropdown.Item href="#">Українська</Dropdown.Item>
<Dropdown.Item href="#">Англійська</Dropdown.Item>
{categories.map((category, index) => (
<Dropdown.Item
key={index}
onClick={() => storeCategory(category.key, category.value)}
href="/courses"
>
{category.value}
</Dropdown.Item>
))}
</Dropdown>

<form className="w-[431px] border-b-[1.5px] flex flex-row gap-3 pb-1 border-[#B5B7F6]">
Expand Down

0 comments on commit b165e02

Please sign in to comment.