Skip to content

Commit

Permalink
Added article entity with block components for code, images, text and…
Browse files Browse the repository at this point in the history
… whole detailed article combined; Article slice, types, selectors. Added shared Skeleton, Icon and Code ui components.

Fixed Input styles and storybook & unit tests.
  • Loading branch information
yaazzik committed Jun 30, 2023
1 parent 2d08c25 commit a24a471
Show file tree
Hide file tree
Showing 177 changed files with 1,077 additions and 130 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_entities_ProfileCard_Dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_entities_ProfileCard_Light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_features_LoginModal_Dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_features_LoginModal_Error.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_features_LoginModal_Light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_features_LoginModal_Loading.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_pages_AboutPage_Dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_pages_AboutPage_Light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_pages_MainPage_Dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_pages_MainPage_Light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_pages_PageNotFound_Dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_pages_PageNotFound_Light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_pages_ProfilePage_Dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_pages_ProfilePage_Light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_shared_AppLink_Primary_Dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_shared_AppLink_Primary_Light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_shared_AppLink_Secondary_Dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .loki/reference/chrome_iphone7_shared_Button_Clear.png
Binary file modified .loki/reference/chrome_iphone7_shared_Button_Clear_Dark.png
Binary file modified .loki/reference/chrome_iphone7_shared_Button_Disabled.png
Binary file modified .loki/reference/chrome_iphone7_shared_Button_Outlined.png
Binary file modified .loki/reference/chrome_iphone7_shared_Button_Outlined_Dark.png
Binary file modified .loki/reference/chrome_iphone7_shared_Button_Primary.png
Binary file modified .loki/reference/chrome_iphone7_shared_Input_Light.png
Binary file modified .loki/reference/chrome_iphone7_shared_Modal_Dark.png
Binary file modified .loki/reference/chrome_iphone7_shared_Modal_Primary.png
Binary file modified .loki/reference/chrome_iphone7_shared_Text_Dark.png
Binary file modified .loki/reference/chrome_iphone7_shared_Text_Error.png
Binary file modified .loki/reference/chrome_iphone7_shared_Text_Light.png
Binary file modified .loki/reference/chrome_iphone7_widget_PageError_Dark.png
Binary file modified .loki/reference/chrome_iphone7_widget_PageError_Light.png
Binary file modified .loki/reference/chrome_iphone7_widget_Sidebar_Dark.png
Binary file modified .loki/reference/chrome_iphone7_widget_Sidebar_Light.png
Binary file modified .loki/reference/chrome_iphone7_widget_Sidebar_Not_Auth.png
Binary file modified .loki/reference/chrome_laptop_entities_ProfileCard_Dark.png
Binary file modified .loki/reference/chrome_laptop_entities_ProfileCard_Light.png
Binary file modified .loki/reference/chrome_laptop_entities_ProfileCard_With_Error.png
Binary file modified .loki/reference/chrome_laptop_features_LanguageSwitcher_Dark.png
Binary file modified .loki/reference/chrome_laptop_features_LoginModal_Dark.png
Binary file modified .loki/reference/chrome_laptop_features_LoginModal_Error.png
Binary file modified .loki/reference/chrome_laptop_features_LoginModal_Light.png
Binary file modified .loki/reference/chrome_laptop_features_LoginModal_Loading.png
Binary file modified .loki/reference/chrome_laptop_pages_AboutPage_Dark.png
Binary file modified .loki/reference/chrome_laptop_pages_AboutPage_Light.png
Binary file modified .loki/reference/chrome_laptop_pages_MainPage_Dark.png
Binary file modified .loki/reference/chrome_laptop_pages_MainPage_Light.png
Binary file modified .loki/reference/chrome_laptop_pages_PageNotFound_Dark.png
Binary file modified .loki/reference/chrome_laptop_pages_PageNotFound_Light.png
Binary file modified .loki/reference/chrome_laptop_pages_ProfilePage_Dark.png
Binary file modified .loki/reference/chrome_laptop_pages_ProfilePage_Light.png
Binary file modified .loki/reference/chrome_laptop_shared_AppLink_Primary_Dark.png
Binary file modified .loki/reference/chrome_laptop_shared_AppLink_Primary_Light.png
Binary file modified .loki/reference/chrome_laptop_shared_AppLink_Secondary_Dark.png
Binary file modified .loki/reference/chrome_laptop_shared_AppLink_Secondary_Light.png
Binary file modified .loki/reference/chrome_laptop_shared_Button_Clear.png
Binary file modified .loki/reference/chrome_laptop_shared_Button_Clear_Dark.png
Binary file modified .loki/reference/chrome_laptop_shared_Button_Disabled.png
Binary file modified .loki/reference/chrome_laptop_shared_Button_Outlined.png
Binary file modified .loki/reference/chrome_laptop_shared_Button_Outlined_Dark.png
Binary file modified .loki/reference/chrome_laptop_shared_Button_Primary.png
Binary file modified .loki/reference/chrome_laptop_shared_Input_Light.png
Binary file modified .loki/reference/chrome_laptop_shared_Modal_Dark.png
Binary file modified .loki/reference/chrome_laptop_shared_Modal_Primary.png
Binary file modified .loki/reference/chrome_laptop_shared_Text_Dark.png
Binary file modified .loki/reference/chrome_laptop_shared_Text_Error.png
Binary file modified .loki/reference/chrome_laptop_shared_Text_Light.png
Binary file modified .loki/reference/chrome_laptop_widget_PageError_Dark.png
Binary file modified .loki/reference/chrome_laptop_widget_PageError_Light.png
Binary file modified .loki/reference/chrome_laptop_widget_Sidebar_Dark.png
Binary file modified .loki/reference/chrome_laptop_widget_Sidebar_Light.png
Binary file modified .loki/reference/chrome_laptop_widget_Sidebar_Not_Auth.png
4 changes: 4 additions & 0 deletions extractedTranslations/en/articleDetailsPage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"Скопировано!": "",
"Статья не найдена": ""
}
2 changes: 2 additions & 0 deletions extractedTranslations/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"Неверное имя пользователя или пароль": "",
"О сайте": "About",
"Обновить страницу": "Refresh page",
"Ошибка": "",
"Пароль": "Password",
"Скопировано!": "",
"Страна": "",
"Страница не найдена": "Page not found",
"Страница профиля": "",
Expand Down
92 changes: 88 additions & 4 deletions json-server/db.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,95 @@
"id": 3
}
],
"articles": [
{
"id": "1",
"title": "Javascript news",
"subtitle": "Что нового в JS за 2022 год?",
"img": "https://teknotower.com/wp-content/uploads/2020/11/js.png",
"views": 1022,
"createdAt": "26.02.2022",
"type": ["IT"],
"blocks": [
{
"id": "1",
"type": "TEXT",
"title": "Заголовок этого блока",
"paragraphs": [
"Программа, которую по традиции называют «Hello, world!», очень проста. Она выводит куда-либо фразу «Hello, world!», или другую подобную, средствами некоего языка.",
"JavaScript — это язык, программы на котором можно выполнять в разных средах. В нашем случае речь идёт о браузерах и о серверной платформе Node.js. Если до сих пор вы не написали ни строчки кода на JS и читаете этот текст в браузере, на настольном компьютере, это значит, что вы буквально в считанных секундах от своей первой JavaScript-программы.",
"Существуют и другие способы запуска JS-кода в браузере. Так, если говорить об обычном использовании программ на JavaScript, они загружаются в браузер для обеспечения работы веб-страниц. Как правило, код оформляют в виде отдельных файлов с расширением .js, которые подключают к веб-страницам, но программный код можно включать и непосредственно в код страницы. Всё это делается с помощью тега <script>. Когда браузер обнаруживает такой код, он выполняет его. Подробности о теге script можно посмотреть на сайте w3school.com. В частности, рассмотрим пример, демонстрирующий работу с веб-страницей средствами JavaScript, приведённый на этом ресурсе. Этот пример можно запустить и средствами данного ресурса (ищите кнопку Try it Yourself), но мы поступим немного иначе. А именно, создадим в каком-нибудь текстовом редакторе (например — в VS Code или в Notepad++) новый файл, который назовём hello.html, и добавим в него следующий код:"
]
},
{
"id": "4",
"type": "CODE",
"code": "<!DOCTYPE html>\n<html>\n <body>\n <p id=\"hello\"></p>\n\n <script>\n document.getElementById(\"hello\").innerHTML = \"Hello, world!\";\n </script>\n </body>\n</html>;"
},
{
"id": "5",
"type": "TEXT",
"title": "Заголовок этого блока",
"paragraphs": [
"Программа, которую по традиции называют «Hello, world!», очень проста. Она выводит куда-либо фразу «Hello, world!», или другую подобную, средствами некоего языка.",
"Существуют и другие способы запуска JS-кода в браузере. Так, если говорить об обычном использовании программ на JavaScript, они загружаются в браузер для обеспечения работы веб-страниц. Как правило, код оформляют в виде отдельных файлов с расширением .js, которые подключают к веб-страницам, но программный код можно включать и непосредственно в код страницы. Всё это делается с помощью тега <script>. Когда браузер обнаруживает такой код, он выполняет его. Подробности о теге script можно посмотреть на сайте w3school.com. В частности, рассмотрим пример, демонстрирующий работу с веб-страницей средствами JavaScript, приведённый на этом ресурсе. Этот пример можно запустить и средствами данного ресурса (ищите кнопку Try it Yourself), но мы поступим немного иначе. А именно, создадим в каком-нибудь текстовом редакторе (например — в VS Code или в Notepad++) новый файл, который назовём hello.html, и добавим в него следующий код:"
]
},
{
"id": "2",
"type": "IMAGE",
"src": "https://hsto.org/r/w1560/getpro/habr/post_images/d56/a02/ffc/d56a02ffc62949b42904ca00c63d8cc1.png",
"title": "Рисунок 1 - скриншот сайта"
},
{
"id": "3",
"type": "CODE",
"code": "const path = require('path');\n\nconst server = jsonServer.create();\n\nconst router = jsonServer.router(path.resolve(__dirname, 'db.json'));\n\nserver.use(jsonServer.defaults({}));\nserver.use(jsonServer.bodyParser);"
},
{
"id": "7",
"type": "TEXT",
"title": "Заголовок этого блока",
"paragraphs": [
"JavaScript — это язык, программы на котором можно выполнять в разных средах. В нашем случае речь идёт о браузерах и о серверной платформе Node.js. Если до сих пор вы не написали ни строчки кода на JS и читаете этот текст в браузере, на настольном компьютере, это значит, что вы буквально в считанных секундах от своей первой JavaScript-программы.",
"Существуют и другие способы запуска JS-кода в браузере. Так, если говорить об обычном использовании программ на JavaScript, они загружаются в браузер для обеспечения работы веб-страниц. Как правило, код оформляют в виде отдельных файлов с расширением .js, которые подключают к веб-страницам, но программный код можно включать и непосредственно в код страницы. Всё это делается с помощью тега <script>. Когда браузер обнаруживает такой код, он выполняет его. Подробности о теге script можно посмотреть на сайте w3school.com. В частности, рассмотрим пример, демонстрирующий работу с веб-страницей средствами JavaScript, приведённый на этом ресурсе. Этот пример можно запустить и средствами данного ресурса (ищите кнопку Try it Yourself), но мы поступим немного иначе. А именно, создадим в каком-нибудь текстовом редакторе (например — в VS Code или в Notepad++) новый файл, который назовём hello.html, и добавим в него следующий код:"
]
},
{
"id": "8",
"type": "IMAGE",
"src": "https://hsto.org/r/w1560/getpro/habr/post_images/d56/a02/ffc/d56a02ffc62949b42904ca00c63d8cc1.png",
"title": "Рисунок 1 - скриншот сайта"
},
{
"id": "9",
"type": "TEXT",
"title": "Заголовок этого блока",
"paragraphs": [
"JavaScript — это язык, программы на котором можно выполнять в разных средах. В нашем случае речь идёт о браузерах и о серверной платформе Node.js. Если до сих пор вы не написали ни строчки кода на JS и читаете этот текст в браузере, на настольном компьютере, это значит, что вы буквально в считанных секундах от своей первой JavaScript-программы."
]
}
]
}
],
"comments": [
{
"id": 1,
"body": "some comment",
"postId": 1
"id": "1",
"text": "some comment",
"articleId": "1",
"userId": "1"
},
{
"id": "2",
"text": "some comment 2",
"articleId": "1",
"userId": "1"
},
{
"id": "3",
"text": "some comment 3",
"articleId": "1",
"userId": "1"
}
],
"users": [
Expand All @@ -40,4 +124,4 @@
"username": "Karotish",
"avatar": "https://www.computerhope.com/jargon/g/guest-user.png"
}
}
}
4 changes: 4 additions & 0 deletions public/locales/en/articleDetailsPage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"Статья не найдена": "Article not found",
"Скопировано!": "Copied!"
}
4 changes: 3 additions & 1 deletion public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@
"Страна": "Country",
"Валюта": "Currency",
"Авторизация": "Authorization",
"Выйти": "Logout"
"Выйти": "Logout",
"Ошибка": "Error",
"Статьи": "Articles"
}
4 changes: 4 additions & 0 deletions public/locales/ru/articleDetailsPage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"Статья не найдена": "Статья не найдена",
"Скопировано!": "Скопировано!"
}
5 changes: 4 additions & 1 deletion public/locales/ru/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"Страна": "Страна",
"Валюта": "Валюта",
"Авторизация": "Авторизация",
"Выйти": "Выйти"
"Выйти": "Выйти",
"Ошибка": "Ошибка",
"Статьи": "Статьи"

}

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 @@ -8,12 +8,14 @@ import { ProfileSchema } from 'entities/Profile';
import { AxiosInstance } from 'axios';
import { NavigateOptions } from 'react-router';
import { To } from 'history';
import { ArticleDetailsSchema } from 'entities/Article';

