diff --git a/frontend/package.json b/frontend/package.json index fd51a960..e481ae99 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,6 +16,7 @@ "joi-browser": "^13.4.0", "jwt-decode": "^3.1.2", "mdbreact": "^5.0.1", + "moment": "^2.30.1", "node-sass": "^4.14.1", "prop-types": "^15.7.2", "react": "^17.0.1", diff --git a/frontend/src/pages/Admin/Components/Broadcast/AddBroadcasts/AddBroadcasts.jsx b/frontend/src/pages/Admin/Components/Broadcast/AddBroadcasts/AddBroadcasts.jsx index 23239deb..56c81267 100644 --- a/frontend/src/pages/Admin/Components/Broadcast/AddBroadcasts/AddBroadcasts.jsx +++ b/frontend/src/pages/Admin/Components/Broadcast/AddBroadcasts/AddBroadcasts.jsx @@ -1,11 +1,11 @@ -import React, { useRef, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import SunEditor from "suneditor-react"; import "suneditor/dist/css/suneditor.min.css"; import styles from "./add-broadcasts.module.scss"; import Joi from "joi-browser"; import { Button2 } from "../../../../../components/util/Button/index"; -import { formatTag } from '../../../../../components/util/Tags'; -import Loader from "../../../../../components/util/Loader/index"; +import { formatTag } from "../../../../../components/util/Tags"; +import Loader from "../../../../../components/util/Loader/index"; import { SimpleToast } from "../../../../../components/util/Toast/index"; import { postBoardcast } from "../../../../../service/Broadcast"; @@ -30,12 +30,13 @@ export function AddBroadcasts() { const [formData, setFormData] = useState(schema); const [errorObj, setErrorObj] = useState({}); const [isUploadingData, setIsUploadingData] = useState(false); + const [broadcastContent, setBroadcasetContent] = useState(""); const handleCloseToast = (event, reason) => { if (reason === "clickaway") { return; } setToast({ ...toast, toastStatus: false }); - } + }; const validationSchema = { title: Joi.string().required(), @@ -52,7 +53,7 @@ export function AddBroadcasts() { }); if (!check.error) return true; const errors = {}; - check.error.details.map(item => { + check.error.details.map((item) => { if (!errors[item.path[0]]) errors[item.path[0]] = item.message; return 0; }); @@ -60,7 +61,7 @@ export function AddBroadcasts() { return false; }; - const validateField = input => { + const validateField = (input) => { const { name, value } = input; const obj = { [name]: value }; const obj_schema = { [name]: validationSchema[name] }; @@ -69,7 +70,7 @@ export function AddBroadcasts() { return result.error ? result.error.details[0].message : null; }; - const handleChange = e => { + const handleChange = (e) => { const { currentTarget: input } = e; const errors = { ...errorObj }; const errorMessage = validateField(input); @@ -83,7 +84,7 @@ export function AddBroadcasts() { const addTag = () => { const tag = formatTag(tagRef.current.value.trim(), "Hyphens"); if (tag) { - setTags(prevTags => [...prevTags, tag]); + setTags((prevTags) => [...prevTags, tag]); setFormData({ ...formData, tags: [...formData.tags, tag] }); tagRef.current.value = ""; } @@ -91,185 +92,194 @@ export function AddBroadcasts() { const addImageUrl = () => { const url = imageRef.current.value; if (url.trim()) { - setImageUrls(prevUrl => [...prevUrl, url.trim()]); - setFormData({ ...formData, imageUrl: [...formData.imageUrl, url.trim()] }); + setImageUrls((prevUrl) => [...prevUrl, url.trim()]); + setFormData({ + ...formData, + imageUrl: [...formData.imageUrl, url.trim()], + }); imageRef.current.value = ""; } - } + }; - const removeTag = tag => { - setTags(tags.filter(t => t !== tag)); - setFormData({ ...formData, tags: formData.tags.filter(t => t !== tag) }); + const removeTag = (tag) => { + setTags(tags.filter((t) => t !== tag)); + setFormData({ ...formData, tags: formData.tags.filter((t) => t !== tag) }); + }; + const removeImageUrl = (url) => { + setImageUrls(imageUrls.filter((u) => u !== url)); + setFormData({ + ...formData, + imageUrl: formData.imageUrl.filter((u) => u !== url), + }); }; - const removeImageUrl = url => { - setImageUrls(imageUrls.filter(u => u !== url)); - setFormData({ ...formData, imageUrl: formData.imageUrl.filter(u => u !== url) }); - } async function uploadData(formData) { const response = await postBoardcast(formData, setToast, toast); - if(response) { - const schema = { - title: "", - content: "", - tags: [], - expiresOn: "dd-mm-yyyy", - imageUrl: [], - link: "", - }; - setTags([]) - setImageUrls([]) - setFormData(schema) - } + if (response) { + const schema = { + title: "", + content: "", + tags: [], + expiresOn: "dd-mm-yyyy", + imageUrl: [], + link: "", + }; + setTags([]); + setImageUrls([]); + setFormData(schema); + } } const onSubmit = async (e) => { e.preventDefault(); + setFormData({ ...formData, content: broadcastContent }); if (isFormValid()) { // TODO: send data to server - setIsUploadingData(true) + setIsUploadingData(true); await uploadData(formData); - setIsUploadingData(false) + setIsUploadingData(false); } }; - const onContentChange = content => { + const onContentChange = (content) => { let value = ""; if (content !== "

" && content !== "


") { value = content; } - handleChange({ currentTarget: { name: "content", value } }); + setBroadcasetContent(value); }; return (
- {toast.toastStatus && ( - - )} -
-
-
-

ADD BROADCAST

-
-
-
-
- - - {errorObj.title && ( -
{errorObj.title}
- )} + {toast.toastStatus && ( + + )} +
+ +
+

ADD BROADCAST

+
-
-
-
- - {errorObj.content && ( -
{errorObj.content}
- )} +
+
+ + + {errorObj.title && ( +
{errorObj.title}
+ )} +
-
-
-
- - {errorObj.expiresOn && ( -
{errorObj.expiresOn}
- )} +
+
+ + {errorObj.content && ( +
{errorObj.content}
+ )} +
-
-
-
-
- {imageUrls.map((tag, index) => ( - - ))} +
+
+ + {errorObj.expiresOn && ( +
{errorObj.expiresOn}
+ )}
- { - if (e.key === "Enter") { - addImageUrl(); - } - }} - placeholder="Enter Image url (Hit enter to add image url)" - /> -
-
-
- - - {errorObj.link && ( -
{errorObj.link}
- )} +
+
+ {imageUrls.map((tag, index) => ( + + ))} +
+ { + if (e.key === "Enter") { + addImageUrl(); + } + }} + placeholder="Enter Image url (Hit enter to add image url)" + /> + +
+
+
+
+ + + {errorObj.link && ( +
{errorObj.link}
+ )} +
-
-
-
-
- {tags.map((tag, index) => ( - - ))} +
+
+
+ {tags.map((tag, index) => ( + + ))} +
+ { + if (e.key === "Enter") { + addTag(); + } + }} + placeholder="Enter Tags (Hit enter to add tags)" + />
- { - if (e.key === "Enter") { - addTag(); - } - }} - placeholder="Enter Tags (Hit enter to add tags)" +
+
+ {isUploadingData ? : null} +
+
+
-
-
{isUploadingData?:null}
-
- -
- + +
-
); } @@ -288,5 +298,5 @@ const ImageUrl = ({ label, remove }) => { {label} x
- ) -} + ); +}; diff --git a/frontend/src/pages/Admin/Components/Broadcast/AddBroadcasts/add-broadcasts.module.scss b/frontend/src/pages/Admin/Components/Broadcast/AddBroadcasts/add-broadcasts.module.scss index 68e46618..9b99e38d 100644 --- a/frontend/src/pages/Admin/Components/Broadcast/AddBroadcasts/add-broadcasts.module.scss +++ b/frontend/src/pages/Admin/Components/Broadcast/AddBroadcasts/add-broadcasts.module.scss @@ -121,11 +121,13 @@ .tag { padding: 5px 10px; border-radius: 4px; - margin-right: 10px; background-color: #f5f5f5; color: #333; font-size: 14px; cursor: pointer; + width: 100%; + overflow: hidden; + margin: 2px; & .tag-remove { margin-left: 5px; @@ -221,4 +223,4 @@ height: 10px; justify-content: center; align-items: center; -} \ No newline at end of file +} diff --git a/frontend/src/pages/Admin/Components/Broadcast/ManageBroadcasts/Card/Card.jsx b/frontend/src/pages/Admin/Components/Broadcast/ManageBroadcasts/Card/Card.jsx index 1b47046f..6233701e 100644 --- a/frontend/src/pages/Admin/Components/Broadcast/ManageBroadcasts/Card/Card.jsx +++ b/frontend/src/pages/Admin/Components/Broadcast/ManageBroadcasts/Card/Card.jsx @@ -105,7 +105,6 @@ export function Card(props) {
-
{ + props.setIndex(props.index); + }} > diff --git a/frontend/src/pages/Admin/Components/Broadcast/ManageBroadcasts/ManageBroadcasts.jsx b/frontend/src/pages/Admin/Components/Broadcast/ManageBroadcasts/ManageBroadcasts.jsx index cc597290..eb9a1a33 100644 --- a/frontend/src/pages/Admin/Components/Broadcast/ManageBroadcasts/ManageBroadcasts.jsx +++ b/frontend/src/pages/Admin/Components/Broadcast/ManageBroadcasts/ManageBroadcasts.jsx @@ -12,7 +12,7 @@ import { customBoardcast } from "../../../../../service/Broadcast.jsx"; export function ManageBroadcasts() { const [array, setArray] = useState([]); - const [index, setIndex] = useState(0); + const [index, setIndex] = useState(""); const [visible, setVisible] = useState(false); const [tags, setTags] = useState(""); const [month, setMonth] = useState(""); @@ -21,6 +21,10 @@ export function ManageBroadcasts() { const [isLoaded, setLoaded] = useState(false); const [filterText, setFilterText] = useState(""); const [handleDelete, setHandleDelete] = useState(0); + useEffect(() => { + if (index === "") setVisible(false); + else setVisible(true); + }, [index]); const months = [ "January", "Febuary", @@ -85,7 +89,7 @@ export function ManageBroadcasts() { const result = await customBoardcast(api); setArray(result); setLoaded(true); - } + }; return (
handler(i)} + index={i} + setIndex={setIndex} handleDelete={handleDelete} setHandleDelete={setHandleDelete} /> diff --git a/frontend/src/pages/Broadcast/Component/AllBroadcasts/Edit/Edit.jsx b/frontend/src/pages/Broadcast/Component/AllBroadcasts/Edit/Edit.jsx index 2083b5c2..545884c9 100644 --- a/frontend/src/pages/Broadcast/Component/AllBroadcasts/Edit/Edit.jsx +++ b/frontend/src/pages/Broadcast/Component/AllBroadcasts/Edit/Edit.jsx @@ -1,79 +1,244 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, useRef } from "react"; +import SunEditor from "suneditor-react"; import style from "./edit.module.scss"; -import { TextField } from "@material-ui/core"; +import styles from "../../../../Admin/Components/Broadcast/AddBroadcasts/add-broadcasts.module.scss"; +import { formatTag } from "../../../../../components/util/Tags"; +import { SimpleToast } from "../../../../../components/util/Toast"; +import { UpdateBoardCast } from "../../../../../service/Broadcast"; import CloseIcon from "@material-ui/icons/Close"; +import moment from "moment"; export function Edit(props) { const [a, seta] = useState(); + const [broadcast, setBroadcast] = useState({}); + const [broadcastContent, setBroadcastContent] = useState(""); + const [tags, setTags] = useState([]); + const [imageUrls, setImageUrls] = useState([]); + const [isUploadingData, setIsUploadingData] = useState(false); + const [toast, setToast] = useState({ + toastStatus: false, + toastType: "", + toastMessage: "", + }); + const tagRef = useRef(); + const imageRef = useRef(); function scrolls() { let b = window.scrollY; seta(b); } + const onContentChange = (content) => { + let value = ""; + if (content !== "

" && content !== "


") { + value = content; + } + setBroadcastContent(value); + }; useEffect(() => { window.addEventListener("scroll", scrolls); }, []); + useEffect(() => { + setBroadcast(props?.data); + setBroadcastContent(props?.data?.content); + setImageUrls(props?.data?.imageUrl); + setTags(props?.data?.tags); + }, [props]); + + const handleChange = (e) => { + if (e.target.name === "expiresOn") + setBroadcast({ + ...broadcast, + [e.target.name]: new Date(e.target.value).toISOString(), + }); + else setBroadcast({ ...broadcast, [e.target.name]: e.target.value }); + }; + const addTag = () => { + const tag = formatTag(tagRef.current.value.trim(), "Hyphens"); + if (tag) { + setTags((prevTags) => [...prevTags, tag]); + setBroadcast({ ...broadcast, tags: [...broadcast.tags, tag] }); + tagRef.current.value = ""; + } + }; + const addImageUrl = () => { + const url = imageRef.current.value; + if (url.trim()) { + setImageUrls((prevUrl) => [...prevUrl, url.trim()]); + setBroadcast({ + ...broadcast, + imageUrl: [...broadcast.imageUrl, url.trim()], + }); + imageRef.current.value = ""; + } + }; + + const removeTag = (tag) => { + setTags(tags.filter((t) => t !== tag)); + setBroadcast({ + ...broadcast, + tags: broadcast.tags.filter((t) => t !== tag), + }); + }; + const removeImageUrl = (url) => { + setImageUrls(imageUrls.filter((u) => u !== url)); + setBroadcast({ + ...broadcast, + imageUrl: broadcast.imageUrl.filter((u) => u !== url), + }); + }; + const handleCloseToast = (event, reason) => { + if (reason === "clickaway") { + return; + } + setToast({ ...toast, toastStatus: false }); + }; + const handleUpdate = async () => { + setIsUploadingData(true); + const { _id, imageUrl, tags, title, link, expiresOn, isApproved } = + broadcast; + const response = await UpdateBoardCast( + { + id: _id, + imageUrl, + tags, + title, + link, + expiresOn, + content: broadcastContent, + isApproved, + }, + setToast, + toast + ); + if (response) { + setBroadcast({}); + setTags([]); + setImageUrls([]); + props.setVisible(false); + } + setIsUploadingData(false); + }; let dark = props.theme; return props.visible ? (
+ {toast.toastStatus && ( + + )}

Edit modal props.setVisible(false)} + onClick={() => { + setBroadcast({}); + props.setVisible(false); + }} />

-
-
-
Title:
- -
-
-
Description:
- -
-
-
Link:
- + { + e.preventDefault(); + handleUpdate(); + }} + > +
+
+ + +
+
+
+ +
+
+
+
+ +
+
+
+
+ {imageUrls?.map((tag, index) => ( + + ))} + { + if (e.key === "Enter") { + addImageUrl(); + } + }} + placeholder="Enter Image url (Hit enter to add image url)" + /> + +
+
+
+ + +
+
+
+
+
+
+ {tags?.map((tag, index) => ( + + ))} +
+ { + if (e.key === "Enter") { + addTag(); + } + }} + placeholder="Enter Tags (Hit enter to add tags)" + /> +
+
- @@ -81,3 +246,25 @@ export function Edit(props) {
) : null; } + +const Tag = ({ label, remove }) => { + return ( +
remove(label)}> + {label} + x +
+ ); +}; + +const ImageUrl = ({ label, remove }) => { + return ( +
remove(label)}> + {label} + x +
+ ); +}; + +const formartDate = (date) => { + return moment.utc(date).format("YYYY-MM-DD"); +}; diff --git a/frontend/src/pages/Broadcast/Component/AllBroadcasts/Edit/edit.module.scss b/frontend/src/pages/Broadcast/Component/AllBroadcasts/Edit/edit.module.scss index a1a39a74..ab7d6efe 100644 --- a/frontend/src/pages/Broadcast/Component/AllBroadcasts/Edit/edit.module.scss +++ b/frontend/src/pages/Broadcast/Component/AllBroadcasts/Edit/edit.module.scss @@ -19,6 +19,8 @@ border-radius: 8px; background: white; padding: 1em; + height: 100%; + overflow-y: scroll; @media (max-width: 600px) { width: 95%; }