This commit is contained in:
2023-12-01 14:43:18 +05:00
parent b8cec033bb
commit edcd51599c
33 changed files with 2669 additions and 236 deletions
@@ -0,0 +1,317 @@
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { ChangeEvent, useEffect, useState } from "react";
import api from "../../utils/api";
import Button from "../Button";
import IProject from "../../types/IProject";
import useModalStore from "../../stores/useModalStore";
interface EditProjectModalProps {
projectId: string;
}
function EditProjectModal({ projectId }: EditProjectModalProps) {
const [project, setProject] = useState<IProject>({
name: "",
company: "",
city: "",
image: "",
devices: [],
});
const [file, setFile] = useState<File>();
const [previewFile, setPreviewFile] = useState<string>();
const [setModal] = useModalStore((state) => [state.setModal]);
function handleChangeFile(e: ChangeEvent<HTMLInputElement>) {
if (!e.target.files) return;
const targetFile = e.target.files[0];
setFile(targetFile);
setPreviewFile(URL.createObjectURL(targetFile));
}
async function uploadFile() {
if (!file) return;
const formData = new FormData();
formData.append("file", file);
try {
const { file }: { file: string } = await api
.post("upload", { body: formData })
.json();
setProject((prev) => ({ ...prev, image: file }));
} catch (error) {
if (error instanceof Error) {
alert(`Error: ${error.message}`);
}
}
}
async function updateProject() {
try {
await api.put(`projects/${projectId}`, { json: { ...project } });
} catch (error) {
if (error instanceof Error) {
alert(`Error: ${error.message}`);
}
}
}
async function handleSubmit(e: ChangeEvent<HTMLFormElement>) {
e.preventDefault();
await updateProject();
setModal(null);
window.location.reload();
}
async function getProject() {
try {
const project: IProject = await api.get(`projects/${projectId}`).json();
setProject(project);
} catch (error) {
if (error instanceof Error) {
alert(`Error: ${error.message}`);
}
}
}
useEffect(() => {
uploadFile();
}, [file]);
useEffect(() => {
getProject();
}, []);
return (
<div className="bg-white shadow-lg text-black p-8 rounded-xl flex flex-col gap-4">
<p className="text-xl pb-4 border-b border-[#ccc]">
Редактирование проекта
</p>
<form
onSubmit={handleSubmit}
className="grid grid-cols-2 gap-4 w-[512px]"
>
<div className="flex flex-col gap-1">
<label className="text-sm">Название</label>
<input
autoFocus
required
type="text"
placeholder="Название"
className="border border-neutral-500 px-3 py-2 rounded-lg outline-none"
value={project.name}
onChange={(e) =>
setProject((prev) => ({ ...prev, name: e.target.value }))
}
/>
</div>
<div className="flex flex-col gap-1">
<label className="text-sm">Компания</label>
<input
required
type="text"
placeholder="Компания"
className="border border-neutral-500 px-3 py-2 rounded-lg outline-none"
value={project.company}
onChange={(e) =>
setProject((prev) => ({ ...prev, company: e.target.value }))
}
/>
</div>
<div className="flex flex-col gap-1">
<label className="text-sm">Город</label>
<input
required
type="text"
placeholder="Город"
className="border border-neutral-500 px-3 py-2 rounded-lg outline-none"
value={project.city}
onChange={(e) =>
setProject((prev) => ({ ...prev, city: e.target.value }))
}
/>
</div>
<label className="relative border border-dashed border-neutral-500 px-3 py-2 hover:bg-opacity-10 hover:bg-black cursor-pointer rounded-lg flex flex-col gap-2">
<input
type="file"
accept="image/*"
className="absolute opacity-0"
onChange={handleChangeFile}
/>
<p>{file ? file.name : "Выберите изображение"}</p>
{project.image && <img src={project.image} alt="" />}
{previewFile && <img src={previewFile} alt="" />}
</label>
<div className="flex flex-col gap-1">
<label className="text-sm">Стадия</label>
<select
required
value={project.stage || ""}
className="border border-neutral-500 px-3 py-2 rounded-lg outline-none"
onChange={(e) =>
setProject((prev) => ({ ...prev, stage: +e.target.value }))
}
>
<option value="" disabled>
Выберите стадию
</option>
<option value={1}>1</option>
<option value={2}>2</option>
<option value={3}>3</option>
<option value={4}>4</option>
<option value={5}>5</option>
<option value={6}>6</option>
</select>
</div>
<div className="flex flex-col gap-1">
<label className="text-sm">Год релиза</label>
<select
required
value={project.releaseYear || ""}
className="border border-neutral-500 px-3 py-2 rounded-lg outline-none"
onChange={(e) =>
setProject((prev) => ({ ...prev, releaseYear: +e.target.value }))
}
>
<option value="" disabled>
Выберите год релиза
</option>
<option value={2024}>2024</option>
<option value={2023}>2023</option>
<option value={2022}>2022</option>
<option value={2021}>2021</option>
<option value={2020}>2020</option>
<option value={2019}>2019</option>
<option value={2018}>2018</option>
<option value={2017}>2017</option>
<option value={2016}>2016</option>
<option value={2015}>2015</option>
<option value={2014}>2014</option>
<option value={2013}>2013</option>
<option value={2012}>2012</option>
<option value={2011}>2011</option>
<option value={2010}>2010</option>
</select>
</div>
<div className="flex flex-col gap-1">
<p className="text-sm">Девайсы</p>
<div className="">
<label className="flex items-center gap-2">
<input
type="checkbox"
checked={project.devices!.includes("stream")}
onChange={(e) => {
if (e.target.checked) {
setProject((prev) => ({
...prev,
devices: [...prev.devices!, "stream"],
}));
} else {
setProject((prev) => ({
...prev,
devices: prev.devices!.filter(
(device) => device !== "stream"
),
}));
}
}}
/>
<span>Stream</span>
</label>
<label className="flex items-center gap-2">
<input
type="checkbox"
checked={project.devices!.includes("touch")}
onChange={(e) => {
if (e.target.checked) {
setProject((prev) => ({
...prev,
devices: [...prev.devices!, "touch"],
}));
} else {
setProject((prev) => ({
...prev,
devices: prev.devices!.filter(
(device) => device !== "touch"
),
}));
}
}}
/>
<span>Touch</span>
</label>
<label className="flex items-center gap-2">
<input
type="checkbox"
checked={project.devices!.includes("mobile")}
onChange={(e) => {
if (e.target.checked) {
setProject((prev) => ({
...prev,
devices: [...prev.devices!, "mobile"],
}));
} else {
setProject((prev) => ({
...prev,
devices: prev.devices!.filter(
(device) => device !== "mobile"
),
}));
}
}}
/>
<span>Mobile</span>
</label>
<label className="flex items-center gap-2">
<input
type="checkbox"
checked={project.devices!.includes("vr")}
onChange={(e) => {
if (e.target.checked) {
setProject((prev) => ({
...prev,
devices: [...prev.devices!, "vr"],
}));
} else {
setProject((prev) => ({
...prev,
devices: prev.devices!.filter(
(device) => device !== "vr"
),
}));
}
}}
/>
<span>VR</span>
</label>
</div>
</div>
<div className="col-span-full flex justify-end">
<Button className="text-white outline-none">
Сохранить изменения
</Button>
</div>
</form>
</div>
);
}
export default EditProjectModal;