add contests

This commit is contained in:
Виталий Лавшонок
2025-12-05 23:42:18 +03:00
parent 358c7def78
commit fd34761745
36 changed files with 2518 additions and 710 deletions

View File

@@ -3,16 +3,25 @@ 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 { fetchMyArticles } from '../../../../redux/slices/articles';
import { useNavigate } from 'react-router-dom';
export interface ArticleItemProps {
id: number;
name: string;
tags: string[];
createdAt: string;
}
const ArticleItem: FC<ArticleItemProps> = ({ id, name, tags }) => {
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 (
@@ -35,18 +44,8 @@ const ArticleItem: FC<ArticleItemProps> = ({ id, name, tags }) => {
</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 className="text-[18px] flex text-liquid-light gap-[10px] mt-[20px]">
{`Опубликована ${formatDate(createdAt)}`}
</div>
<img
@@ -72,20 +71,12 @@ const ArticlesBlock: FC<ArticlesBlockProps> = ({ className = '' }) => {
const dispatch = useAppDispatch();
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,
const { data: articleData } = useAppSelector(
(state) => state.profile.articles,
);
useEffect(() => {
dispatch(setMenuActiveProfilePage('articles'));
dispatch(fetchMyArticles());
}, [dispatch]);
return (
@@ -130,19 +121,21 @@ const ArticlesBlock: FC<ArticlesBlockProps> = ({ className = '' }) => {
</div>
)}
{status === 'failed' && (
<div className="text-liquid-red">
Ошибка:{' '}
{error || 'Не удалось загрузить статьи'}
</div>
<div className="text-liquid-red">Ошибка: </div>
)}
{status === 'successful' &&
articles.length === 0 && (
articleData?.articles.items.length === 0 && (
<div className="text-liquid-light">
У вас пока нет статей
</div>
)}
{articles.map((v) => (
<ArticleItem key={v.id} {...v} />
{articleData?.articles.items.map((v, i) => (
<ArticleItem
key={i}
id={v.articleId}
name={v.title}
createdAt={v.createdAt}
/>
))}
</div>
</div>