Added warehouse edit api call and image displaying

This commit is contained in:
Tim Howitz 2025-06-06 18:18:49 +01:00
parent 4df13145eb
commit 127c69cb1e

View File

@ -1,4 +1,5 @@
"use client"; "use client";
import Image from "next/image";
import axios from "axios"; import axios from "axios";
import useSWR from "swr"; import useSWR from "swr";
import { Dispatch, SetStateAction, useMemo, useState } from "react"; import { Dispatch, SetStateAction, useMemo, useState } from "react";
@ -80,7 +81,7 @@ function FilterInput({
// Modal Component for Bulk Logging // Modal Component for Bulk Logging
function BulkLogModal({ onClose }: { onClose: () => void }) { function BulkLogModal({ onClose }: { onClose: () => void }) {
const [palletNote, setPalletNote] = useState(""); const [palletNote, setPalletNote] = useState("");
const [warehouseLocation, setWarehouseLocation] = useState(""); const [warehouseArea, setWarehouseArea] = useState("");
const [error, setError] = useState(""); const [error, setError] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
@ -91,7 +92,7 @@ function BulkLogModal({ onClose }: { onClose: () => void }) {
}; };
async function handleLog() { async function handleLog() {
if (!palletNote || !warehouseLocation) { if (!palletNote || !warehouseArea) {
setError("All fields are required."); setError("All fields are required.");
return; return;
} }
@ -99,10 +100,10 @@ function BulkLogModal({ onClose }: { onClose: () => void }) {
try { try {
await axios.post("/api/warehouse/log-bulk", { await axios.post("/api/warehouse/log-bulk", {
palletNote, palletNote,
warehouseLocation, warehouseArea,
}); });
alert(`Logged bulk pallet to storage: ${warehouseLocation}`); alert(`Logged bulk pallet to storage: ${warehouseArea}`);
onClose(); onClose();
} catch { } catch {
setError("Failed to log pallet. Please try again."); setError("Failed to log pallet. Please try again.");
@ -130,11 +131,11 @@ function BulkLogModal({ onClose }: { onClose: () => void }) {
/> />
<input <input
type="text" type="text"
placeholder="Storage Location (e.g., B-05)" placeholder="Warehouse Area (e.g., B-05)"
value={warehouseLocation} value={warehouseArea}
onChange={(e) => setWarehouseLocation(e.target.value)} onChange={(e) => setWarehouseArea(e.target.value)}
className="w-full p-2 border border-neutral-300 rounded-md placeholder-neutral-400 focus:ring-2 focus:ring-blue-500" className="w-full p-2 border border-neutral-300 rounded-md placeholder-neutral-400 focus:ring-2 focus:ring-blue-500"
aria-label="Storage Location" aria-label="Warehouse Area"
disabled={isSubmitting} disabled={isSubmitting}
/> />
</div> </div>
@ -185,7 +186,7 @@ function LogModal({ onClose }: { onClose: () => void }) {
const [type, setType] = useState(""); const [type, setType] = useState("");
const [description, setDescription] = useState(""); const [description, setDescription] = useState("");
const [earthquakeCode, setEarthquakeCode] = useState(""); const [earthquakeCode, setEarthquakeCode] = useState("");
const [warehouseLocation, setWarehouseLocation] = useState(""); const [warehouseArea, setWarehouseArea] = useState("");
const [isRequired, setIsRequired] = useState(true); const [isRequired, setIsRequired] = useState(true);
const [error, setError] = useState(""); const [error, setError] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
@ -213,7 +214,7 @@ function LogModal({ onClose }: { onClose: () => void }) {
}; };
async function handleLog() { async function handleLog() {
if (!name || !type || !description || !earthquakeCode || !warehouseLocation) { if (!name || !type || !description || !earthquakeCode || !warehouseArea) {
setError("All fields are required."); setError("All fields are required.");
return; return;
} }
@ -228,7 +229,7 @@ function LogModal({ onClose }: { onClose: () => void }) {
formData.append("type", type); formData.append("type", type);
formData.append("description", description); formData.append("description", description);
formData.append("earthquakeCode", earthquakeCode); formData.append("earthquakeCode", earthquakeCode);
formData.append("warehouseLocation", warehouseLocation); formData.append("warehouseArea", warehouseArea);
if (image) { if (image) {
formData.append("image", image); formData.append("image", image);
} }
@ -237,7 +238,7 @@ function LogModal({ onClose }: { onClose: () => void }) {
headers: { "Content-Type": "multipart/form-data" }, headers: { "Content-Type": "multipart/form-data" },
}); });
alert(`Logged ${name} to storage: ${warehouseLocation}`); alert(`Logged ${name} to storage: ${warehouseArea}`);
onClose(); onClose();
} catch { } catch {
setError("Failed to log artefact. Please try again."); setError("Failed to log artefact. Please try again.");
@ -301,11 +302,11 @@ function LogModal({ onClose }: { onClose: () => void }) {
/> />
<input <input
type="text" type="text"
placeholder="Warehouse Location (e.g., A-12)" placeholder="Warehouse Area (e.g., A-12)"
value={warehouseLocation} value={warehouseArea}
onChange={(e) => setWarehouseLocation(e.target.value)} onChange={(e) => setWarehouseArea(e.target.value)}
className="w-full p-2 border border-neutral-300 rounded-md placeholder-neutral-400 focus:ring-2 focus:ring-blue-500" className="w-full p-2 border border-neutral-300 rounded-md placeholder-neutral-400 focus:ring-2 focus:ring-blue-500"
aria-label="Storage Location" aria-label="Warehouse Area"
disabled={isSubmitting} disabled={isSubmitting}
/> />
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@ -362,12 +363,11 @@ function LogModal({ onClose }: { onClose: () => void }) {
); );
} }
// Modal Component for Editing Artefact
function EditModal({ artefact, onClose }: { artefact: ExtendedArtefact; onClose: () => void }) { function EditModal({ artefact, onClose }: { artefact: ExtendedArtefact; onClose: () => void }) {
const [name, setName] = useState(artefact.name); const [name, setName] = useState(artefact.name);
const [type, setType] = useState(""); const [type, setType] = useState(artefact.type);
const [description, setDescription] = useState(artefact.description); const [description, setDescription] = useState(artefact.description);
const [warehouseLocation, setWarehouseLocation] = useState(""); const [warehouseArea, setWarehouseArea] = useState(artefact.warehouseArea);
const [earthquakeCode, setEarthquakeCode] = useState(artefact.earthquakeCode); const [earthquakeCode, setEarthquakeCode] = useState(artefact.earthquakeCode);
const [isRequired, setIsRequired] = useState(artefact.isRequired); const [isRequired, setIsRequired] = useState(artefact.isRequired);
const [isSold, setIsSold] = useState(artefact.isSold); const [isSold, setIsSold] = useState(artefact.isSold);
@ -376,9 +376,6 @@ function EditModal({ artefact, onClose }: { artefact: ExtendedArtefact; onClose:
const [error, setError] = useState(""); const [error, setError] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
// todo add display of image in public dir at /artefact.imageName
// todo add display of artefact.createdAt date
function handleOverlayClick(e: { target: any; currentTarget: any }) { function handleOverlayClick(e: { target: any; currentTarget: any }) {
if (e.target === e.currentTarget) { if (e.target === e.currentTarget) {
onClose(); onClose();
@ -386,7 +383,7 @@ function EditModal({ artefact, onClose }: { artefact: ExtendedArtefact; onClose:
} }
async function handleSave() { async function handleSave() {
if (!name || !type || !description || !earthquakeCode || !warehouseLocation) { if (!name || !type || !description || !earthquakeCode || !warehouseArea) {
setError("All fields are required."); setError("All fields are required.");
return; return;
} }
@ -396,8 +393,24 @@ function EditModal({ artefact, onClose }: { artefact: ExtendedArtefact; onClose:
} }
setIsSubmitting(true); setIsSubmitting(true);
try { try {
// todo add api route const formData = new FormData();
await new Promise((resolve) => setTimeout(resolve, 500)); // Simulated API call formData.append("id", artefact.id.toString());
formData.append("name", name);
formData.append("type", type);
formData.append("description", description);
formData.append("earthquakeCode", earthquakeCode);
formData.append("warehouseArea", warehouseArea);
formData.append("isRequired", isRequired.toString());
formData.append("isSold", isSold.toString());
formData.append("isCollected", isCollected.toString());
if (image) {
formData.append("image", image);
}
await axios.post("/api/warehouse/edit-artefact", formData, {
headers: { "Content-Type": "multipart/form-data" },
});
alert(`Updated artefact ${name}`); alert(`Updated artefact ${name}`);
onClose(); onClose();
} catch { } catch {
@ -431,6 +444,17 @@ function EditModal({ artefact, onClose }: { artefact: ExtendedArtefact; onClose:
<h3 className="text-lg font-semibold mb-4 text-neutral-800">Edit Artefact</h3> <h3 className="text-lg font-semibold mb-4 text-neutral-800">Edit Artefact</h3>
{error && <p className="text-red-600 text-sm mb-2">{error}</p>} {error && <p className="text-red-600 text-sm mb-2">{error}</p>}
<div className="space-y-2"> <div className="space-y-2">
{artefact.imageName && (
<div className="mb-2">
<Image
src={`/uploads/${artefact.imageName}`}
alt="Artefact"
width={200}
height={200}
className="object-cover rounded-md"
/>
</div>
)}
<input <input
type="file" type="file"
accept="image/jpeg,image/png" accept="image/jpeg,image/png"
@ -439,7 +463,7 @@ function EditModal({ artefact, onClose }: { artefact: ExtendedArtefact; onClose:
aria-label="Artefact Image" aria-label="Artefact Image"
disabled={isSubmitting} disabled={isSubmitting}
/> />
<p className="text-sm text-neutral-600">Created At: {new Date(artefact.createdAt).toLocaleDateString("en-GB")}</p>
<input <input
type="text" type="text"
placeholder="Name" placeholder="Name"
@ -477,14 +501,13 @@ function EditModal({ artefact, onClose }: { artefact: ExtendedArtefact; onClose:
/> />
<input <input
type="text" type="text"
placeholder="Warehouse Location (e.g., A-12)" placeholder="Warehouse Area (e.g., A-12)"
value={warehouseLocation} value={warehouseArea}
onChange={(e) => setWarehouseLocation(e.target.value)} onChange={(e) => setWarehouseArea(e.target.value)}
className="w-full p-2 border border-neutral-300 rounded-md placeholder-neutral-400 focus:ring-2 focus:ring-blue-500" className="w-full p-2 border border-neutral-300 rounded-md placeholder-neutral-400 focus:ring-2 focus:ring-blue-500"
aria-label="Storage Location" aria-label="Storage Location"
disabled={isSubmitting} disabled={isSubmitting}
/> />
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<input <input
type="checkbox" type="checkbox"