Now let's work on showing available media files in MediaLibrary so that user can pick one from the list and use as featured image.
Backend route and controller
// routes
router.delete("/media/:id", requireSignin, isAdmin, removeMedia);
// controllers
export const removeMedia = async (req, res) => {
try {
const { id } = req.params;
const media = await Media.findByIdAndDelete(id);
return res.json({ ok: true });
} catch (err) {
console.log(err);
}
};
Show all media in frontend. On click, set selected and allow delete
// components/media/MediaLibrary.js
import React, { useContext, useEffect } from "react";
import { Upload, message, Image, Badge } from "antd";
import { InboxOutlined, CloseCircleFilled } from "@ant-design/icons";
import { AuthContext } from "../../context/auth";
import { MediaContext } from "../../context/media";
import axios from "axios";
import toast from "react-hot-toast";
const { Dragger } = Upload;
const MediaLibrary = () => {
// context
const [auth, setAuth] = useContext(AuthContext);
const [media, setMedia] = useContext(MediaContext);
useEffect(() => {
const fetchMedia = async () => {
try {
const { data } = await axios.get("/media");
// console.log(data);
setMedia((prev) => ({ ...prev, images: data }));
} catch (err) {
console.log(err);
}
};
// execute
fetchMedia();
}, []);
const props = {
name: "file",
multiple: true,
action: `${process.env.NEXT_PUBLIC_API}/upload-image-file`,
headers: {
Authorization: `Bearer ${auth.token}`,
},
onChange(info) {
const { status } = info.file;
if (status !== "uploading") {
// console.log(info.file, info.fileList);
}
if (status === "done") {
// console.log("############ ============> ", info.file.response);
setMedia({
images: [...media.images, info.file.response],
showMediaModal: true,
// selected: info.file.response,
});
message.success(`${info.file.name} file uploaded successfully.`);
} else if (status === "error") {
message.error(`${info.file.name} file upload failed.`);
}
},
onDrop(e) {
console.log("Dropped files", e.dataTransfer.files);
},
};
const handleImageDelete = async (imageId) => {
try {
const { data } = await axios.delete(`/media/${imageId}`);
console.log(data);
if (data.ok) {
setMedia((prev) => ({
...prev,
images: prev.images.filter((image) => image._id !== imageId),
selected: null,
}));
}
} catch (err) {
console.log(err);
}
};
return (
<>
<Dragger {...props} accept="image/*">
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text">
Click or drag file to this area to upload
</p>
</Dragger>
<div style={{ textAlign: "center" }}>
{media?.images?.map((image) => (
<Badge>
<Image
onClick={() => {
setMedia({ ...media, selected: image });
toast.success("Selected");
}}
style={{
paddingTop: 5,
paddingRight: 10,
height: "100px",
width: "100px",
objectFit: "cover",
}}
src={image.url}
/>
<br />
<CloseCircleFilled
style={{ marginRight: 10, color: "#f5222d" }}
onClick={() => handleImageDelete(image._id)}
/>
</Badge>
))}
</div>
</>
);
};
export default MediaLibrary;