Files
graff.estate/client/src/components/modals/EditProjectModal.tsx
T
2023-12-01 14:43:18 +05:00

318 lines
9.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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;