Add games page

This commit is contained in:
2024-05-12 10:05:49 +04:00
parent a2ea5fc409
commit 275d99bd85
7 changed files with 101 additions and 39 deletions

View File

@@ -1,2 +1,3 @@
NEXT_PUBLIC_BASE_URL=http://127.0.0.1:3000/api
NEXT_PUBLIC_COVER_FULL_URL=http://127.0.0.1:8000/content/images/cover/full_size
NEXT_PUBLIC_COVER_PREVIEW_URL=http://127.0.0.1:8000/content/images/cover/preview

25
src/app/games/page.tsx Normal file
View File

@@ -0,0 +1,25 @@
import { GameService } from "@/entities/game";
import { GameCard } from "@/features/gameCard";
import { Section } from "@/widgets/section";
import { Metadata } from "next";
export const metadata: Metadata = {
title: ".Torrent: Игры",
description:
".Torrent: Игры - каталог .torrent файлов для обмена видеоиграми",
};
export default async function Home() {
const gameCards = await GameService.getGameCards();
return (
<div className="w-full h-full max-w-[var(--app-width)] m-auto overflow-y-auto">
{gameCards && (
<Section>
{gameCards.map((card) => (
<GameCard key={card.id} card={card} />
))}
</Section>
)}
</div>
);
}

View File

@@ -8,7 +8,8 @@ const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: ".Torrent",
description: ".torrent file sharing service",
description:
".Torrent - сервис обмена .torrent файлами видеоигр, фильмов и аудиокниг",
};
export default function RootLayout({
@@ -17,7 +18,7 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
// suppressHydrationWarning only for html for theme support
// suppressHydrationWarning for theme support
<html lang="ru" suppressHydrationWarning>
<body className={inter.className}>
<ThemeProvider enableSystem={false} defaultTheme="light">

View File

@@ -5,9 +5,13 @@ import { Section } from "@/widgets/section";
export default async function Home() {
const gameCards = await GameService.getGameCards();
return (
<div className="w-full max-w-[var(--app-width)] m-auto">
<div className="w-full h-full max-w-[var(--app-width)] m-auto overflow-y-auto">
{gameCards && (
<Section name="Игры">
<Section
name="Игры"
link="/games"
invite_text={'Перейти в раздел "Игры"'}
>
{gameCards.map((card) => (
<GameCard key={card.id} card={card} />
))}

View File

@@ -1,19 +1,26 @@
import { z } from "zod";
export const gameCardSchema = z.object({
export const gameCardSchema = z
.object({
id: z.number(),
title: z.string().min(3),
cover: z
.string()
.optional()
.transform((u) => {
if (!!u) return process.env.NEXT_PUBLIC_COVER_FULL_URL + "/" + u;
}),
cover: z.string().optional(),
description: z.string().optional(),
release_date: z
.string()
.min(1)
.transform((d) => new Date(d)),
})
.transform((card) => {
return {
...card,
cover: card.cover
? process.env.NEXT_PUBLIC_COVER_FULL_URL + "/" + card.cover
: undefined,
cover_preview: card.cover
? process.env.NEXT_PUBLIC_COVER_PREVIEW_URL + "/" + card.cover
: undefined,
};
});
export type GameCardType = z.infer<typeof gameCardSchema>;

View File

@@ -4,9 +4,9 @@ import Image from "next/image";
export const GameCard = ({ card }: { card: GameCardType }) => {
return (
<div className="group/gamecard cursor-pointer">
{!!card.cover && (
{!!card.cover_preview && (
<Image
src={card.cover}
src={card.cover_preview}
className="rounded-lg"
alt=""
width={700}

View File

@@ -1,17 +1,41 @@
"use client";
import Link from "next/link";
import { useRouter } from "next/navigation";
export const Section = ({
name,
invite_text,
link,
children,
}: {
name: string;
name?: string;
invite_text?: string;
link?: string;
children: React.ReactNode;
}) => {
const router = useRouter();
return (
// open section onClick
<section className="w-full p-5 pt-8">
<h2 className="text-4xl pb-2 cursor-pointer w-fit">{name}</h2>
<section className="w-full h-fit p-5 mb-20 pt-8">
{name && (
<h2
className="text-4xl pb-2 cursor-pointer w-fit"
onClick={() => link && router.push(link)}
>
{name}
</h2>
)}
<div className="grid grid-cols-1 tb:grid-cols-2 lp:grid-cols-3 gap-y-10 gap-x-3">
{children}
</div>
{link && invite_text && (
<div className="w-full flex justify-end pt-5">
<Link href={link} className="text-lg">
{invite_text}
</Link>
</div>
)}
</section>
);
};