diff --git a/package-lock.json b/package-lock.json index 3c07795..c1e3b2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7169,6 +7169,11 @@ } } }, + "goober": { + "version": "2.0.39", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.0.39.tgz", + "integrity": "sha512-ryw0VaZaehKmnjL4ZEJaiUVQc+XFa5dXIAbf2QC3F+WVKRbzaSuJyq7w28bdlwqYctiZ0Ok5QL/Pap5M2pCHQg==" + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -13544,6 +13549,24 @@ "prop-types": "^15.7.2" } }, + "react-error-boundary": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.3.tgz", + "integrity": "sha512-A+F9HHy9fvt9t8SNDlonq01prnU8AmkjvGKV4kk8seB9kU3xMEO8J/PQlLVmoOIDODl5U2kufSBs4vrWIqhsAA==", + "requires": { + "@babel/runtime": "^7.12.5" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", + "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + } + } + }, "react-error-overlay": { "version": "6.0.7", "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.7.tgz", @@ -13564,6 +13587,14 @@ "resolved": "https://registry.npmjs.org/react-flip-move/-/react-flip-move-3.0.4.tgz", "integrity": "sha512-HyUVv9g3t/BS7Yz9HgrtYSWyRNdR2F81nkj+C5iRY675AwlqCLB5JU9mnZWg0cdVz7IM4iquoyZx70vzZv3Z8Q==" }, + "react-hot-toast": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.0.0.tgz", + "integrity": "sha512-J0J2rcSvKetlziVquwESgk85pV9JB0Dz3RJIZcAEv7CWU2y2z8BQqxmZHZUxjPKIBGPqXAocZch4Kj4oUdX4+w==", + "requires": { + "goober": "^2.0.35" + } + }, "react-image-lightbox": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/react-image-lightbox/-/react-image-lightbox-5.1.1.tgz", diff --git a/package.json b/package.json index d54b5f9..5f2fd0b 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,9 @@ "react-cookies": "^0.1.1", "react-dom": "^16.13.1", "react-dropzone": "^11.0.1", + "react-error-boundary": "^3.1.3", "react-flip-move": "^3.0.4", + "react-hot-toast": "^2.0.0", "react-pose": "^4.0.10", "react-pose-text": "^3.1.0", "react-router-dom": "^5.1.2", diff --git a/src/components/alerts/confirm.jsx b/src/components/alerts/confirm.jsx new file mode 100644 index 0000000..174a4e6 --- /dev/null +++ b/src/components/alerts/confirm.jsx @@ -0,0 +1,25 @@ +import Swal from 'sweetalert2'; + +const Confirm = ( + title, + cb, + text = `You won't be able to revert this`, + icon = 'warning', + confirmBtnText = 'Save', +) => { + Swal.fire({ + title, + text, + icon, + showCancelButton: true, + confirmButtonColor: '#3085d6', + cancelButtonColor: '#d33', + confirmButtonText: confirmBtnText, + }).then((result) => { + if (result.isConfirmed) { + cb(true); + } + }); +}; + +export default Confirm; diff --git a/src/components/alerts/index.jsx b/src/components/alerts/index.jsx index b2d6631..4872f2b 100644 --- a/src/components/alerts/index.jsx +++ b/src/components/alerts/index.jsx @@ -3,5 +3,15 @@ import RequestStatus from './request'; import TimerAlert from './timer'; import HTMLAlert from './html'; import ChainInput from './chaining'; +import Confirm from './confirm'; +import Toast from './toast'; -export { NotifyAlert, RequestStatus, TimerAlert, HTMLAlert, ChainInput }; +export { + NotifyAlert, + RequestStatus, + TimerAlert, + HTMLAlert, + ChainInput, + Confirm, + Toast, +}; diff --git a/src/components/alerts/toast.jsx b/src/components/alerts/toast.jsx new file mode 100644 index 0000000..f5cab8e --- /dev/null +++ b/src/components/alerts/toast.jsx @@ -0,0 +1,21 @@ +import toast, { Toaster } from 'react-hot-toast'; + +// const Toast = (toastMessage, toastType='success') => { +// // toast[toastType](toastMessage); + +// toast('Here is your toast.'); +// }; + +import React from 'react'; + +const Toast = () => { + const notify = () => toast('Here is your toast.'); + return ( +
+ {notify()} + +
+ ); +}; + +export default Toast; diff --git a/src/components/inputs/image.jsx b/src/components/inputs/image.jsx index e2b337a..9bda396 100644 --- a/src/components/inputs/image.jsx +++ b/src/components/inputs/image.jsx @@ -43,7 +43,7 @@ const DropPicture = ({ defaultPicture }) => { try { const compressedFile = await imageCompression(acceptedFiles[0], options); formData.append('file', compressedFile); - const { data } = await http.post( + const { data } = await http.patch( `${apiUrl}/${endPoints.user.updateProfilePicture}`, formData, { @@ -78,7 +78,7 @@ const DropPicture = ({ defaultPicture }) => {
-
+

Upload your profile picture

diff --git a/src/components/utils/socialHandle.jsx b/src/components/utils/socialHandle.jsx index ef7ad61..004851c 100644 --- a/src/components/utils/socialHandle.jsx +++ b/src/components/utils/socialHandle.jsx @@ -4,7 +4,7 @@ import propTypes from 'prop-types'; const SocialHandle = ({ platform, iconClass }) => { return (
-
+
{platform}
diff --git a/src/config.json b/src/config.json index 84f97fe..1a41b44 100644 --- a/src/config.json +++ b/src/config.json @@ -1,28 +1,32 @@ { - "apiUrl": "http://localhost:5000", + "apiUrl": "https://yb-server.herokuapp.com", "endPoints": { "user": { "onboarding": { "login": "api/user/login", "signup": "api/user/signup" }, - "allUsers": "api/user/info/all", - "loggedInUser": "api/user/info", - "getClassStudents": "api/user/class/all", - "updateProfilePicture": "api/user/update/profile_picture" + "allUsers": "api/users/all", + "loggedInUser": "api/user", + "getClassStudents": "api/users/class", + "updateProfilePicture": "api/user/update-profile-picture", + "updateDetails": "api/user/update" }, "slamBook": { - "getUserAnswers": "api/user/answers", - "deleteAnswerById": "api/slambook/answer/delete", - "upsertAnswer": "api/slambook/answer/upsert", - "createQuestion": "api/slambook/question/new", - "allQuestions": "api/slambook/questions/all", - "getQuestionById": "api/slambook/question", - "deleteQuestionById": "api/slambook/question/delete" + "getUserAnswers": "api/answers", + "deleteAnswerById": "api/answer/delete", + "upsertAnswer": "api/answer/upsert", + "createQuestion": "api/question/new", + "allQuestions": "api/questions/all", + "getQuestionById": "api/question", + "deleteQuestionById": "api/question/delete" }, "messages": { - "forLoggedInUser": "api/user/messages", - "feed": "api/user/messages/all" + "forLoggedInUser": "api/messages", + "feed": "api/messages/all", + "new": "api/message/new", + "delete": "api/message/delete", + "deleteByMessageId": "api/message/delete-by-id" } }, "routes": { diff --git a/src/layouts/private/user/navbar.jsx b/src/layouts/private/user/navbar.jsx index 095fdde..374596e 100644 --- a/src/layouts/private/user/navbar.jsx +++ b/src/layouts/private/user/navbar.jsx @@ -39,10 +39,10 @@ const Navbar = () => { Home - Writes + Write Message - Polls + Moderation @@ -59,7 +59,7 @@ const Navbar = () => { Self Answers - Reset Password + Update Password diff --git a/src/pages/private/admin/manageQuestions.jsx b/src/pages/private/admin/manageQuestions.jsx index f10898f..f3b9269 100644 --- a/src/pages/private/admin/manageQuestions.jsx +++ b/src/pages/private/admin/manageQuestions.jsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import http from '../../../services/httpService'; -import { apiUrl, routes } from '../../../config.json'; +import { apiUrl, endPoints } from '../../../config.json'; import ListQuestions from './questions/listQuestion'; import { NotifyAlert } from '../../../components'; @@ -16,8 +16,9 @@ const ManageQuestions = () => { useEffect(() => { const fetchQuestions = async () => { try { - const { data } = await http.get(`${apiUrl}/api/admin/questions`); - console.log(data) + const { data } = await http.get( + `${apiUrl}/${endPoints.slamBook.allQuestions}`, + ); setQuestions(data); setNoQuestions(false); } catch (ex) {} @@ -47,11 +48,14 @@ const ManageQuestions = () => { return setInputValidationAlert(updatedInputValidation); } - const originalQuestions = questions; + const originalQuestions = [...questions]; try { - const { data } = await http.post(`${apiUrl}/api/admin/questions`, { - question: previousInputValue, - }); + const { data } = await http.post( + `${apiUrl}/${endPoints.slamBook.createQuestion}`, + { + title: previousInputValue, + }, + ); NotifyAlert('Successfully added the question', 'top'); setQuestions([data, ...questions]); setNoQuestions(false); diff --git a/src/pages/private/admin/questions/listQuestion.jsx b/src/pages/private/admin/questions/listQuestion.jsx index ba79e0f..c9b69cb 100644 --- a/src/pages/private/admin/questions/listQuestion.jsx +++ b/src/pages/private/admin/questions/listQuestion.jsx @@ -36,9 +36,7 @@ const ListQuestions = ({ onKeyDown={handleKeyPress} /> {inputValidationAlert.apply && ( - - {inputValidationAlert.message} - + {inputValidationAlert.message} )}
@@ -63,7 +61,7 @@ const ListQuestions = ({
diff --git a/src/pages/private/user/answers/box.jsx b/src/pages/private/user/answers/box.jsx index b46f7a7..44ed0ad 100644 --- a/src/pages/private/user/answers/box.jsx +++ b/src/pages/private/user/answers/box.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import propTypes from 'prop-types'; import SplitText from 'react-pose-text'; import Tooltip from '@material-ui/core/Tooltip'; @@ -13,6 +13,10 @@ import http from '../../../../services/httpService'; const AnswerBox = ({ question, questionId, answer, answerId }) => { const [CurrentAnswer, setCurrentAnswer] = useState(answer); + useEffect(() => { + setCurrentAnswer(answer); + }, [answer]); + const charPoses = { exit: { opacity: 0, y: 20 }, enter: { diff --git a/src/pages/private/user/answers/index.jsx b/src/pages/private/user/answers/index.jsx index 2cb973e..c56a550 100644 --- a/src/pages/private/user/answers/index.jsx +++ b/src/pages/private/user/answers/index.jsx @@ -11,7 +11,7 @@ const SelfAnswers = () => { const [totalQuestions, setTotalQuestions] = useState(0); // Total Number of Questions const [CurrentPage, setCurrentPage] = useState(1); // The current pagination page // eslint-disable-next-line no-unused-vars - const [postsPerPage, setpostsPerPage] = useState(1); // No. of posts per page + const [postsPerPage, setPostsPerPage] = useState(1); // No. of posts per page useEffect(() => { document.title = 'Self Questions'; @@ -35,10 +35,8 @@ const SelfAnswers = () => { }, []); const getAnswer = (questionId) => { - // console.log('Question ID is ', questionId); - const result = answeredQuestions.find((e) => e.questionId._id === questionId); - // console.log('Answer result is ', result); - return result ? { answer: result.answer, _id: result._id } : {}; + const result = answeredQuestions.find((e) => e.titleId === questionId); + return result ? { content: result.content, _id: result._id } : {}; }; const getTotalAnswersClass = () => { @@ -75,7 +73,7 @@ const SelfAnswers = () => { diff --git a/src/pages/private/user/index.jsx b/src/pages/private/user/index.jsx index 7358373..75d8610 100644 --- a/src/pages/private/user/index.jsx +++ b/src/pages/private/user/index.jsx @@ -6,6 +6,7 @@ import SelfAnswers from './answers'; import HomePage from './home'; import LogOut from './logout'; import ResetPassword from './resetPassword'; +import ModerateMessages from './moderation'; export { ListPolls, @@ -16,4 +17,5 @@ export { HomePage, LogOut, ResetPassword, + ModerateMessages, }; diff --git a/src/pages/private/user/messages/index.jsx b/src/pages/private/user/messages/index.jsx index e86058c..d415461 100644 --- a/src/pages/private/user/messages/index.jsx +++ b/src/pages/private/user/messages/index.jsx @@ -18,27 +18,22 @@ class PeopleCards extends Component { sections: [], persons: [], people: [], + isModalOpen: false, }; // eslint-disable-next-line react/sort-comp async componentDidMount() { const { data: persons } = await http.get(`${apiUrl}/${endPoints.user.allUsers}`); - - let departments = persons.map((e) => { - return e.deptSection.department; - }); - let sections = persons.map((e) => { - return e.deptSection.section; - }); - departments.sort(); - departments = ['ALL', ...new Set(departments)]; - sections.sort(); - sections = ['ALL', ...new Set(sections)]; + const departments = ['ALL', ...new Set(persons.map((e) => e.department).sort())]; + const sections = ['ALL', ...new Set(persons.map((e) => e.section).sort())]; this.setState({ persons, sections, departments, - people: persons, + people: + persons && persons.length > 0 + ? persons.sort((a, b) => a.userId - b.userId) + : persons, ProgressBar: !this.state.ProgressBar, }); } @@ -51,9 +46,7 @@ class PeopleCards extends Component { filterPeople = (e) => { const people = this.state.persons.filter( (person) => - person.credentials.name - .toLowerCase() - .search(e.target.value.trim().toLowerCase()) !== -1, + person.name.toLowerCase().search(e.target.value.trim().toLowerCase()) !== -1, ); this.setState({ people, NoSearchResults: !people.length }); }; @@ -65,7 +58,7 @@ class PeopleCards extends Component { return this.setState({ people: persons.filter((e) => { - return e.deptSection.section === sectionSelect; + return e.section === sectionSelect; }), departmentSelect: input.value, }); @@ -74,12 +67,9 @@ class PeopleCards extends Component { return this.setState({ people: persons.filter((e) => { if (sectionSelect !== 'ALL') { - return ( - e.deptSection.department === input.value && - e.deptSection.section === sectionSelect - ); + return e.department === input.value && e.section === sectionSelect; } - return e.deptSection.department === input.value; + return e.department === input.value; }), departmentSelect: input.value, }); @@ -92,7 +82,7 @@ class PeopleCards extends Component { return this.setState({ people: persons.filter((e) => { - return e.deptSection.department === departmentSelect; + return e.department === departmentSelect; }), sectionSelect: input.value, }); @@ -101,25 +91,21 @@ class PeopleCards extends Component { return this.setState({ people: persons.filter((e) => { if (departmentSelect !== 'ALL') { - return ( - e.deptSection.section === input.value && - e.deptSection.department === departmentSelect - ); + return e.section === input.value && e.department === departmentSelect; } - return e.deptSection.section === input.value; + return e.section === input.value; }), sectionSelect: input.value, }); }; + handleModalOpen = (isModalOpen) => { + this.setState({ ...this.state, isModalOpen }); + }; + render() { - const { - ProgressBar, - departments, - sections, - people, - NoSearchResults, - } = this.state; + const { ProgressBar, departments, sections, people, NoSearchResults } = + this.state; return ( <> @@ -162,10 +148,11 @@ class PeopleCards extends Component {
diff --git a/src/pages/private/user/messages/modal.jsx b/src/pages/private/user/messages/modal.jsx index ba60039..7871f60 100644 --- a/src/pages/private/user/messages/modal.jsx +++ b/src/pages/private/user/messages/modal.jsx @@ -2,62 +2,50 @@ import React, { useState, useEffect } from 'react'; import propTypes from 'prop-types'; import { MDBContainer, - MDBBtn, MDBModal, MDBModalBody, MDBModalHeader, MDBModalFooter, - MDBRating, } from 'mdbreact'; -import { apiUrl } from '../../../../config.json'; +import toast, { Toaster } from 'react-hot-toast'; +import { apiUrl, endPoints } from '../../../../config.json'; import http from '../../../../services/httpService'; import { NotifyAlert, TimerAlert } from '../../../../components'; -const ModalBox = ({ personId, personName, toggleOpen, triggerModal }) => { - const [ModalValue, setModalValue] = useState(''); - const [basic] = useState([ - { - tooltip: '1/5', - }, - { - tooltip: '2/5', - }, - { - tooltip: '3/5', - }, - { - tooltip: '4/5', - }, - { - tooltip: '5/5', - }, - ]); +const ModalBox = ({ + personId, + personName, + toggleOpen, + triggerModal, + modalValue, + isAnonymousMessage, +}) => { + const [ModalValue, setModalValue] = useState(() => modalValue); + const [isAnonymous, setIsAnonymous] = useState(() => isAnonymousMessage); + + console.log('isAnonymousMessage...', isAnonymousMessage); useEffect(() => { - const getUserMessage = async () => { - try { - const { data } = await http.get(`${apiUrl}/api/user/messages/${personId}`); - setModalValue(data.message); - } catch (ex) { - if (ex.response && ex.response.status === 404) { - // TimerAlert('Error', ex.response.data, 'error'); - } - } - }; - getUserMessage(); - }, [personId]); + setModalValue(modalValue); + }, [modalValue]); + + // useEffect(() => { + // setIsAnonymous(); + // }, [isAnonymous]) const handleSubmit = () => { const messageObject = { - message: ModalValue, - sendTo: personId, + content: ModalValue, + receiverId: personId, + isAnonymous, }; const submitData = async () => { try { const { data } = await http.put( - `${apiUrl}/api/user/messages`, + `${apiUrl}/${endPoints.messages.new}`, messageObject, ); + console.log('data...', data); setModalValue(data.message); TimerAlert('Message sent successfully'); triggerModal(personId); @@ -68,10 +56,12 @@ const ModalBox = ({ personId, personName, toggleOpen, triggerModal }) => { submitData(); }; + // TODO: Implement handle delete. const handleDelete = () => {}; return ( + triggerModal(personId)}> {`You're here for : ${personName}`} @@ -79,27 +69,30 @@ const ModalBox = ({ personId, personName, toggleOpen, triggerModal }) => {
-

- Write a nice message for {personName} :) -

+

Write a nice message for {personName} :)