From 8f4ff714256632f08d7c05f8d96e3c2e46f0741a Mon Sep 17 00:00:00 2001 From: Brandon Egger Date: Sun, 25 Jun 2023 20:05:46 -0500 Subject: [PATCH] add basic implementation of file upload --- src/components/admin/resources/form.tsx | 32 +++++++----------- src/pages/api/resources/photo/[id].tsx | 44 ++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/components/admin/resources/form.tsx b/src/components/admin/resources/form.tsx index b17c51a..539adbf 100644 --- a/src/components/admin/resources/form.tsx +++ b/src/components/admin/resources/form.tsx @@ -41,7 +41,6 @@ import { import Modal from "react-modal"; import { type RouterInputs } from "~/utils/api"; import { PlatformLinkButton } from "~/pages/resources/[id]"; -import axios from "axios"; // Required for accessibility // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access @@ -55,36 +54,21 @@ export type ResourceUpdateInput = RouterInputs["auditoryResource"]["update"]; * File needs to be path relative to resource_logos/ */ const SelectImageInput = ({ file }: { file?: string }) => { - const onChange = async (event: ChangeEvent) => { - console.log(event.target.files); + const { getValues } = useFormContext(); + const onChange = async (event: ChangeEvent) => { const data = new FormData(); if (!event.target.files || !event.target.files[0]) { return; } + const resourceId = getValues("id"); data.append("photo", event.target.files[0]); - const response = await axios.post( - "/api/resources/photo/645b1afc1905d6074dfcf17d", - data, - { - headers: { - "Content-Type": "multipart/form-data", - }, - } - ); - - const ress = await fetch("/api/resources/photo/645b1afc1905d6074dfcf17d", { + await fetch(`/api/resources/photo/${resourceId}`, { method: "POST", - headers: { - Accept: "application/json", - }, body: data, }); - - console.log("done"); - console.log(response); }; return ( @@ -105,7 +89,13 @@ const SelectImageInput = ({ file }: { file?: string }) => { { + onChange(event).catch(() => { + throw new Error( + "Unexpected error occured when selecting new file." + ); + }); + }} accept="image/*" id="resource-image-file" type="file" diff --git a/src/pages/api/resources/photo/[id].tsx b/src/pages/api/resources/photo/[id].tsx index d2d6c14..3257ea3 100644 --- a/src/pages/api/resources/photo/[id].tsx +++ b/src/pages/api/resources/photo/[id].tsx @@ -1,24 +1,60 @@ import { type NextApiHandler } from "next"; import formidable from "formidable"; +import * as path from "path"; +import { prisma } from "~/server/db"; -const handler: NextApiHandler = (req, res) => { +/** + * Returns filename for a given filepath. + * @param filepath + */ +function getFileName(filepath: string) { + return filepath.split("/").at(-1) ?? ""; +} + +const handler: NextApiHandler = async (req, res) => { if (req.method !== "POST") { res.status(404).end(); return; } const { id } = req.query; - console.log(id); + + if (Array.isArray(id) || !id) { + res.writeHead(400, "Invalid resource ID provided").end(); + return; + } const form = formidable({ uploadDir: "./public/resource_logos/uploads", keepExtensions: true, }); - form.parse(req, (err, fields, files) => { - console.log(JSON.stringify(files)); + const localUploadPath: Promise = new Promise((resolve, reject) => { + form.parse(req, (_err, _fields, files) => { + const photo = Array.isArray(files.photo) ? files.photo[0] : files.photo; + if (!photo) { + reject("Invalid file type sent (or none provided)"); + return; + } + + resolve(path.join("uploads", getFileName(photo.filepath))); + }); }); + try { + await prisma.auditoryResource.update({ + where: { + id, + }, + data: { + icon: await localUploadPath, + }, + }); + } catch (error: unknown) { + res.writeHead(400, JSON.stringify((error as Error).message)).end(); + return; + } + res.writeHead(200, { "Content-Type": "application/json" }).end(); };