import Link from "next/link"; import React from "react"; import { allProjects } from "contentlayer/generated"; import { Navigation } from "../components/nav"; import { Card } from "../components/card"; import { Article } from "./article"; import Redis from "ioredis"; // Заменяем @upstash/redis на ioredis import { Eye } from "lucide-react"; // Создаем подключение к локальному Redis const redis = new Redis({ host: process.env.REDIS_HOST || "localhost", port: parseInt(process.env.REDIS_PORT || "6379"), password: process.env.REDIS_PASSWORD, // если есть пароль }); export const revalidate = 60; export default async function ProjectsPage() { const viewsEntries = await redis.mget( ...allProjects.map((p) => `projects:${p.slug}:views`) ); const views = allProjects.reduce((acc, project, index) => { acc[project.slug] = parseInt(viewsEntries[index] as string) || 0; return acc; }, {} as Record); const featured = allProjects.find((project) => project.slug === "cbg")!; const top2 = allProjects.find((project) => project.slug === "blog")!; const top3 = allProjects.find((project) => project.slug === "bimkaspace")!; const sorted = allProjects .filter((p) => p.published) .filter( (project) => project.slug !== featured.slug && project.slug !== top2.slug && project.slug !== top3.slug, ) .sort( (a, b) => new Date(b.date ?? Number.POSITIVE_INFINITY).getTime() - new Date(a.date ?? Number.POSITIVE_INFINITY).getTime(), ); return (

Проекты

Часть проектов делал из академического интереса, часть мои проекты для себя.

{featured.date ? ( ) : ( SOON )}
{" "} {Intl.NumberFormat("en-US", { notation: "compact" }).format( views[featured.slug] ?? 0, )}

{featured.title}

{featured.description}

Подробнее

{[top2, top3].map((project) => (
))}
{sorted .filter((_, i) => i % 3 === 0) .map((project) => (
))}
{sorted .filter((_, i) => i % 3 === 1) .map((project) => (
))}
{sorted .filter((_, i) => i % 3 === 2) .map((project) => (
))}
); }