export interface StateSchema {
counter: CounterSchema;
user: UserSchema;
loginForm?: LoginSchema;
profile?: ProfileSchema;
articleDetails?: ArticleDetailsSchema;
}

export type StateSchemaKeys = keyof StateSchema;
Expand Down
3 changes: 3 additions & 0 deletions src/app/styles/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ body {
.page-wrapper {
flex-grow: 1;
padding: 2rem;
height: calc(100vh - var(--navbar-height));
overflow-y: auto;
width: 100%;
}
6 changes: 6 additions & 0 deletions src/app/styles/themes/blue.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,10 @@
--bg-color-inverted: #2aa6ac;
--primary-color: #f4f6fb;
--secondary-color: #444;

// skeleton
--skeleton-color: #5faff2;

// text
--text-color: #fff;
}
6 changes: 6 additions & 0 deletions src/app/styles/themes/dark.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,10 @@
--bg-color-inverted: #fbc7db;
--primary-color: #3fd055;
--secondary-color: #6c00d5;

// skeleton
--skeleton-color: #2d2d2d;

// text
--text-color: #fff;
}
7 changes: 7 additions & 0 deletions src/app/styles/themes/light.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,11 @@
--bg-color-inverted: #000;
--primary-color: #149c04;
--secondary-color: #d2d2d8;

