import { ArrowRight, CalendarDays, ChevronRight } from "lucide-react"; import { useQuery } from "@tanstack/react-query"; import { Link } from "react-router-dom"; import { contentApi, directoriesApi } from "../shared/api/endpoints"; import { normalizeContentList, toList } from "../shared/api/normalize"; import { queryKeys } from "../shared/api/queryKeys"; import { Badge } from "../shared/ui/Badge"; import { Button } from "../shared/ui/Button"; import { MaterialCard } from "../shared/ui/MaterialCard"; import { ResponsiveImage } from "../shared/ui/ResponsiveImage"; import { EmptyState, ErrorState, Skeleton } from "../shared/ui/States"; function eventDateParts(value = "") { const date = new Date(value); if (!Number.isNaN(date.getTime())) { return [ date.toLocaleDateString("ru-RU", { day: "numeric" }), date.toLocaleDateString("ru-RU", { month: "short" }), ]; } const [day = "", month = ""] = String(value).split(" "); return [day, month]; } export function HomePage() { const { data: contentPayload, isLoading, isError, refetch } = useQuery({ queryKey: queryKeys.content({ page: "home" }), queryFn: () => contentApi.list({ limit: 6 }), }); const { data: eventsPayload } = useQuery({ queryKey: queryKeys.events({ page: "home" }), queryFn: () => directoriesApi.events({ limit: 3 }), }); const { data: categoriesPayload } = useQuery({ queryKey: queryKeys.categories, queryFn: directoriesApi.categories, }); const pageMaterials = normalizeContentList(contentPayload); const pageEvents = toList(eventsPayload); const pageCategories = toList(categoriesPayload); const featured = pageMaterials.find((item) => item.featured) ?? pageMaterials[0]; if (isLoading) { return (
); } if (isError) { return (
); } if (!featured) { return (
); } return ( <>
{featured.category}

{featured.title}

{featured.excerpt}

Новая лента

Последние публикации

Смотреть все →
{pageMaterials.slice(1, 4).map((material) => ( ))}

Календарь

Ближайшие события

Лекции, выставки, защиты проектов и встречи университетского сообщества.

{pageEvents.length === 0 && (
Backend пока не вернул ближайшие события.
)} {pageEvents.map((event) => { const [day, month] = eventDateParts(event.date ?? event.startsAt); return (
{day} {month}

{event.title}

{event.time ?? event.startsAt} · {event.place ?? event.location}

); })}

Навигация по темам

{pageCategories.map((category, index) => { const name = typeof category === "string" ? category : category.name ?? category.title ?? category.label; const value = typeof category === "string" ? category : category.slug ?? category.id ?? name; const description = typeof category === "string" ? "Материалы этой категории доступны в едином каталоге." : category.description; return ( {String(index + 1).padStart(2, "0")}

{name}

{description}

); })}
); }