125 lines
4.5 KiB
TypeScript
125 lines
4.5 KiB
TypeScript
import { FC, useEffect, useState } from 'react';
|
||
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 { useNavigate } from 'react-router-dom';
|
||
|
||
export interface ArticleItemProps {
|
||
id: number;
|
||
name: string;
|
||
tags: string[];
|
||
}
|
||
|
||
const ArticleItem: React.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 ',
|
||
'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`);
|
||
}}
|
||
>
|
||
<div className="h-[23px] flex ">
|
||
<div className="text-[18px] font-bold w-[60px] mr-[20px] flex items-center">
|
||
#{id}
|
||
</div>
|
||
<div className="text-[18px] font-bold flex items-center">
|
||
{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}
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
<img
|
||
className=" absolute right-[10px] top-[10px] h-[24px] w-[24px] hover:bg-liquid-light rounded-[5px] transition-all duration-300"
|
||
src={Edit}
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
navigate(
|
||
`/article/create?back=/home/account/articles&articleId=${id}`,
|
||
);
|
||
}}
|
||
/>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
interface ArticlesBlockProps {
|
||
className?: string;
|
||
}
|
||
|
||
const ArticlesBlock: FC<ArticlesBlockProps> = ({ className = '' }) => {
|
||
const dispatch = useAppDispatch();
|
||
const articles = useAppSelector((state) => state.articles.articles);
|
||
const [active, setActive] = useState<boolean>(true);
|
||
|
||
useEffect(() => {
|
||
dispatch(setMenuActiveProfilePage('articles'));
|
||
dispatch(fetchArticles({}));
|
||
}, []);
|
||
return (
|
||
<div className="h-full w-full relative p-[20px]">
|
||
<div
|
||
className={cn(
|
||
' 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',
|
||
)}
|
||
onClick={() => {
|
||
setActive(!active);
|
||
}}
|
||
>
|
||
<span>Мои статьи</span>
|
||
<img
|
||
src={ChevroneDown}
|
||
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',
|
||
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} />
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default ArticlesBlock;
|