149 lines
5.5 KiB
TypeScript
149 lines
5.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 { useNavigate } from 'react-router-dom';
|
||
|
||
export interface ArticleItemProps {
|
||
id: number;
|
||
name: string;
|
||
createdAt: string;
|
||
}
|
||
|
||
export const formatDate = (isoDate?: string): string => {
|
||
if (!isoDate) return '';
|
||
const date = new Date(isoDate);
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const year = date.getFullYear();
|
||
|
||
return `${day}.${month}.${year}`;
|
||
};
|
||
|
||
const ArticleItem: FC<ArticleItemProps> = ({ id, name, createdAt }) => {
|
||
const navigate = useNavigate();
|
||
|
||
return (
|
||
<div
|
||
className={cn(
|
||
'w-full relative rounded-[10px] text-liquid-white mb-[20px]',
|
||
'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-[18px] flex text-liquid-light gap-[10px] mt-[20px]">
|
||
{`Опубликована ${formatDate(createdAt)}`}
|
||
</div>
|
||
|
||
<img
|
||
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(
|
||
`/article/create?back=/home/account/articles&articleId=${id}`,
|
||
);
|
||
}}
|
||
/>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
interface ArticlesBlockProps {
|
||
className?: string;
|
||
}
|
||
|
||
const ArticlesBlock: FC<ArticlesBlockProps> = ({ className = '' }) => {
|
||
const dispatch = useAppDispatch();
|
||
const [active, setActive] = useState<boolean>(true);
|
||
|
||
const { data: articleData } = useAppSelector(
|
||
(state) => state.profile.articles,
|
||
);
|
||
|
||
useEffect(() => {
|
||
dispatch(setMenuActiveProfilePage('articles'));
|
||
}, [dispatch]);
|
||
|
||
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}
|
||
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',
|
||
active && 'grid-rows-[1fr] opacity-100',
|
||
)}
|
||
>
|
||
<div className="overflow-hidden">
|
||
<div className="grid gap-[20px] pt-[20px] pb-[20px] box-border">
|
||
{status === 'loading' && (
|
||
<div className="text-liquid-light">
|
||
Загрузка статей...
|
||
</div>
|
||
)}
|
||
{status === 'failed' && (
|
||
<div className="text-liquid-red">Ошибка: </div>
|
||
)}
|
||
{status === 'successful' &&
|
||
articleData?.articles.items.length === 0 && (
|
||
<div className="text-liquid-light">
|
||
У вас пока нет статей
|
||
</div>
|
||
)}
|
||
{articleData?.articles.items.map((v, i) => (
|
||
<ArticleItem
|
||
key={i}
|
||
id={v.articleId}
|
||
name={v.title}
|
||
createdAt={v.createdAt}
|
||
/>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default ArticlesBlock;
|