Skip to content

Commit

Permalink
Merge branch 'master' into enhancement-159-footerApi
Browse files Browse the repository at this point in the history
  • Loading branch information
ArturKhelshtein authored Feb 1, 2024
2 parents 9f306e9 + 13e0f54 commit fe3dd0c
Show file tree
Hide file tree
Showing 19 changed files with 324 additions and 30 deletions.
2 changes: 2 additions & 0 deletions src/app/providers/StoreProvider/config/StateSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { SearchResultSchema } from '@/features/SearchProduct/types/types'
import { LoginSchema } from '@/features/login/model/types/types'
import { BrandSchema } from '@/widgets/BrandBlock/types/types'
import { ApiInstance } from '@/shared/api/api'
import { ShopNewsSchema } from '@/widgets/NewsBlock/model/types/types'
import { StoreReviewsSchema } from '@/widgets/ReviewsBlock/model/types/types'
import { CoreBaseFooterSchema } from '@/widgets/Footer/model/types/types'

Expand All @@ -13,6 +14,7 @@ export interface StateSchema {
coreBaseFooter: CoreBaseFooterSchema
brand: BrandSchema
searchResult: SearchResultSchema
shopNews: ShopNewsSchema
}

export interface ThunkExtraArg {
Expand Down
4 changes: 3 additions & 1 deletion src/app/providers/StoreProvider/config/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import brandSlice from '@/widgets/BrandBlock/slice/brandSlice'
import searchProductSlice from '@/features/SearchProduct/slice/searchProductSlice'
import { storeReviewsReducer } from '@/widgets/ReviewsBlock/model/slice/reviewsSlice'
import footerSlice from '@/widgets/Footer/model/slice/footerSlice'
import { shopNewsReducer } from '@/widgets/NewsBlock/model/slice/shopNewsSlice'

export type RootState = StateSchema

Expand All @@ -16,7 +17,8 @@ const rootReducer: ReducersMapObject<RootState> = {
coreBaseFooter: footerSlice,
brand: brandSlice,
searchResult: searchProductSlice,
storeReviews: storeReviewsReducer
storeReviews: storeReviewsReducer,
shopNews: shopNewsReducer
}

export function createReduxStore(initialState: RootState) {
Expand Down
18 changes: 18 additions & 0 deletions src/assets/icons/image-not-found-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 9 additions & 6 deletions src/entities/NewsCard/NewsCard.module.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@use '@/app/styles/index' as var;

.card {
max-width: 340px;
min-width: 340px;
position: relative;
transition: transform 0.3s ease-in-out;
Expand All @@ -14,12 +15,6 @@
transition: transform 0.3s ease-in-out;
}

img {
border-radius: 6px;
transition: transform 0.3s ease-in-out;
scroll-snap-align: start;
}

.heading
{
font-size: #{'min(max(14px, 1.2vw), 16px)'};
Expand All @@ -46,4 +41,12 @@
line-height: 120%;
font-weight: 500;
}

.img {
height: 180px;
width: 100%;
border-radius: 6px;
transition: transform 0.3s ease-in-out;
scroll-snap-align: start;
}
}
13 changes: 4 additions & 9 deletions src/entities/NewsCard/NewsCard.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react'
import NewsCard from './NewsCard'
import Img1 from '@/assets/images/news/img-news-01.png'

const meta = {
title: 'entities/NewsCard',
Expand All @@ -16,13 +15,9 @@ type Story = StoryObj<typeof meta>

export const Default: Story = {
args: {
card: {
id: 1,
src: Img1,
alt: 'Покупай и не жди. До -50% на весь электротранспорт!',
title: 'Покупай и не жди. До -50% на весь электротранспорт!',
date: '15 Мая, 2022',
promo: true
}
id: 1,
image: 'http://gealit.ru/media/news/18.png',
title: 'Покупай и не жди. До -50% на весь электротранспорт!',
date: '2022-05-15'
}
}
33 changes: 24 additions & 9 deletions src/entities/NewsCard/NewsCard.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,43 @@
import { FC } from 'react'
import { TCard } from '@/models/CardModel'
import { TEXT_PROMO } from '@/shared/constants/constants'
import { FC, useMemo } from 'react'
import styles from './NewsCard.module.scss'
import Link from '@/shared/ui/Link/Link'
import Heading, { HeadingType } from '@/shared/ui/Heading/Heading'
import NoImage from '@/assets/icons/image-not-found-icon.svg'

export type Props = {
card: TCard
id: number
image: string
date: string
title: string
}

/**
* Карточка из блока группы новостей
* @param {TCard} card - параметры карточки из группы новостей
*/

const NewsCard: FC<Props> = ({ card }) => {
const NewsCard: FC<Props> = ({ image, date, title }) => {
const newDate = useMemo(() => {
const _parsedDate = new Date(date)
const year = _parsedDate.getFullYear()
const formatter = new Intl.DateTimeFormat('ru', { month: 'long', day: 'numeric' }).format(_parsedDate)

return `${formatter}, ${year}`
}, [date])

return (
<Link to={''} className={styles.card}>
<img src={card.src} alt={card.alt} draggable="false" />
{image ? (
<img src={image} alt={'новость'} draggable="false" className={styles.img} />
) : (
<NoImage className={styles.img} />
)}
<Heading type={HeadingType.NORMAL} className={styles.heading}>
{card.title}
{title}
</Heading>
<span>{card.date}</span>
{card.promo ? <span className={styles.promo}>{TEXT_PROMO}</span> : null}
<span>{newDate}</span>
{/* TODO */}
{/* {promo ? <span className={styles.promo}>{TEXT_PROMO}</span> : null} */}
</Link>
)
}
Expand Down
21 changes: 21 additions & 0 deletions src/entities/StoryCard/StoryCard.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@use '@/app/styles/index' as var;

.card {
position: relative;
transition: transform 0.3s ease-in-out;
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 15px;

&:hover {
transform: scale(1.1, 1.05);
transition: transform 0.3s ease-in-out;
}

img {
border-radius: 6px;
transition: transform 0.3s ease-in-out;
scroll-snap-align: start;
}
}
25 changes: 25 additions & 0 deletions src/entities/StoryCard/StoryCard.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { Meta, StoryObj } from '@storybook/react'
import StoryCard from './StoryCard'
import Img1 from '@/assets/images/stories/img-stories-01.png'

const meta = {
title: 'entities/StoryCard',
component: StoryCard,
parameters: {
layout: 'centered'
},
tags: ['autodocs']
} satisfies Meta<typeof StoryCard>

export default meta
type Story = StoryObj<typeof meta>

export const Default: Story = {
args: {
card: {
id: 1,
src: Img1,
alt: 'Stock image'
}
}
}
23 changes: 23 additions & 0 deletions src/entities/StoryCard/StoryCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { FC } from 'react'
import { TCard } from '@/models/CardModel'
import styles from './StoryCard.module.scss'
import Link from '@/shared/ui/Link/Link'

export type Props = {
card: TCard
}

/**
* Карточка из блока группы историй
* @param {TCard} card - параметры карточки из группы историй
*/

const StoryCard: FC<Props> = ({ card }) => {
return (
<Link to={''} className={styles.card}>
<img src={card.src} alt={card.alt} draggable="false" />
</Link>
)
}

export default StoryCard
3 changes: 2 additions & 1 deletion src/pages/MainPage/MainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import ReviewsBlock from '@/widgets/ReviewsBlock/ui/ReviewsBlock/ReviewsBlock'
import Advantages from '@/widgets/Advantages/ui/Advantages/Advantages'
import NewsBlock from '@/widgets/NewsBlock/ui/NewsBlock'
import ContainerCards from '@/components/ContainerCards/ContainerCards'

Check failure on line 11 in src/pages/MainPage/MainPage.tsx

View workflow job for this annotation

GitHub Actions / pipeline (18.x)

'ContainerCards' is defined but never used
import StoriesBlock from '@/widgets/StoriesBlock/ui/StoriesBlock'
import BlogBlock from '@/widgets/BlogBlock/ui/BlogBlock'

const MainPage = () => {
return (
<>
<SliderBlock />
<WrapperForMainContent>
<ContainerCards title={TEXT_STORIES} cards={storiesData} />
<StoriesBlock />
<BlogBlock />
<NewsBlock />
<CategoryGrid />
Expand Down
1 change: 1 addition & 0 deletions src/shared/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export enum ApiRoutes {
STORE_REVIEWS = 'store-reviews',
CATEGORIES = 'catalogue/category',
CORE_BASE = 'core/base'
SHOP_NEWS = 'shopnews'
}

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

export const getShopNewsSelector = (state: StateSchema) => {
return state.shopNews.news
}
22 changes: 22 additions & 0 deletions src/widgets/NewsBlock/model/services/getShopNews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { createAsyncThunk } from '@reduxjs/toolkit'
import { ThunkConfig } from '@/app/providers/StoreProvider/config/StateSchema'
import { ApiError, ApiErrorTypes, ApiRoutes } from '@/shared/api/types'
import { apiErrorIdentify } from '@/shared/api/apiErrorIdentify'
import { ShopNewsData } from '../types/types'

// export const getStoreReviews = createAsyncThunk<StoreReviewData[], void, ThunkConfig<ApiError>>(
export const getShopNews = createAsyncThunk<ShopNewsData[], void, ThunkConfig<ApiError>>(
//void1- выходные данные, void2- входные данные , thunkConfig- тип store
'shop-news', // action type, первый аргумент
async (_, thunkAPI) => {
// второй аргумент- асинхронная функция , кот вызовет dispatch в компоненте
const { rejectWithValue, extra } = thunkAPI
try {
const { data } = await extra.api.get(ApiRoutes.SHOP_NEWS)

return data.results
} catch (error) {
return rejectWithValue(apiErrorIdentify(error, ApiErrorTypes.DATA_EMPTY_ERROR))
}
}
)
29 changes: 29 additions & 0 deletions src/widgets/NewsBlock/model/slice/shopNewsSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { createSlice } from '@reduxjs/toolkit'
import { getShopNews } from '../services/getShopNews'
import { ShopNewsSchema } from '../types/types'

const initialState: ShopNewsSchema = {
isLoading: false,
news: []
}

export const shopNewsSlice = createSlice({
name: 'shopNews',
initialState,
reducers: {},
extraReducers: builder => {
builder
.addCase(getShopNews.pending, state => {
state.isLoading = true
})
.addCase(getShopNews.fulfilled, (state, { payload }) => {
state.isLoading = false
state.news = payload
})
.addCase(getShopNews.rejected, state => {
state.isLoading = false
})
}
})

export const { actions: shopNewsActions, reducer: shopNewsReducer } = shopNewsSlice
22 changes: 22 additions & 0 deletions src/widgets/NewsBlock/model/types/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export interface GetShopNewsResponse {
count: number
previous: string
next: string
results: ShopNewsData[]
}

export interface ShopNewsData {
id: number
title: string
text: string
image: string
pub_date: string
slug: string
meta_title: string
meta_description: string
}

export interface ShopNewsSchema {
isLoading: boolean
news: ShopNewsData[]
}
18 changes: 14 additions & 4 deletions src/widgets/NewsBlock/ui/NewsBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import { FC } from 'react'
import { FC, useEffect } from 'react'
import { getShopNewsSelector } from '../model/selectors/selectors'
import { useSelector } from 'react-redux'
import { useAppDispatch } from '@/shared/libs/hooks/store'
import { getShopNews } from '../model/services/getShopNews'
import IconLink from '@/assets/icons/IconLink'
import Heading, { HeadingType } from '@/shared/ui/Heading/Heading'
import Link from '@/shared/ui/Link/Link'
import styles from './NewsBlock.module.scss'
import NewsCard from '@/entities/NewsCard/NewsCard'
import { newsData } from '@/mockData/newsData'
import Scroll from '@/shared/ui/Scroll/Scroll'

/**
* Блок группы новостей
*/
const NewsBlock: FC = () => {
const dispatch = useAppDispatch()
const news = useSelector(getShopNewsSelector)

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

return (
<section className={styles.wrapper}>
<article>
Expand All @@ -21,8 +31,8 @@ const NewsBlock: FC = () => {
</Link>
</article>
<Scroll>
{newsData.map(item => (
<NewsCard key={item.id} card={item} />
{news.map(item => (
<NewsCard key={item.id} id={item.id} image={item.image} date={item.pub_date} title={item.title} />
))}
</Scroll>
</section>
Expand Down
Loading

0 comments on commit fe3dd0c

Please sign in to comment.