-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added image upload component and backend call #132
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import React, { useContext } from "react"; | ||
import { storage } from "../../db/firebase"; // import firebase storage | ||
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage"; | ||
|
||
export const ImageUpload = ({}) => { | ||
const saveFile = async (e: React.ChangeEvent<HTMLInputElement>) => { | ||
const files = e.target.files; | ||
if (!files || files.length === 0) return; | ||
|
||
try { | ||
const file = files[0]; | ||
|
||
const extension = file.name.split(".").pop(); | ||
const storageRef = ref(storage, `images/${Date.now()}.${extension}`); | ||
|
||
const uploadTask = uploadBytesResumable(storageRef, file); | ||
|
||
uploadTask.on( | ||
"state_changed", | ||
(snapshot) => { | ||
const progress = | ||
(snapshot.bytesTransferred / snapshot.totalBytes) * 100; | ||
}, | ||
(error) => { | ||
console.error("Upload failed:", error); | ||
}, | ||
async () => { | ||
const downloadURL = await getDownloadURL(uploadTask.snapshot.ref); | ||
// TODO: Incorporate baby and caregiver context | ||
// https://github.com/GTBitsOfGood/motherhood-beyond-bars/blob/_original/mobile/screens/babybook/SelectPicture.tsx#L28 | ||
// TODO: Incorporate caption | ||
const metadata = { | ||
imageURL: downloadURL, | ||
caregiverID: "test-caregiverId", | ||
caption: "test-caption", | ||
babyID: "test-babyId", | ||
}; | ||
const response = await fetch("/api/save-image", { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify(metadata), | ||
}); | ||
if (!response.ok) { | ||
const result = await response.json(); | ||
alert(result.error || "Error uploading image metadata"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Return an object here as well instead of an error |
||
} | ||
} | ||
); | ||
} catch (error) { | ||
console.error("Upload failed:", error); | ||
alert("An error occurred while uploading the image."); | ||
} | ||
}; | ||
return <input type="file" onChange={saveFile} />; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The backend and frontend should be separated where the backend endpoint is in a separate file from the frontend so that it can be re-used |
||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// pages/api/saveImage.js | ||
import { NextApiRequest, NextApiResponse } from "next"; | ||
import { db } from "../../db/firebase"; // Firestore database | ||
import { doc, setDoc, Timestamp } from "firebase/firestore"; | ||
|
||
export default async function handler( | ||
req: NextApiRequest, | ||
res: NextApiResponse | ||
) { | ||
if (req.method === "POST") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. API isn't needed in this case since Firebase can do client-side database calls, so to speed up code fetching we should call the Firebase functions as endpoints rather than in the API. There are some cases where we need to handle things on the server-side, but we're good in this case |
||
// Extracting the necessary data from the request body | ||
const { imageURL, caregiverID, caption, babyID } = req.body; | ||
|
||
try { | ||
// Create a reference to the document in the 'babies' collection and save metadata | ||
const docRef = doc( | ||
db, | ||
"babies", | ||
babyID, | ||
"book", | ||
`${caregiverID}_${Date.now()}` | ||
); | ||
await setDoc(docRef, { | ||
imageUrl: imageURL, | ||
caption: caption, | ||
date: Timestamp.now(), | ||
caregiverId: caregiverID, | ||
}); | ||
|
||
res.status(200).json({ message: "Image metadata saved successfully" }); | ||
} catch (error) { | ||
console.error("Error saving image metadata:", error); | ||
res.status(500).json({ error: "Error saving image metadata" }); | ||
} | ||
} else { | ||
res.status(405).json({ message: "Method not allowed" }); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// pages/upload-test.js | ||
|
||
import { ImageUpload } from "@components/BabyBook/ImageUpload"; | ||
|
||
const UploadTestPage = () => { | ||
return ( | ||
<div> | ||
<h1>Test Image Upload</h1> | ||
<ImageUpload /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default UploadTestPage; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return an object instead of printing the error or showing an alert so that displaying errors can be handled by the frontend, should be in the form
{success: false, error: [error message]}