Work on game edit

This commit is contained in:
2024-05-26 13:55:34 +04:00
parent 2572c43733
commit 8b6246a38c
16 changed files with 405 additions and 217 deletions

View File

@@ -0,0 +1,184 @@
"use client";
import {
gameCreateSchema,
GameCreateType,
GameService,
GameType,
} from "@/entities/game";
import clsx from "clsx";
import Image from "next/image";
import Link from "next/link";
import { getYouTubeID } from "@/shared/utils";
import { UserService } from "@/entities/user";
import useSWR from "swr";
import { useEffect, useState } from "react";
import { SubmitHandler, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
export const GameInfo = ({ game }: { game: GameType }) => {
const { data: me } = useSWR("user", () => UserService.IdentifyYourself());
const [editable, setEditable] = useState<boolean>(false);
useEffect(() => setEditable(me?.id === game.owner_id), [me, game]);
const {
register,
handleSubmit,
setValue,
formState: { errors },
} = useForm<GameCreateType>({
resolver: zodResolver(gameCreateSchema),
});
useEffect(() => {
register("torrent_file", { value: game.torrent_file });
register("cover", { value: game.cover });
}, []);
useEffect(() => {
console.log(errors);
}, [errors]);
const onSubmit = (formData: GameCreateType) => {
const updatedGame = GameService.changeGame(game.id, formData);
console.log(updatedGame);
};
return (
<form
onSubmit={handleSubmit(onSubmit)}
className="p-4 flex flex-col lp:block"
>
{game.cover && (
<div className="lp:w-[60%] lp:px-4 lp:pl-0 py-2 float-left">
<Image
src={game.cover}
className="rounded-lg w-full object-contain"
alt=""
width={1280}
height={720}
/>
</div>
)}
<span className="lp:max-w-[40%]">
<h1
className={clsx(
"text-4xl outline-none",
!editable && "cursor-default"
)}
suppressContentEditableWarning={true}
contentEditable={editable}
{...register("title", { value: game.title })}
onInput={(e) => {
setValue("title", e.currentTarget.innerText, {
shouldValidate: true,
});
console.log();
}}
>
{game.title}
</h1>
{game.description && (
<div
contentEditable={editable}
suppressContentEditableWarning={true}
className={clsx(
"text-md text-justify",
"text-fg4 pt-2 outline-none",
!editable && "cursor-default"
)}
{...register("description", { value: game.description })}
onInput={(e) => {
setValue("description", e.currentTarget.innerText, {
shouldValidate: true,
});
}}
>
{game.description}
</div>
)}
</span>
<div
className={clsx(
"w-full flex justify-between pt-4",
!editable && "cursor-default"
)}
>
{[
[
{ name: "Система", key: "system" },
{ name: "Процессор", key: "processor" },
{ name: "Оперативная память", key: "memory" },
{ name: "Видеокарта", key: "graphics" },
{ name: "Место на диске", key: "storage" },
],
[
{ name: "Версия игры", key: "version" },
{
name: "Дата обновления раздачи",
key: "update_date",
value: game.update_date.toLocaleDateString("ru-ru"),
},
{ name: "Язык", key: "language" },
{ name: "Разработчик", key: "developer" },
{
name: "Год выхода",
key: "release_date",
value: game.release_date.toLocaleDateString("en-us", {
year: "numeric",
}),
},
{ name: "Объём загрузки", key: "download_size" },
],
].map((section, i) => (
<ul key={i} className="w-[48%] bg-bg1 rounded-lg py-1 px-4">
{section.map((req) => (
<li key={req.name} className="font-bold text-sm lp:text-md py-1">
{req.name + ": "}
<input
readOnly={!editable}
className={clsx(
"font-normal outline-none bg-bg1",
req.value === undefined && "text-fg4"
)}
{...register(req.key as keyof GameCreateType)}
defaultValue={
req.value ??
(game[req.key as keyof GameType] as string) ??
"Не известно"
}
></input>
</li>
))}
</ul>
))}
</div>
{game.trailer && getYouTubeID(game.trailer) && (
<iframe
src={"https://youtube.com/embed/" + getYouTubeID(game.trailer)}
className="w-full aspect-video rounded-lg mt-4"
allowFullScreen
/>
)}
<div className="relative w-full flex items-center justify-around pt-4">
<Link
href={process.env.NEXT_PUBLIC_CONTENT_URL + "/" + game.torrent_file}
className="p-4 bg-ac0 text-fg1 text-2xl rounded-lg"
>
Скачать {game.title}
</Link>
</div>
<div className="w-full flex justify-end">
<Link
className="text-right text-sm relative top-4 lp:-top-4"
href="/how_to_download"
>
Как скачать игру
<br /> с помощью .torrent файла?
</Link>
</div>
<input type="submit" className=" m-2 p-2 bg-ac0" />
</form>
);
};

View File

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

View File

@@ -50,6 +50,7 @@ export const Header = () => {
</span>
<label className="flex flex-col items-start relative w-36">
<input
type="search"
className="peer/search w-full rounded-lg bg-bg4 px-2"
placeholder=" "
/>

View File

@@ -14,7 +14,7 @@ export const MobileMenu = ({
return (
<div className="relative">
<button
className="peer w-16 h-16 *:w-12 *:h-1 *:bg-fg1 *:my-3
className="w-16 h-16 *:w-12 *:h-1 *:bg-fg1 *:my-3
*:transition-all *:duration-300 *:relative"
onClick={() => changeMenuOpen(!open)}
onBlur={() => changeMenuOpen(false)}
@@ -30,7 +30,7 @@ export const MobileMenu = ({
<div
className={clsx(
"h-0 absolute transition-all duration-300 overflow-hidden\
bg-bg4 rounded-lg px-4 flex flex-col",
bg-bg4 rounded-lg px-4 flex flex-col shadow-xl",
open && "h-32"
)}
onClick={() => changeMenuOpen(false)}