update articles slice
This commit is contained in:
@@ -3,8 +3,7 @@ import { useAppDispatch, useAppSelector } from '../../../../redux/hooks';
|
||||
import { setMenuActiveProfilePage } from '../../../../redux/slices/store';
|
||||
import { cn } from '../../../../lib/cn';
|
||||
import { ChevroneDown, Edit } from '../../../../assets/icons/groups';
|
||||
import { fetchArticles } from '../../../../redux/slices/articles';
|
||||
|
||||
import { fetchMyArticles } from '../../../../redux/slices/articles';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export interface ArticleItemProps {
|
||||
@@ -13,21 +12,21 @@ export interface ArticleItemProps {
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
const ArticleItem: React.FC<ArticleItemProps> = ({ id, name, tags }) => {
|
||||
const ArticleItem: FC<ArticleItemProps> = ({ id, name, tags }) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'w-full relative rounded-[10px] text-liquid-white mb-[20px]',
|
||||
// type == "first" ? "bg-liquid-lighter" : "bg-liquid-background",
|
||||
'gap-[20px] px-[20px] py-[10px] box-border ',
|
||||
'gap-[20px] px-[20px] py-[10px] box-border',
|
||||
'border-b-[1px] border-b-liquid-lighter cursor-pointer hover:bg-liquid-lighter transition-all duration-300',
|
||||
)}
|
||||
onClick={() => {
|
||||
navigate(`/article/${id}?back=/home/account/articles`);
|
||||
}}
|
||||
onClick={() =>
|
||||
navigate(`/article/${id}?back=/home/account/articles`)
|
||||
}
|
||||
>
|
||||
<div className="h-[23px] flex ">
|
||||
<div className="h-[23px] flex">
|
||||
<div className="text-[18px] font-bold w-[60px] mr-[20px] flex items-center">
|
||||
#{id}
|
||||
</div>
|
||||
@@ -35,13 +34,14 @@ const ArticleItem: React.FC<ArticleItemProps> = ({ id, name, tags }) => {
|
||||
{name}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-[14px] flex text-liquid-light gap-[10px] mt-[10px]">
|
||||
{tags.map((v, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={cn(
|
||||
'rounded-full px-[16px] py-[8px] bg-liquid-lighter',
|
||||
v == 'Sertificated' && 'text-liquid-green',
|
||||
v === 'Sertificated' && 'text-liquid-green',
|
||||
)}
|
||||
>
|
||||
{v}
|
||||
@@ -50,8 +50,9 @@ const ArticleItem: React.FC<ArticleItemProps> = ({ id, name, tags }) => {
|
||||
</div>
|
||||
|
||||
<img
|
||||
className=" absolute right-[10px] top-[10px] h-[24px] w-[24px] hover:bg-liquid-light rounded-[5px] transition-all duration-300"
|
||||
className="absolute right-[10px] top-[10px] h-[24px] w-[24px] hover:bg-liquid-light rounded-[5px] transition-all duration-300"
|
||||
src={Edit}
|
||||
alt="Редактировать"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
navigate(
|
||||
@@ -69,49 +70,79 @@ interface ArticlesBlockProps {
|
||||
|
||||
const ArticlesBlock: FC<ArticlesBlockProps> = ({ className = '' }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const articles = useAppSelector((state) => state.articles.articles);
|
||||
const [active, setActive] = useState<boolean>(true);
|
||||
|
||||
// ✅ Берём только "мои статьи"
|
||||
const articles = useAppSelector(
|
||||
(state) => state.articles.fetchMyArticles.articles,
|
||||
);
|
||||
const status = useAppSelector(
|
||||
(state) => state.articles.fetchMyArticles.status,
|
||||
);
|
||||
const error = useAppSelector(
|
||||
(state) => state.articles.fetchMyArticles.error,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setMenuActiveProfilePage('articles'));
|
||||
dispatch(fetchArticles({}));
|
||||
}, []);
|
||||
dispatch(fetchMyArticles());
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<div className="h-full w-full relative p-[20px]">
|
||||
<div
|
||||
className={cn(
|
||||
' border-b-[1px] border-b-liquid-lighter rounded-[10px]',
|
||||
'border-b-[1px] border-b-liquid-lighter rounded-[10px]',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{/* Заголовок */}
|
||||
<div
|
||||
className={cn(
|
||||
' h-[40px] text-[24px] font-bold flex gap-[10px] border-b-[1px] border-b-transparent items-center cursor-pointer transition-all duration-300',
|
||||
active && ' border-b-liquid-lighter',
|
||||
'h-[40px] text-[24px] font-bold flex gap-[10px] border-b-[1px] border-b-transparent items-center cursor-pointer transition-all duration-300',
|
||||
active && 'border-b-liquid-lighter',
|
||||
)}
|
||||
onClick={() => {
|
||||
setActive(!active);
|
||||
}}
|
||||
onClick={() => setActive(!active)}
|
||||
>
|
||||
<span>Мои статьи</span>
|
||||
<img
|
||||
src={ChevroneDown}
|
||||
alt="toggle"
|
||||
className={cn(
|
||||
'transition-all duration-300',
|
||||
active && 'rotate-180',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Контент */}
|
||||
<div
|
||||
className={cn(
|
||||
' grid grid-flow-row grid-rows-[0fr] opacity-0 transition-all duration-300',
|
||||
'grid grid-flow-row grid-rows-[0fr] opacity-0 transition-all duration-300',
|
||||
active && 'grid-rows-[1fr] opacity-100',
|
||||
)}
|
||||
>
|
||||
<div className="overflow-hidden">
|
||||
<div className="grid gap-[20px] pt-[20px] pb-[20px] box-border">
|
||||
{articles.map((v, i) => (
|
||||
<ArticleItem key={i} {...v} />
|
||||
{status === 'loading' && (
|
||||
<div className="text-liquid-light">
|
||||
Загрузка статей...
|
||||
</div>
|
||||
)}
|
||||
{status === 'failed' && (
|
||||
<div className="text-liquid-red">
|
||||
Ошибка:{' '}
|
||||
{error || 'Не удалось загрузить статьи'}
|
||||
</div>
|
||||
)}
|
||||
{status === 'successful' &&
|
||||
articles.length === 0 && (
|
||||
<div className="text-liquid-light">
|
||||
У вас пока нет статей
|
||||
</div>
|
||||
)}
|
||||
{articles.map((v) => (
|
||||
<ArticleItem key={v.id} {...v} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user