Files
mwitnessing/components/location/LocationForm.js
Dobromir Popov 860115e074 fix js error
2025-01-04 02:12:17 +02:00

322 lines
12 KiB
JavaScript

import axiosInstance from '../../src/axiosSecure';
import { useEffect, useState, useRef } from "react";
import { useRouter } from "next/router";
import toast from "react-hot-toast";
import Link from "next/link";
import DayOfWeek from "../DayOfWeek";
import TextEditor from "../TextEditor";
import FileUploadWithPreview from 'components/FileUploadWithPreview ';
import ProtectedRoute, { serverSideAuth } from "../../components/protectedRoute";
import { UserRole } from "@prisma/client";
import { Input } from '@mui/base';
const common = require('src/helpers/common');
// ------------------ LocationForm ------------------
// This component is used to create and edit locations
// location model:
// model Location {
// id Int @id @default(autoincrement())
// name String
// address String
// isActive Boolean @default(true)
// content String? @db.Text
// cartEvents CartEvent[]
// reports Report[]
// backupLocationId Int?
// backupLocation Location? @relation("BackupLocation", fields: [backupLocationId], references: [id])
// BackupForLocations Location[] @relation("BackupLocation")
// }
export default function LocationForm() {
const [uploadedImages, setUploadedImages] = useState([]);
const [isPreviewMode, setIsPreviewMode] = useState(false);
useEffect(() => {
const fetchUploadedImages = async () => {
try {
// ToDo: we don't have this endpoint yet and we don't use the uploaded images collection
// const response = await axiosInstance.get('/uploaded-images');
// setUploadedImages(response.data.imageUrls);
} catch (error) {
console.error('Error fetching uploaded images:', error);
}
};
fetchUploadedImages();
}, []);
const quillRef = useRef(null);
const handleImageSelect = (e) => {
const imageUrl = e.target.value;
if (imageUrl && quillRef.current) {
const editor = quillRef.getQuill();
const range = editor.getSelection(true);
if (range) {
editor.insertEmbed(range.index, 'image', imageUrl);
}
}
};
const [content, setContent] = useState("");
const [location, set] = useState({
name: "",
address: "",
isActive: true,
});
const [isRawHtml, setIsRawHtml] = useState(false);
// const [isEdit, setIsEdit] = useState(false);
const router = useRouter();
useEffect(() => {
const fetchLocation = async (id) => {
try {
console.log("fetching location " + router.query.id);
const { data } = await axiosInstance.get("/api/data/locations/" + id);
set(data);
setContent(data.content);
} catch (error) {
console.error(error);
}
};
if (router.query?.id) {
fetchLocation(parseInt(router.query.id.toString()));
}
console.log("called");
}, [router.query.id]);
const [locations, setLocations] = useState([]);
useEffect(() => {
const fetchLocations = async () => {
try {
console.log("fetching locations");
const { data } = await axiosInstance.get("/api/data/locations");
setLocations(data);
console.log(data);
} catch (error) {
console.error(error);
}
};
if (!locations.length) {
fetchLocations();
}
}, []);
const handleChange = ({ target }) => {
if (target.type === "checkbox") {
set({ ...location, [target.name]: target.checked });
} else if (target.type === "number") {
set({ ...location, [target.name]: parseInt(target.value) });
} else {
set({ ...location, [target.name]: target.value });
}
}
const handleSubmit = async (e) => {
e.preventDefault();
try {
const dataToSend = {
...location,
name: location.name.trim(),
content: content,
};
if (router.query?.id) { // UPDATE
//connect backup location
delete dataToSend.id;
dataToSend.backupLocationId = parseInt(dataToSend.backupLocationId);
// dataToSend.backupLocation = { connect: { id: location.backupLocationId } };
// delete dataToSend.backupLocationId;
await axiosInstance.put("/api/data/locations/" + router.query.id, {
...dataToSend,
});
toast.success("Task Updated", {
position: "bottom-center",
});
} else { // CREATE
await axiosInstance.post("/api/data/locations", dataToSend);
toast.success("Task Saved", {
position: "bottom-center",
});
}
router.push("/cart/locations");
} catch (error) {
//toast.error(error.response.data.message);
}
};
return (
<>
<ProtectedRoute allowedRoles={[UserRole.ADMIN]} deniedMessage="">
<div className="w-full max-lg">
<form className="bg-white dark:bg-gray-800 shadow-md rounded px-8 pt-6 pb-8 mb-4" onSubmit={handleSubmit} >
<div className="mb-4">
<label className="label" htmlFor="name">Location Name</label>
<input className="textbox" placeholder="name" id="name" name="name" onChange={handleChange} value={location.name} autoComplete="off" />
</div>
{/* Location.address */}
<div className="mb-4">
<label className="label" htmlFor="address"> Address</label>
<input className="textbox"
placeholder="address" id="address" name="address" onChange={handleChange} value={location.address} autoComplete="off" />
</div>
{/* UI for Location.isActive */}
<div className="mb-4">
<div className="form-check">
<input className="checkbox form-input" type="checkbox" id="isActive" name="isActive" onChange={handleChange} checked={location.isActive} autoComplete="off" />
<label className="label" htmlFor="isActive">Активна</label>
</div>
</div>
{/* is on main menu */}
<div className="mb-4">
<div className="form-check">
<input className="checkbox form-input" type="checkbox" id="isOnMainMenu" name="isOnMainMenu" onChange={handleChange} checked={location.isOnMainMenu} autoComplete="off" />
<label className="label" htmlFor="isOnMainMenu">Покажи в главното меню</label>
</div>
</div>
{/* backupLocation */}
<div className="mb-4">
<label className="label" htmlFor="backupLocation">При дъжд и лошо време</label>
{locations && (
<select name="backupLocationId" id="backupLocationId" onChange={handleChange} value={location.backupLocationId} placeholder="Избери локация...">
<option>Избери локация...</option>
{locations.map((loc) => (
<option key={loc.id} value={loc.id} type="number">{loc.name}</option>
))}
</select>
)}
</div>
{/* Location.content */}
<div className="mb-4">
{/* <select onChange={handleImageSelect}>
<option>Select an image</option>
{uploadedImages.map((imageUrl, index) => (
<option key={index} value={imageUrl}>{imageUrl}</option>
))}
</select> */}
{router.query.id && (
<>
<div className="flex space-x-4">
<FileUploadWithPreview
name="picture1"
label="Снимка 1"
value={location.picture1}
prefix={`location-${router.query.id}-picture1`}
onUpload={(name, imageUrl) => {
console.log('Uploaded image URL:', imageUrl);
set(location => ({ ...location, [name]: imageUrl }));
}}
/>
<FileUploadWithPreview
name="picture2"
label="Снимка 2"
value={location.picture2}
prefix={`location-${router.query.id}-picture2`}
onUpload={(name, imageUrl) => {
console.log('Uploaded image URL:', imageUrl);
set(location => ({ ...location, [name]: imageUrl }));
}}
/>
<FileUploadWithPreview
name="picture3"
label="Снимка 3"
value={location.picture3}
prefix={`location-${router.query.id}-picture3`}
onUpload={(name, imageUrl) => {
console.log('Uploaded image URL:', imageUrl);
set(location => ({ ...location, [name]: imageUrl }));
}}
/>
</div>
<label className="label" htmlFor="content">Content</label>
<ProtectedRoute allowedRoles={[UserRole.ADMIN]} deniedMessage=" ">
<label className="label" htmlFor="backupLocation">Admin Edit Location HTML</label>
<div className="field mb-4">
<label className="switch">
<input
type="checkbox"
checked={isRawHtml}
onChange={(e) => {
setIsRawHtml(e.target.checked);
}}
/>
<span className="slider round"></span>
<span className="ml-2">Edit Raw HTML</span>
</label>
{isRawHtml && <>
<label className="label" htmlFor="backupLocation">Admin Edit Location HTML</label>
<textarea
className="w-full min-h-[200px] p-3 border rounded-lg shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-800 dark:border-gray-700 dark:text-gray-200 font-mono resize-y"
placeholder="HTML Content"
id="contentHTML_Raw"
name="contentHTML_Raw"
onChange={(e) => setContent(e.target.value)}
value={content}
autoComplete="off"
spellCheck="false"
/>
</>
}
</div>
</ProtectedRoute>
{!isRawHtml && <>
<TextEditor
ref={quillRef}
value={content}
onChange={setContent}
placeholder="Описание на локацията. Снимки"
prefix={`location-${router.query.id}`} />
</>}
</>)}
</div>
<div className="panel-actions pt-12">
<Link href="/cart/locations" className="action-button"> Отмени </Link>
<button className="button bg-blue-500 hover:bg-blue-700 focus:outline-none focus:shadow-outline" type="submit">
{router.query?.id ? "Обнови" : "Запази"}
</button>
</div>
</form>
</div>
<button className='button' onClick={() => setIsPreviewMode(!isPreviewMode)}>
{isPreviewMode ? 'Скрий прегледа' : 'Преглед'}
</button>
</ProtectedRoute>
<ProtectedRoute allowedRoles={[UserRole.USER]} deniedMessage=" " bypass={isPreviewMode}>
<label className="label" htmlFor="backupLocation">При дъжд и лошо време</label>
{location.name}
{location.address}
{location.backupLocationName}
<div className="border-2 border-blue-500 p-5 my-5 rounded-lg" dangerouslySetInnerHTML={{ __html: content }}></div>
</ProtectedRoute>
</>
);
}