// skeleton
--skeleton-color: #fff;
--skeleton-shadow: rgba(0 0 0 / 20%);

// text
--text-color: #000;
}
21 changes: 16 additions & 5 deletions src/app/styles/variables/global.scss
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
@import url("https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap");
@import url("https://fonts.googleapis.com/css2?family=VT323&display=swap");

:root {
--font-family-main: "Press Start 2P", cursive;
--font-family-main: "Press Start 2P", cursive !important;
--font-code: var(--font-size-m) / var(--font-line-m) "VT323", monospace;

// Small size
--font-size-s: 12px;
--font-size-s: 14px;
--font-line-s: 20px;
--font-s: var(--font-size-s) / var(--font-line-s) var(--font-family-main);

// Medium size
--font-size-m: 18px;
--font-line-m: 26px;
--font-line-m: 24px;
--font-m: var(--font-size-m) / var(--font-line-m) var(--font-family-main);

// Large size
--font-size-l: 44px;
--font-line-l: 52px;
--font-size-l: 26px;
--font-line-l: 36px;
--font-l: var(--font-size-l) / var(--font-line-l) var(--font-family-main);

// Extra large size
--font-size-xl: 34px;
--font-line-xl: 46px;
--font-xl: var(--font-size-xl) / var(--font-line-xl) var(--font-family-main);

// Для вычисления размеров элементов
--navbar-height: 50px;
--sidebar-width: 240px;
Expand All @@ -29,4 +36,8 @@
// Цвета
--overlay-color: rgba(0 0 0 / 60%);
--error-color: #f00;

// Код
--code-bg: #fff;
--code-border: 2px solid #000;
}
6 changes: 6 additions & 0 deletions src/entities/Article/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export { ArticleDetails } from './ui/ArticleDetails/ArticleDetails';
export type { Article } from './model/types/article';
export { ArticleDetailsSchema } from './model/types/articleDetailsSchema';
export { ArticleImageBlockComponent } from './ui/ArticleImageBlockComponent/ArticleImageBlockComponent';
export { ArticleTextBlockComponent } from './ui/ArticleTextBlockComponent/ArticleTextBlockComponent';
export { ArticleCodeBlockComponent } from './ui/ArticleCodeBlockComponent/ArticleCodeBlockComponent';
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { StateSchema } from 'app/providers/StoreProvider';
import { getArticleDetailsData, getArticleDetailsError, getArticleDetailsIsLoading } from './articleDetailsSelectors';

