Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ class APIService {
this.config = config;
this.defaultHeaders = {
'Content-Type': 'application/json',
'Accept-Language': services.i18n.getLang() // устанавливаем по умолчанию значение языка из i18n
};

this.services.i18n.subscribe((lang) => { // подписка на изменения языка
this.defaultHeaders['Accept-Language'] = lang;
});
}

/**
Expand Down
11 changes: 7 additions & 4 deletions src/app/article/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { useDispatch, useSelector } from 'react-redux';
import shallowequal from 'shallowequal';
import articleActions from '../../store-redux/article/actions';
import HeadLayout from '../../components/head-layout';
import Comments from '../../containers/comments';
import commentsActions from '../../store-redux/comments/actions';

function Article() {
const store = useStore();
Expand All @@ -23,10 +25,12 @@ function Article() {

const params = useParams();

const { t, lang } = useTranslate();

useInit(() => {
//store.actions.article.load(params.id);
dispatch(articleActions.load(params.id));
}, [params.id]);
dispatch(commentsActions.load(params.id));
}, [params.id, lang]);

const select = useSelector(
state => ({
Expand All @@ -36,8 +40,6 @@ function Article() {
shallowequal,
); // Нужно указать функцию для сравнения свойства объекта, так как хуком вернули объект

const { t } = useTranslate();

const callbacks = {
// Добавление в корзину
addToBasket: useCallback(_id => store.actions.basket.addToBasket(_id), [store]),
Expand All @@ -55,6 +57,7 @@ function Article() {
<Navigation />
<Spinner active={select.waiting}>
<ArticleCard article={select.article} onAdd={callbacks.addToBasket} t={t} />
<Comments />
</Spinner>
</PageLayout>
</>
Expand Down
5 changes: 2 additions & 3 deletions src/app/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,16 @@ import HeadLayout from '../../components/head-layout';

function Main() {
const store = useStore();
const { t, lang } = useTranslate();

useInit(
async () => {
await Promise.all([store.actions.catalog.initParams(), store.actions.categories.load()]);
},
[],
[lang], // обновляем данные с сервера, с учетом нового языка
true,
);

const { t } = useTranslate();

return (
<>
<HeadLayout>
Expand Down
5 changes: 2 additions & 3 deletions src/app/profile/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,17 @@ import HeadLayout from '../../components/head-layout';

function Profile() {
const store = useStore();
const { t, lang } = useTranslate();

useInit(() => {
store.actions.profile.load();
}, []);
}, [lang]);

const select = useSelector(state => ({
profile: state.profile.data,
waiting: state.profile.waiting,
}));

const { t } = useTranslate();

return (
<>
<HeadLayout>
Expand Down
40 changes: 40 additions & 0 deletions src/components/add-comment/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { memo, useState } from 'react';
import './style.css';
import Button from '../button';
import { cn as bem } from '@bem-react/classname';
import PropTypes from 'prop-types';

function AddComment(props) {
const { t = text => text, addComment = () => {}, cancelComment = () => {}, id } = props;
const [text, setText] = useState('');

const handleChange = event => {
setText(event.target.value);
};

const onAddComment = () => {
addComment(id, text);
};

const cn = bem('AddComment');

return (
<div className={cn()}>
<div className={cn('text__bold')}>{t('Новый комментарий')}</div>
<textarea rows={4} value={text} onChange={handleChange} className={cn('textarea')} />
<div className={cn('actions')}>
<Button title={t('Отправить')} style={'primary'} onClick={onAddComment} disabled={!text.trim()} />
<Button title={t('Отмена')} style={'outline'} onClick={cancelComment} />
</div>
</div>
);
}

AddComment.propTypes = {
t: PropTypes.func,
addComment: PropTypes.func,
cancelComment: PropTypes.func,
id: PropTypes.string,
};

export default memo(AddComment);
36 changes: 36 additions & 0 deletions src/components/add-comment/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.AddComment {
display: flex;
flex-direction: column;
gap: 16px;
padding: 8px 0 24px 0;
}

.AddComment-title {
font-family: var(--second-font-family), sans-serif;
font-weight: 700;
font-size: 24px;
line-height: 133%;
}

.AddComment-text__bold {
font-weight: 700;
font-size: 16px;
line-height: 137%;
}

.AddComment-textarea {
resize: none;
width: 100%;
padding: 8px 12px;
font-weight: 400;
font-size: 14px;
line-height: 130%;
border: 1px solid var(--filter-border);
border-radius: 4px;
}

.AddComment-actions {
display: flex;
gap: 16px;
}

3 changes: 2 additions & 1 deletion src/components/article-card/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
display: flex;
flex-direction: column;
gap: 24px;
padding-block: 24px;
padding-top: 24px;
padding-bottom: 32px;
}

.ArticleCard-prop-wrapper {
Expand Down
4 changes: 2 additions & 2 deletions src/components/button/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import PropTypes from 'prop-types';
import { cn as bem } from '@bem-react/classname';
import './style.css';

function Button({ onClick = () => {}, title, style, type = 'button' }) {
function Button({ onClick = () => {}, title, style, type = 'button', disabled }) {
const cn = bem('Button');

return (
<div className={cn()}>
<button type={type} className={cn({ style })} onClick={() => onClick()}>{title}</button>
<button type={type} className={cn({ style })} onClick={() => onClick()} disabled={disabled}>{title}</button>
</div>
);
}
Expand Down
7 changes: 7 additions & 0 deletions src/components/button/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
border-color: var(--primary);
color: var(--primary);
}

&:disabled {
background-color: var(--close);
color: var(--second-text);
cursor: auto;
}
}

.Button_style_delete {
Expand Down Expand Up @@ -39,3 +45,4 @@
color: var(--primary);
}
}

68 changes: 68 additions & 0 deletions src/components/comments-content/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { memo } from 'react';
import Spinner from '../../components/spinner';
import './style.css';
import { cn as bem } from '@bem-react/classname';
import AddComment from '../add-comment';
import CommentsListTree from '../comments-list-tree';
import SignInNotice from '../sign-in-notice';
import PropTypes from 'prop-types';

function CommentsContent(props) {
const {
exists,
waiting,
comments,
activeNodeId,
id,
addComment,
cancelComment,
setNodeId,
count,
pathname,
userId,
t = text => text,
} = props;

const cn = bem('CommentsContent');

return (
<Spinner active={waiting}>
<div className={cn()}>
<div className={cn('title')}>Комментарии ({count})</div>
<CommentsListTree
data={comments}
setNodeId={setNodeId}
addComment={addComment}
cancelComment={cancelComment}
activeNodeId={activeNodeId}
userId={userId}
exists={exists}
pathname={pathname}
t={t}
/>
</div>
{activeNodeId === 'main' && (exists ? (
<AddComment id={id} cancelComment={cancelComment} addComment={addComment} />
) : (
<SignInNotice pathname={pathname} />
))}
</Spinner>
);
}

CommentsContent.propTypes = {
exists: PropTypes.bool,
waiting: PropTypes.bool,
comment: PropTypes.arrayOf(),
addComment: PropTypes.func,
cancelComment: PropTypes.func,
setNodeId: PropTypes.func,
activeNodeId: PropTypes.string,
count: PropTypes.number,
id: PropTypes.string,
userId: PropTypes.string,
pathname: PropTypes.string,
t: PropTypes.func,
};

export default memo(CommentsContent);
23 changes: 23 additions & 0 deletions src/components/comments-content/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.CommentsContent {
display: flex;
flex-direction: column;
gap: 16px;
}

.CommentsContent-title {
font-family: var(--second-font-family), sans-serif;
font-weight: 700;
font-size: 24px;
line-height: 133%;
padding: 8px 0;
}

.CommentsContent-text {
font-weight: 400;
font-size: 16px;
line-height: 137%;
}

.CommentsContent-link {
color: var(--primary);
}
51 changes: 51 additions & 0 deletions src/components/comments-list-tree/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { memo } from 'react';
import CommentsNode from '../comments-node';
import PropTypes from 'prop-types';

function CommentsListTree(props) {
const {
t = text => text,
data = [],
addComment,
activeNodeId,
setNodeId,
userId,
exists,
pathname,
cancelComment,
} = props;

return (
<>
{data &&
data[0]?.children.map(item => (
<CommentsNode
key={item._id}
node={item}
addComment={addComment}
cancelComment={cancelComment}
setNodeId={setNodeId}
activeNodeId={activeNodeId}
t={t}
userId={userId}
exists={exists}
pathname={pathname}
/>
))}
</>
);
}

CommentsListTree.propTypes = {
exists: PropTypes.bool,
addComment: PropTypes.func,
cancelComment: PropTypes.func,
setNodeId: PropTypes.func,
data: PropTypes.arrayOf(),
activeNodeId: PropTypes.string,
userId: PropTypes.string,
pathname: PropTypes.string,
t: PropTypes.func,
};

export default memo(CommentsListTree);
Loading