diff --git a/src/Pages/BlogsAndArticles/EditBlogsAndArticles.jsx b/src/Pages/BlogsAndArticles/EditBlogsAndArticles.jsx index 1a1283b..d7f35db 100644 --- a/src/Pages/BlogsAndArticles/EditBlogsAndArticles.jsx +++ b/src/Pages/BlogsAndArticles/EditBlogsAndArticles.jsx @@ -51,7 +51,6 @@ const EditBlogsAndArticles = () => { console.log(blog?.tags?.map((tagObject) => tagObject.tag)); const [valueQuill, setValueQuill] = useState(blog?.content); - console.log(blog); const { register, diff --git a/src/Pages/Community/CommunityBannerCard.jsx b/src/Pages/Community/CommunityBannerCard.jsx index 485ccb0..d1dbd0f 100644 --- a/src/Pages/Community/CommunityBannerCard.jsx +++ b/src/Pages/Community/CommunityBannerCard.jsx @@ -49,7 +49,7 @@ const CommunityBannerCard = ({ // border={"1px solid #9B4651"} borderRadius={8} overflow={"hidden"} - backgroundColor={"#101015"} + backgroundColor={"#2d3436"} // backgroundColor={status ? "#ffe5ea": '#ffffff'} backdropFilter="blur(1px)" > diff --git a/src/Pages/Usecase/AddUseCase.jsx b/src/Pages/Usecase/AddUseCase.jsx index fde0c11..0c45967 100644 --- a/src/Pages/Usecase/AddUseCase.jsx +++ b/src/Pages/Usecase/AddUseCase.jsx @@ -410,7 +410,7 @@ const AddUseCase = () => { - + diff --git a/src/Pages/Usecase/EditUseCase.jsx b/src/Pages/Usecase/EditUseCase.jsx new file mode 100644 index 0000000..bd673d8 --- /dev/null +++ b/src/Pages/Usecase/EditUseCase.jsx @@ -0,0 +1,583 @@ +import React, { useEffect, useState } from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import { + Box, + Button, + Divider, + FormControl, + Textarea, + FormHelperText, + FormLabel, + Heading, + Image, + Input, + Stack, + useToast, +} from "@chakra-ui/react"; +import { + useGetBlogByIdQuery, + useGetUsecaseByIdQuery, + useUpdateBlogMutation, + useUpdateUsecaseMutation, +} from "../../Services/api.service"; +import { useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import FullscreenLoaders from "../../Components/Loaders/FullscreenLoaders"; +import { addBlogSchema, addUsecase, editUsecase } from "../../Validations/Validations"; +import fallbackImage from "../../assets/fallBackImage.png"; +import fallbackImageLarge from "../../assets/ultp-fallback-img.webp"; +import { OPACITY_ON_LOAD } from "../../Layout/animations"; +import { TiWarning } from "react-icons/ti"; +import ReactQuill from "react-quill"; +import ChipSelector from "../../Components/ChipSelector/ChipSelector"; +import { motion } from "framer-motion"; +import Loader01 from "../../Components/Loaders/Loader01"; +import Header from "../../Components/Header"; +import ToastBox from "../../Components/ToastBox"; + +const EditUseCase = () => { + const { id } = useParams(); + const toast = useToast(); + const navigate = useNavigate(); + const [updateBlog] = useUpdateUsecaseMutation(); + const { data, error, isLoading } = useGetUsecaseByIdQuery(id); + const blog = data?.data; + const [isLoading01, setIsLoading01] = useState(false); + const [selectedImage, setSelectedImage] = useState(fallbackImageLarge); + const [selectedImageLarge, setSelectedImageLarge] = + useState(fallbackImageLarge); + const [largeImageData, setLargeImageData] = useState(null); + const [smallImageData, setSmallImageData] = useState(null); + const [chips, setChips] = useState(); + const [metaDescription, setMetaDescription] = useState(""); + + const handleDescriptionChange = (e) => { + setMetaDescription(e.target.value); + }; + + const [valueQuill, setValueQuill] = useState(blog?.content); + + const { + register, + handleSubmit, + reset, + formState: { errors }, + setValue, + } = useForm({ + resolver: yupResolver(editUsecase), + defaultValues: { + title: blog?.title, + meta_description: blog?.meta_description, + content: blog?.content, + // banner_image: null, + // icon: null, + // attachment: null, + }, + }); + + useEffect(() => { + if (data?.data) { + setSelectedImage(`https://rubix.betadelivery.com/${blog?.icon}`); + setSelectedImageLarge( + `https://rubix.betadelivery.com/${blog?.bannerImage}` + ); + setValue("meta_description", blog?.meta_description); + setValue("title", blog?.title); + setValue("content", blog?.content); + setValue("attachment", blog?.attachment); + setValueQuill(blog?.content); + } + }, [data, blog, setValue]); + + const onSubmit = async (data) => { + console.log(data); + const formData = new FormData(); + formData.append("meta_description", data.meta_description); + formData.append("title", data.title); + formData.append("category", data.category); + formData.append("summary", data.summary); + formData.append("content", valueQuill); // Add the content to formData + if (data?.banner_image[0] || selectedImageLarge !== fallbackImageLarge) { + formData.append("banner_image", data.banner_image[0]); + } + if (data?.icon[0]) { + formData.append("icon", data.icon[0]); + } + if(data?.attachment !== blog?.attachment){ + Array.from(data?.attachment).forEach((file, index) => { + formData.append(`attachment`, file); + })} + + + try { + setIsLoading01(true); + updateBlog({ id: id, data: formData }) + .then((response) => { + // Handle the response here + console.log("Mutation response:", response?.data?.statusCode); + console.log("Mutation response:", response?.data?.message); + console.log(response); + + if (response?.data?.statusCode === 200) { + setIsLoading01(false); + toast({ + render: () => ( + + ), + }); + reset(); + navigate("/usecase"); + }else if(response?.error?.status === 500){ + setIsLoading01(false); + toast({ + render: () => ( + + ), + }); + + } + }) + .catch((error) => { + // Handle errors + console.error("Error creating community:", error); + setIsLoading01(false); + // Handle error notification if needed + }); + } catch (error) { + // Handle errors + console.error("Error creating community:", error); + } + }; + + const handleImageChange = (e) => { + const file = e.target.files[0]; + setSmallImageData(file); + if (file) { + const reader = new FileReader(); + reader.onloadend = () => { + setSelectedImage(reader.result); + }; + reader.readAsDataURL(file); + } + }; + + const handleImageChangeLarge = (e) => { + const file = e.target.files[0]; + setLargeImageData(file); + console.log(largeImageData); + if (file) { + const reader = new FileReader(); + reader.onloadend = () => { + setSelectedImageLarge(reader.result); + }; + reader.readAsDataURL(file); + } + }; + + if (isLoading) { + return ; + } + return ( + + + + + + Usecase Image + + + Below is the profile that will be displayed on the community page. + + + + + {selectedImageLarge === fallbackImage || largeImageData === null ? ( + "" + ) : ( + + {largeImageData?.name} + + {(largeImageData?.size / (1024 * 1024)).toFixed(2)} mb + + + )} + setSelectedImageLarge(fallbackImageLarge)} + backgroundColor="red.400" + color={"whitesmoke"} + transition={"0.5s"} + _hover={{ + backgroundColor: "red.500", + }} + size="xs" + > + Remove + + + + + + + + Icon Image + + + Below is the profile that will be displayed on the community page. + + + + {selectedImage === fallbackImage || smallImageData === null ? ( + "" + ) : ( + + {smallImageData?.name} + + {(smallImageData?.size / (1024 * 1024)).toFixed(2)} mb + + + )} + setSelectedImage(fallbackImageLarge)} + backgroundColor="red.400" + color={"whitesmoke"} + transition={"0.5s"} + _hover={{ + backgroundColor: "red.500", + }} + size="xs" + > + Remove + + + + + + + + Title + + + {errors.title && ( + + {errors.title.message} + + )} + + + + + Description + + 160} + size="sm" + /> + + 160 + ? "red" + : metaDescription.length > 100 + ? "crimson" + : "" + } + fontWeight={metaDescription.length > 160 ? "bold" : ""} + className="web-text-small" + > + If discription crosses 160 characters it will cause problem in SEO + optimisation.you have entered {metaDescription.length} characters + + + {errors.meta_description && ( + + {" "} + {errors.meta_description.message} + + )} + + + + + Banner image + + {/* */} + + + + + + + + Drop images here + + + or click to upload + + + + + + + + + {errors.banner_image && ( + + {" "} + {errors.banner_image.message} + + )} + + Maximum limit of image is 5mb. + + + + + + + + Icon image + + {/* */} + + + + + + + + Drop images here + + + or click to upload + + + + + + + + + {errors.icon && ( + + {errors.icon.message} + + )} + + Maximum limit of image is 5mb. + + + + + + Content + + + + Please share proper linked in link here. + + + + + + Document + + + {errors.attachment && ( + + {" "} + {errors.attachment.message} + + )} + + + + } + color={"whitesmoke"} + backgroundColor={"purple.900"} + _hover={{ + backgroundColor: "purple.800", + }} + type="submit" + size="sm" + rounded={"sm"} + > + Create + + + + + + ); +}; + +export default EditUseCase; diff --git a/src/Pages/Usecase/Usecase.jsx b/src/Pages/Usecase/Usecase.jsx index a297513..a880b53 100644 --- a/src/Pages/Usecase/Usecase.jsx +++ b/src/Pages/Usecase/Usecase.jsx @@ -137,6 +137,8 @@ const Usecase = () => { const extractedArray = filteredData?.map((item, index) => { return { Title: ( + + { /> {item?.title} + ), // Title: {item?.title}, Discription: ( diff --git a/src/Pages/Usecase/ViewUseCase.jsx b/src/Pages/Usecase/ViewUseCase.jsx new file mode 100644 index 0000000..ad02535 --- /dev/null +++ b/src/Pages/Usecase/ViewUseCase.jsx @@ -0,0 +1,163 @@ +import { Box, Divider, Image, Tag, Text, useToast } from "@chakra-ui/react"; +import React from "react"; +import Header from "../../Components/Header"; +import { OPACITY_ON_LOAD } from "../../Layout/animations"; +import { + useGetUsecaseByIdQuery, +} from "../../Services/api.service"; +import { useNavigate, useParams } from "react-router-dom"; +import FullscreenLoaders from "../../Components/Loaders/FullscreenLoaders"; +import { formatDate } from "../../Components/Functions/UTCConvertor"; + +const ViewUseCase = () => { + const { id } = useParams(); + const toast = useToast(); + const navigate = useNavigate(); + const { data, error, isLoading } = useGetUsecaseByIdQuery(id); + const usecase = data?.data; + + if (isLoading) { + return ; + } + + + return ( + + + + + + + + + + + + Icon image + + + Below is the profile that will be displayed on the community page. + + + + + + + + Usecase banner image + + + Below is the profile that will be displayed on the community page. + + + + + + + + + + + + + + + + Status + + {usecase?.status ? ( + + Active + + ) : ( + + Inactive + + )} + + + + Title + {usecase?.title} + + + + + Usecase description + + + {usecase?.meta_description} + + + + + + Content + + + + + + + + + Created at + + + {formatDate(usecase?.createdAt)} + + + + + + Updated at + + + {formatDate(usecase?.updatedAt)} + + + + + + + + ); +}; + +export default ViewUseCase; diff --git a/src/Pages/Whitepapers/EditWhitepaper.jsx b/src/Pages/Whitepapers/EditWhitepaper.jsx index 8894ede..8081e16 100644 --- a/src/Pages/Whitepapers/EditWhitepaper.jsx +++ b/src/Pages/Whitepapers/EditWhitepaper.jsx @@ -54,7 +54,6 @@ const EditWhitepaper = () => { defaultValues: { title: "", image: null, - document: null, }, }); @@ -82,16 +81,20 @@ const EditWhitepaper = () => { }; const onSubmit = async (data) => { + console.log(data); setIsLoadingEdit(true); const form = new FormData(); form.append("title", data?.title); if (data.document[0]) { form.append("document", data.document[0]); } - if (data?.image === data?.data?.image) { - form.append("image"); + if (data?.image[0]) { + form.append("image", data?.image[0]); } - +// Log formData entries +for (let [key, value] of form.entries()) { + console.log(`${key}: ${value}`); +} await updateWhitepaper({ id: id, data: form }) .then((response) => { diff --git a/src/Routes/Routes.js b/src/Routes/Routes.js index 6a48e45..d26e324 100644 --- a/src/Routes/Routes.js +++ b/src/Routes/Routes.js @@ -52,6 +52,8 @@ import EcoBannerView from "../Pages/Banners/EcoBanner/EcoBannerView"; import EcoBannerEdit from "../Pages/Banners/EcoBanner/EcoBannerEdit"; import Usecase from "../Pages/Usecase/Usecase"; import AddUseCase from "../Pages/Usecase/AddUseCase"; +import ViewUseCase from "../Pages/Usecase/ViewUseCase"; +import EditUseCase from "../Pages/Usecase/EditUseCase"; export const RouteLink = [ { path: "/", Component: UnderConstruction }, @@ -146,6 +148,6 @@ export const RouteLink = [ // =============[ useCase ]================ { path: "/usecase", Component: Usecase }, { path: "/usecase/add-usecase", Component: AddUseCase }, - { path: "/usecase/view/:id", Component: UnderConstruction }, - { path: "/usecase/edit/:id", Component: UnderConstruction }, + { path: "/usecase/view/:id", Component: ViewUseCase }, + { path: "/usecase/edit/:id", Component: EditUseCase }, ]; diff --git a/src/Validations/Validations.js b/src/Validations/Validations.js index f91184d..f692c4c 100644 --- a/src/Validations/Validations.js +++ b/src/Validations/Validations.js @@ -290,11 +290,11 @@ export const addWhitePapers = Yup.object().shape({ // }) .optional(), document: Yup.mixed() - .test("required", "You need to provide a file", (files) => { - // return file && file.size <-- u can use this if you don't want to allow empty files to be uploaded; - if (files) return true; - return false; - }) + // .test("required", "You need to provide a file", (files) => { + // // return file && file.size <-- u can use this if you don't want to allow empty files to be uploaded; + // if (files) return true; + // return false; + // }) .test( "fileSize", " The maximum size of profile picture is 15MB.", @@ -376,10 +376,11 @@ export const addVideos = Yup.object().shape({ export const addUsecase = Yup.object().shape({ title: Yup.string().required("Name is required"), meta_description: Yup.string().required("Description is required"), - content: Yup.string(), + attachment: Yup.string().required("Attachment required"), + content: Yup.string().required("Content is required"), banner_image: Yup .mixed() - .required("Thumbnail is required") + // .required("Thumbnail is required") .test("required", "You need to provide a file", (files) => { // return file && file.size <-- u can use this if you don't want to allow empty files to be uploaded; if (files) return true; @@ -399,10 +400,10 @@ export const addUsecase = Yup.object().shape({ return false; } } - ), + ).optional(), icon: Yup .mixed() - .required("Icon is required") + // .required("Icon is required") .test("required", "You need to provide a file", (files) => { if (files) return true; return false; @@ -420,7 +421,61 @@ export const addUsecase = Yup.object().shape({ return false; } } - ), + ).optional(), }); + +export const editUsecase = Yup.object().shape({ + title: Yup.string().required("Name is required"), + meta_description: Yup.string().required("Description is required"), + attachment: Yup.string(), + content: Yup.string(), + banner_image: Yup + .mixed() + // .required("Thumbnail is required") + .test("required", "You need to provide a file", (files) => { + // return file && file.size <-- u can use this if you don't want to allow empty files to be uploaded; + if (files) return true; + return false; + }) + .test( + "fileSize", + " The maximum size of profile picture is 15MB.", + (files) => { + //if u want to allow only certain file sizes + try { + if (files.length !== 0) { + return files[0].size <= 15000000; + } + return true; + } catch (error) { + return false; + } + } + ).optional(), + icon: Yup + .mixed() + // .required("Icon is required") + .test("required", "You need to provide a file", (files) => { + if (files) return true; + return false; + }) + .test( + "fileSize", + " The maximum size of profile picture is 15MB.", + (files) => { + try { + if (files.length !== 0) { + return files[0].size <= 15000000; + } + return true; + } catch (error) { + return false; + } + } + ).optional(), + +}); + +