describe('getArticleDetailsData.test', () => {
test('should return article data', () => {
const state: DeepPartial<StateSchema> = {
articleDetails: {
data: {
title: 'Title',
blocks: [],
views: 20,
id: '1',
},
},
};
expect(getArticleDetailsData(state as StateSchema)).toEqual({
title: 'Title',
blocks: [],
views: 20,
id: '1',
});
});

test('should return undefined from empty state', () => {
const state: DeepPartial<StateSchema> = {};
expect(getArticleDetailsData(state as StateSchema)).toEqual(undefined);
});
});

describe('getArticleDetailsError.test', () => {
test('should return article error', () => {
const state: DeepPartial<StateSchema> = {
articleDetails: {
error: 'error',
},
};
expect(getArticleDetailsError(state as StateSchema)).toEqual('error');
});

test('should return undefined from empty error', () => {
const state: DeepPartial<StateSchema> = {};
expect(getArticleDetailsError(state as StateSchema)).toEqual(undefined);
});
});

describe('getArticleDetailsIsLoading.test', () => {
test('should return article data', () => {
const state: DeepPartial<StateSchema> = {
articleDetails: {
isLoading: true,
},
};
expect(getArticleDetailsIsLoading(state as StateSchema)).toEqual(true);
});

test('should return undefined from empty state', () => {
const state: DeepPartial<StateSchema> = {};
expect(getArticleDetailsIsLoading(state as StateSchema)).toEqual(undefined);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { StateSchema } from 'app/providers/StoreProvider';

export const getArticleDetailsData = (state: StateSchema) => state.articleDetails?.data;
export const getArticleDetailsIsLoading = (state: StateSchema) => state.articleDetails?.isLoading;
export const getArticleDetailsError = (state: StateSchema) => state.articleDetails?.error;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { ThunkConfig } from 'app/providers/StoreProvider';
import { Article } from '../../types/article';

export const fetchArticleById = createAsyncThunk<
Article,
string,
ThunkConfig<string>
>(
'articleDetails/fetchArticleById',
async (articleId, thunkApi) => {
const { extra, rejectWithValue } = thunkApi;

try {
const response = await extra.api.get<Article>(`/articles/${articleId}`);

if (!response.data) {
throw new Error();
}

return response.data;
} catch (e) {
console.log(e);
return rejectWithValue('error');
}
},
);
38 changes: 38 additions & 0 deletions src/entities/Article/model/slice/articleSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { fetchArticleById } from 'entities/Article/model/services/fetchArticleById/fetchArticleById';
import { Article } from '../types/article';
import { ArticleDetailsSchema } from '../types/articleDetailsSchema';

const initialState: ArticleDetailsSchema = {
isLoading: false,
error: undefined,
data: undefined,
};

export const articleDetailsSlice = createSlice({
name: 'articleDetails',
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchArticleById.pending, (state) => {
state.error = undefined;
state.isLoading = true;
})
.addCase(fetchArticleById.fulfilled, (
state,
action: PayloadAction<Article>,
) => {
state.isLoading = false;
state.data = action.payload;
})
.addCase(fetchArticleById.rejected, (state, action) => {
state.isLoading = false;
state.error = action.payload;
});
},
});

// Action creators are generated for each case reducer function
export const { actions: articleDetailsActions } = articleDetailsSlice;
export const { reducer: articleDetailsReducer } = articleDetailsSlice;
Loading

1 comment on commit a24a471

@vercel
Copy link

@vercel vercel bot commented on a24a471 Jun 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.