Skip to content

Commit

Permalink
#150 enhancement: добавить api к BrandBlock через thunk, redux
Browse files Browse the repository at this point in the history
  • Loading branch information
Sibisov-Artem committed Jan 24, 2024
1 parent f573929 commit a0bbd47
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 28 deletions.
2 changes: 2 additions & 0 deletions src/app/providers/SroreProvider/config/StateSchema.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { CategorySchema } from '@/entities/Category/types/types'
import { LoginSchema } from '@/features/login/model/types/types'
import { BrandSchema } from '@/widgets/BrandBlock/types/types'
import { ApiInstance } from '@/shared/api/api'

export interface StateSchema {
login: LoginSchema
category: CategorySchema
brand: BrandSchema
}

export interface ThunkExtraArg {
Expand Down
4 changes: 3 additions & 1 deletion src/app/providers/SroreProvider/config/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { loginReducer } from '@/features/login/model/slice/loginSlice'
import { StateSchema, ThunkExtraArg } from './StateSchema'
import { $api } from '@/shared/api/api'
import categorySlice from '@/entities/Category/slice/categorySlice'
import brandSlice from '@/widgets/BrandBlock/slice/brandSlice'

export type RootState = StateSchema

const rootReducer: ReducersMapObject<StateSchema> = {
login: loginReducer,
category: categorySlice
category: categorySlice,
brand: brandSlice
}

export function createReduxStore(initialState: StateSchema) {
Expand Down
18 changes: 4 additions & 14 deletions src/entities/BrandCard/BrandCard.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
import { FC } from 'react'
import { Routes } from '@/shared/config/routerConfig/routes'
import { TBrand } from '@/models/BrandModel'
import { Brand } from '@/widgets/BrandBlock/types/types'
import Link from '@/shared/ui/Link/Link'
import Img from '@/ui/img'
import BrandWithoutImage from '@/assets/images/brands/brand-without-image.webp'
import {
DEFAULT_WIDTH_FOR_BRANDCARD_IMG,
DEFAULT_HEIGHT_FOR_BRANDCARD_IMG
} from '@/entities/constants/constants'
import styles from './BrandCard.module.scss'

interface BrandCardProps {
card: TBrand
card: Brand
}

/**
* Компонент карточки бренда. Заполнение карточки происходит с применением метода map
* @param {TBrand} card - массив для наполнения карточки бренда;
* @param {Brand} card - массив для наполнения карточки бренда;
*/

const BrandCard: FC<BrandCardProps> = ({ card }) => {
return (
<li className={styles.brand}>
<div className={styles.wrap}>
<Link className={styles.link} to={`${Routes.BRANDS}/${card.slug}`}>
<Img
src={card.image || BrandWithoutImage}
alt={card.name}
width={card.width ?? DEFAULT_WIDTH_FOR_BRANDCARD_IMG}
height={card.height ?? DEFAULT_HEIGHT_FOR_BRANDCARD_IMG}
className={styles.img}
/>
<Img src={card.image || BrandWithoutImage} alt={card.name} className={styles.img} />
</Link>
</div>
</li>
Expand Down
2 changes: 0 additions & 2 deletions src/entities/constants/constants.tsx

This file was deleted.

3 changes: 1 addition & 2 deletions src/pages/MainPage/MainPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import WrapperForMainContent from '@/components/WrapperForMainContent/WrapperForMainContent'
import ContainerCards from '@/components/ContainerCards/ContainerCards'
import SliderBlock from '@/components/SliderBlock/SliderBlock'
import BrandsBlock from '@/widgets/BrandBlock/BrandBlock'
import BrandsBlock from '@/widgets/BrandBlock/ui/BrandBlock/BrandBlock'
import { storiesData } from '@/mockData/storiesData'
import { blogData } from '@/mockData/blogData'
import { newsData } from '@/mockData/newsData'
Expand All @@ -20,7 +20,6 @@ import CategoryGrid from '@/widgets/CategoryGrid/CategoryGrid'
import ReviewsBlock from '@/widgets/ReviewsBlock/ui/ReviewsBlock/ReviewsBlock'
import Advantages from '@/widgets/Advantages/ui/Advantages/Advantages'


const MainPage = () => {
return (
<>
Expand Down
3 changes: 2 additions & 1 deletion src/shared/api/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export enum ApiRoutes {
LOGIN = 'token/login',
LOGOUT = 'token/logout',
CATEGORIES = 'catalogue/category'
CATEGORIES = 'catalogue/category',
BRANDS = 'catalogue/brand'
}

export enum ApiErrorTypes {
Expand Down
3 changes: 3 additions & 0 deletions src/widgets/BrandBlock/selectors/selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { StateSchema } from '@/app/providers/SroreProvider'

export const brandSelector = (state: StateSchema) => state.brand.brands
46 changes: 46 additions & 0 deletions src/widgets/BrandBlock/slice/brandSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import { ApiError, ApiErrorTypes, ApiRoutes } from '@/shared/api/types'
import { ThunkConfig } from '@/app/providers/SroreProvider/config/StateSchema'
import { Brand, BrandSchema } from '../types/types'
import { apiErrorIdentify } from '@/shared/api/apiErrorIdentify'
import { rejectedPayloadHandle } from '@/shared/api/rejectedPayloadHandle'

const initialState: BrandSchema = {
brands: [],
error: undefined
}

export const fetchBrands = createAsyncThunk<Brand[], void, ThunkConfig<ApiError>>(
'catalogue/brand',
async (_, thunkAPI) => {
const { rejectWithValue, extra } = thunkAPI

try {
const response = await extra.api.get(`api/${ApiRoutes.BRANDS}`)

return response.data as Brand[]
} catch (error) {
return rejectWithValue(apiErrorIdentify(error, ApiErrorTypes.DATA_EMPTY_ERROR))
}
}
)

const brandSlice = createSlice({
name: 'brand',
initialState,
reducers: {},
extraReducers: builder => {
builder
.addCase(fetchBrands.pending, state => {
state.error = undefined
})
.addCase(fetchBrands.fulfilled, (state, { payload }) => {
state.brands = payload.filter((c: Brand) => c.is_visible_on_main === true)
})
.addCase(fetchBrands.rejected, (state, { payload }) => {
state.error = rejectedPayloadHandle(payload)
})
}
})

export default brandSlice.reducer
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
export type TBrand = {
export interface BrandSchema {
brands: Brand[]
error?: string | string[]
}

export interface Brand {
id: number
name: string
slug: string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@use '../../shared/styles/utils/variables' as color;
@use '../../shared/styles/utils/mixins' as media;
@use '../../../../shared/styles/utils/variables' as color;
@use '../../../../shared/styles/utils/mixins' as media;

.brands {
width: 100%;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Routes } from '@/shared/config/routerConfig/routes'
import { brandSelector } from '../../selectors/selectors'
import { fetchBrands } from '../../slice/brandSlice'
import { AppDispatch } from '@/app/providers/SroreProvider/config/store'
import IconLink from '@/assets/icons/IconLink'
import Heading, { HeadingType } from '@/shared/ui/Heading/Heading'
import Link from '@/shared/ui/Link/Link'
import BrandCard from '@/entities/BrandCard/BrandCard'
import { brandsData } from '@/mockData/brandData'
import { TEXT_OUR_BRANDS, TEXT_ALL_BRANDS } from '@/shared/constants/constants'
import styles from './BrandBlock.module.scss'

/**
* Компонент списка брендов для главной страницы.
*/
const BrandBlock = () => {
const dispatch = useDispatch<AppDispatch>()
const brands = useSelector(brandSelector)

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

return (
<section className={styles.brands}>
<div className={styles.brands__header}>
Expand All @@ -21,10 +32,9 @@ const BrandBlock = () => {
</Link>
</div>
<ul className={styles.brands__body}>
{brandsData.map(
card =>
card.is_prohibited === false && card.is_visible_on_main && <BrandCard card={card} key={card.id} />
)}
{brands.slice(0, 6).map(card => (
<BrandCard card={card} key={card.id} />
))}
</ul>
</section>
)
Expand Down

0 comments on commit a0bbd47

Please sign in to comment.