need help. I am new to Supabase and don't understand some things.
I want to create simple form where I can upload Image, add name, description and price. I can save Image to bucket, add information into database. Fetch this data.
BUT! I can't imagine how to combine this 2 things. I need grab publicUrl of Image and add it into database to productId.
How to do that? I feel that this must be very simple solution, but I already spend for this 2 days. ChatGPT didn't help me. I don't understand how to solve this.
My form:
import React, { useState } from "react";
import Head from "next/head";
import { useRouter } from "next/router";
import { supabase } from "@/utils/supabaseClient";
import { Button, InputFilled, TextFieldFilled } from "@/core/ui/components";
import { StorageError } from "@supabase/storage-js";
import { useAddress } from "@thirdweb-dev/react";
export default function AddPage() {
const router = useRouter();
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [price, setPrice] = useState("");
const [formError, setFormError] = useState("");
const [coverUrl, setCoverUrl] = useState(null);
const address = useAddress();
const wallet = address;
async function handleSubmit(e: { preventDefault: () => void }) {
e.preventDefault();
const { data, error } = await supabase
.from("products")
.insert([{ name, description, price, wallet }]);
if (data) {
console.log(data);
setFormError("");
router.push("/profile");
}
if (!name || !description || !price) {
setFormError("Please fill in all the fields correctly.");
return;
}
const publicUrl = await uploadImage(coverUrl);
if (publicUrl !== null) {
console.log(publicUrl);
}
}
async function uploadImage(e: any) {
try {
const file = e.target.files[0];
const publicURL = supabase.storage.from("cover").getPublicUrl(file.name);
const {
data,
error,
}: { data: { path: string } | null; error: StorageError | null } =
await supabase.storage.from("cover").upload(`${file.name}`, file);
if (error) {
throw error;
}
console.log("File uploaded successfully");
console.log(publicURL);
} catch (error: any) {
console.log("Error uploading file: ", error.message);
}
}
return (
<>
<Head>
<title>New stuff </title>
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no"
/>
<meta
content="New stuff"
name="New stuff"
/>
</Head>
{/*INPUTS*/}
<form
onSubmit={handleSubmit}
className="m-[12px] flex flex-col items-start gap-[12px] lg:w-2/3">
<div className="flex w-full flex-col items-center justify-center rounded-large border border-dashed border-zinc-700 bg-[#161618]/50 text-white hover:bg-zinc-500/20">
<div className="flex items-center justify-center">
<label
htmlFor="dropzone-file"
className="flex h-64 w-full cursor-pointer flex-col items-center justify-center rounded-lg">
<div className="flex flex-col items-center justify-center pt-5 pb-6">
<svg
aria-hidden="true"
className="mb-3 h-10 w-10 text-zinc-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"></path>
</svg>
<p className="mb-2 text-title-medium text-zinc-500 dark:text-zinc-400">
<span className="font-bold">Click to upload cover</span>
</p>
<p className="text-xs text-zinc-500 dark:text-zinc-400">
SVG, PNG, JPG or GIF
</p>
</div>
<input
id="dropzone-file"
type="file"
className=""
onChange={uploadImage}
/>
</label>
</div>
</div>
<InputFilled
type="text"
placeholder="Name"
id="name"
value={name}
onChange={(event) => setName(event.target.value)}
/>
<TextFieldFilled
type="text"
placeholder="Description"
id="description"
value={description}
onChange={(event) => setDescription(event.target.value)}
/>
<InputFilled
type="text"
placeholder="Price, USD"
id="price"
value={price}
onChange={(event) => setPrice(event.target.value)}
/>
<Button
className=""
type="submit"
onClick={() => router.push("/profile")}
disabled={!name || !description || !price}>
Submit
</Button>
</form>
</>
);
}
Would be happy to get some advices how to fix my issue! I read docs, strive to find solution or example and didn't find. Thanks!
You can store the public URL as a state like this
const [imagePublicUrl, setImagePublicUrl] = useState(null);
Then store the public URL inside your uploadImage
method.
const publicURL = supabase.storage.from("cover").getPublicUrl(file.name);
setImagePublicUrl(publicURL)
And store the imagePublicUrl
when you save the data to Supabase. This of course assumes you create a column named image_url
in your products
table.
const { data, error } = await supabase
.from("products")
.insert([{ name, description, price, wallet, image_url: imagePublicUrl }]);