Init game page

This commit is contained in:
2024-05-12 13:12:13 +04:00
parent 275d99bd85
commit 15247adfa3
9 changed files with 88 additions and 12 deletions

View File

@@ -0,0 +1,48 @@
import { GameService } from "@/entities/game";
import { GameCard } from "@/features/gameCard";
import { Section } from "@/widgets/section";
import Image from "next/image";
export default async function Games({
params: { game_id },
}: {
params: { game_id: number };
}) {
const gameCards = await GameService.getGameCards();
const game = await GameService.getGame(game_id);
return (
<>
{game && (
<div className="p-4 flex flex-col lp:flex-row">
{game.cover && (
<Image
src={game.cover}
className="rounded-lg w-[60%] aspect-video object-cover"
alt=""
width={1280}
height={720}
/>
)}
<div className="pt-2 max-w-[40%]">
<h1 className="text-4xl">{game.title}</h1>
<p className="text-md text-justify text-fg4 pt-2">
{game.description}
</p>
</div>
</div>
)}
{gameCards && (
<Section
name="Другие популярные игры"
link="/games"
invite_text={'Перейти в раздел "Игры"'}
>
{gameCards.map((card) => (
<GameCard key={card.id} card={card} />
))}
</Section>
)}
</>
);
}

View File

@@ -9,10 +9,10 @@ export const metadata: Metadata = {
".Torrent: Игры - каталог .torrent файлов для обмена видеоиграми", ".Torrent: Игры - каталог .torrent файлов для обмена видеоиграми",
}; };
export default async function Home() { export default async function Games() {
const gameCards = await GameService.getGameCards(); const gameCards = await GameService.getGameCards();
return ( return (
<div className="w-full h-full max-w-[var(--app-width)] m-auto overflow-y-auto"> <>
{gameCards && ( {gameCards && (
<Section> <Section>
{gameCards.map((card) => ( {gameCards.map((card) => (
@@ -20,6 +20,6 @@ export default async function Home() {
))} ))}
</Section> </Section>
)} )}
</div> </>
); );
} }

View File

@@ -23,7 +23,9 @@ export default function RootLayout({
<body className={inter.className}> <body className={inter.className}>
<ThemeProvider enableSystem={false} defaultTheme="light"> <ThemeProvider enableSystem={false} defaultTheme="light">
<Header /> <Header />
{children} <div className="w-full h-full max-w-[var(--app-width)] m-auto overflow-y-auto">
{children}
</div>
</ThemeProvider> </ThemeProvider>
</body> </body>
</html> </html>

View File

@@ -5,7 +5,7 @@ import { Section } from "@/widgets/section";
export default async function Home() { export default async function Home() {
const gameCards = await GameService.getGameCards(); const gameCards = await GameService.getGameCards();
return ( return (
<div className="w-full h-full max-w-[var(--app-width)] m-auto overflow-y-auto"> <>
{gameCards && ( {gameCards && (
<Section <Section
name="Игры" name="Игры"
@@ -17,6 +17,6 @@ export default async function Home() {
))} ))}
</Section> </Section>
)} )}
</div> </>
); );
} }

View File

@@ -1,5 +1,6 @@
import { HTTPService } from "@/shared/http/httpService"; import { HTTPService } from "@/shared/http/httpService";
import { gameCardsSchema, GameCardType } from "./schemas/gameCard"; import { gameCardsSchema, GameCardType } from "./schemas/gameCard";
import { gameSchema, GameType } from "./schemas/game";
export abstract class GameService { export abstract class GameService {
public static async getGameCards() { public static async getGameCards() {
@@ -8,4 +9,7 @@ export abstract class GameService {
gameCardsSchema gameCardsSchema
); );
} }
public static async getGame(id: number) {
return await HTTPService.get<GameType>(`/games/${id}`, gameSchema);
}
} }

View File

@@ -1,8 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { gameCardSchema } from "./gameCard"; import { gameCardSchema } from "./gameCard";
export const gameSchema = z.union([ export const gameSchema = gameCardSchema.and(
gameCardSchema,
z.object({ z.object({
torrent_file: z.string().min(1), torrent_file: z.string().min(1),
language: z.string().optional(), language: z.string().optional(),
@@ -17,8 +16,8 @@ export const gameSchema = z.union([
.string() .string()
.min(1) .min(1)
.transform((d) => new Date(d)), .transform((d) => new Date(d)),
}), })
]); );
export type GameType = z.infer<typeof gameSchema>; export type GameType = z.infer<typeof gameSchema>;
export const isGame = (a: any): a is GameType => { export const isGame = (a: any): a is GameType => {

View File

@@ -1,9 +1,10 @@
import { GameCardType } from "@/entities/game"; import { GameCardType } from "@/entities/game";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link";
export const GameCard = ({ card }: { card: GameCardType }) => { export const GameCard = ({ card }: { card: GameCardType }) => {
return ( return (
<div className="group/gamecard cursor-pointer"> <Link className="group/gamecard cursor-pointer" href={"/games/" + card.id}>
{!!card.cover_preview && ( {!!card.cover_preview && (
<Image <Image
src={card.cover_preview} src={card.cover_preview}
@@ -26,6 +27,6 @@ export const GameCard = ({ card }: { card: GameCardType }) => {
<p className="text-lg tb:text-sm pr-2 text-justify line-clamp-5 text-fg4"> <p className="text-lg tb:text-sm pr-2 text-justify line-clamp-5 text-fg4">
{card.description} {card.description}
</p> </p>
</div> </Link>
); );
}; };

View File

@@ -0,0 +1,19 @@
import Image from "next/image";
export const Cover = ({
cover,
type = "preview",
}: {
cover: string;
type?: "cover" | "preview";
}) => {
return (
<Image
src={cover}
className="rounded-lg aspect-video object-cover"
alt=""
width={type === "preview" ? 700 : 1280}
height={type === "preview" ? 400 : 720}
/>
);
};

View File

@@ -0,0 +1,3 @@
import { Cover } from "./cover";
export { Cover };