Skip to content

Commit

Permalink
day 58
Browse files Browse the repository at this point in the history
  • Loading branch information
famovkin committed Mar 20, 2024
1 parent 1ca4ebc commit 4f73e74
Show file tree
Hide file tree
Showing 39 changed files with 614 additions and 154 deletions.
1 change: 1 addition & 0 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"Произошла непредвиденная ошибка": "Unexpected error",
"Сломать": "Broke",
"Главная страница": "Main page",
"Статьи": "Articles",
"О сайте": "About us",
"Короткий язык": "En",
"Введите логин": "Username",
Expand Down
1 change: 1 addition & 0 deletions public/locales/ru/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"Произошла непредвиденная ошибка": "Произошла непредвиденная ошибка",
"Сломать": "Сломать",
"Главная страница": "Главная страница",
"Статьи": "Статьи",
"О сайте": "О нас",
"Короткий язык": "Ру",
"Введите логин": "Логин",
Expand Down
1 change: 1 addition & 0 deletions src/app/styles/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ body {
padding: 20px 20px 20px 45px;
height: calc(100vh - var(--navbar-height));
overflow-y: auto;
width: 100%;
}
3 changes: 3 additions & 0 deletions src/app/styles/themes/dark.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@
// skeleton
--skeleton-color: #1515ad;
--skeleton-shadow: #2b2be8;

// code
--code-bg: #1212a1;
}
3 changes: 3 additions & 0 deletions src/app/styles/themes/light.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@
// skeleton
--skeleton-color: #fff;
--skeleton-shadow: rgba(0 0 0 / 20%);

// code
--code-bg: #fff;
}
3 changes: 3 additions & 0 deletions src/app/styles/themes/yellow.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@
// skeleton
--skeleton-color: #fff;
--skeleton-shadow: rgba(0 0 0 / 20%);

// code
--code-bg: #d7b11b;
}
56 changes: 56 additions & 0 deletions src/entities/Article/model/selectors/articleDetails.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { StateSchema } from 'app/providers/StoreProvider';
import {
getArticleDetailsData,
getArticleDetailsIsLoading,
getArticleDetailsError,
} from './articleDetails';

describe('getArticleDetailsData.test', () => {
test('should return data', () => {
const dataInit = {
id: '1',
title: 'Javascript news',
};

const state: DeepPartial<StateSchema> = {
articleDetails: {
data: dataInit,
},
};
expect(getArticleDetailsData(state as StateSchema)).toEqual(dataInit);
});
test('should work with empty data', () => {
const state: DeepPartial<StateSchema> = {};
expect(getArticleDetailsData(state as StateSchema)).toEqual(undefined);
});
});

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

describe('getArticleDetailsError.error', () => {
test('should return isLoading state', () => {
const state: DeepPartial<StateSchema> = {
articleDetails: {
error: 'error',
},
};
expect(getArticleDetailsError(state as StateSchema)).toEqual('error');
});
test('should work with empty state error', () => {
const state: DeepPartial<StateSchema> = {};
expect(getArticleDetailsError(state as StateSchema)).toEqual(undefined);
});
});
3 changes: 2 additions & 1 deletion src/entities/Article/model/selectors/articleDetails.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { StateSchema } from 'app/providers/StoreProvider';

export const getArticleDetailsData = (state: StateSchema) => state.articleDetails?.data;
export const getArticleDetailsIsLoading = (state: StateSchema) => state.articleDetails?.isLoading;
export const getArticleDetailsIsLoading = (state: StateSchema) => state.articleDetails?.isLoading
|| false;
export const getArticleDetailsError = (state: StateSchema) => state.articleDetails?.error;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.ArticleCodeBlockComponent {
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { memo } from 'react';
import { classNames } from 'shared/lib/classNames/classNames';
import { useTranslation } from 'react-i18next';

import { Code } from 'shared/ui/Code/Code';
import { ArticleCodeBlock } from '../../model/types/article';

import cls from './ArticleCodeBlockComponent.module.scss';

interface ArticleCodeBlockComponentProps {
className?: string;
block: ArticleCodeBlock;
}

export const ArticleCodeBlockComponent = memo(
(props: ArticleCodeBlockComponentProps) => {
const { className, block } = props;
const { t } = useTranslation();

return (
<div
className={classNames(cls.ArticleCodeBlockComponent, {}, [className])}
>
<Code text={block.code} />
</div>
);
},
);
19 changes: 19 additions & 0 deletions src/entities/Article/ui/ArticleDetails/ArticleDetails.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,22 @@
.skeleton {
margin-top: 15px;
}

.avatarWrapper {
display: flex;
justify-content: center;
align-items: center;
}

.articleInfo {
display: flex;
align-items: center;
}

.icon {
margin-right: 8px;
}

.block {
margin-top: 16px;
}
115 changes: 113 additions & 2 deletions src/entities/Article/ui/ArticleDetails/ArticleDetails.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,134 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Theme } from 'app/providers/ThemeProvider';
import { Article } from 'entities/Article';
import {
ArticleBlockType,
ArticleType,
} from 'entities/Article/model/types/article';
import { StoreDecorator } from 'shared/config/storybook/StoreDecorator/StoreDecorator';
import { ThemeDecorator } from 'shared/config/storybook/ThemeDecorator/ThemeDecorator';
import { ArticleDetails } from './ArticleDetails';

const meta: Meta<typeof ArticleDetails> = {
title: 'category/ArticleDetails',
title: 'entities/ArticleDetails',
component: ArticleDetails,
args: {},
};

const article: Article = {
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: [ArticleType.IT],
blocks: [
{
id: '1',
type: ArticleBlockType.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: ArticleBlockType.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: ArticleBlockType.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: ArticleBlockType.IMAGE,
src: 'https://hsto.org/r/w1560/getpro/habr/post_images/d56/a02/ffc/d56a02ffc62949b42904ca00c63d8cc1.png',
title: 'Рисунок 1 - скриншот сайта',
},
{
id: '3',
type: ArticleBlockType.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: ArticleBlockType.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: ArticleBlockType.IMAGE,
src: 'https://hsto.org/r/w1560/getpro/habr/post_images/d56/a02/ffc/d56a02ffc62949b42904ca00c63d8cc1.png',
title: 'Рисунок 1 - скриншот сайта',
},
{
id: '9',
type: ArticleBlockType.TEXT,
title: 'Заголовок этого блока',
paragraphs: [
'JavaScript — это язык, программы на котором можно выполнять в разных средах. В нашем случае речь идёт о браузерах и о серверной платформе Node.js. Если до сих пор вы не написали ни строчки кода на JS и читаете этот текст в браузере, на настольном компьютере, это значит, что вы буквально в считанных секундах от своей первой JavaScript-программы.',
],
},
],
};

export default meta;
type Story = StoryObj<typeof ArticleDetails>;

export const Primary: Story = {
args: {},
};
Primary.decorators = [
StoreDecorator({
articleDetails: {
data: article,
},
}),
];

export const Dark: Story = {
args: {},
};
Dark.decorators = [ThemeDecorator(Theme.DARK)];
Dark.decorators = [
ThemeDecorator(Theme.DARK),
StoreDecorator({
articleDetails: {
data: article,
},
}),
];

export const Loading: Story = {
args: {},
};
Loading.decorators = [
StoreDecorator({
articleDetails: {
isLoading: true,
},
}),
];

export const IsLoading: Story = {
args: {},
};
IsLoading.decorators = [
StoreDecorator({
articleDetails: {
error: 'Error',
},
}),
];
Loading

0 comments on commit 4f73e74

Please sign in to comment.