diff --git a/package-lock.json b/package-lock.json index 159d1760..0fda9dba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6830,19 +6830,6 @@ "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" }, - "history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", - "requires": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" - } - }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -11960,6 +11947,21 @@ "react-is": "^16.6.0", "tiny-invariant": "^1.0.2", "tiny-warning": "^1.0.0" + }, + "dependencies": { + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + } } }, "react-router-dom": { @@ -11974,6 +11976,21 @@ "react-router": "5.2.0", "tiny-invariant": "^1.0.2", "tiny-warning": "^1.0.0" + }, + "dependencies": { + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + } } }, "react-scripts": { @@ -12074,6 +12091,14 @@ "tslib": "^1.0.0" } }, + "react-switch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-switch/-/react-switch-5.0.1.tgz", + "integrity": "sha512-Pa5kvqRfX85QUCK1Jv0rxyeElbC3aNpCP5hV0LoJpU/Y6kydf0t4kRriQ6ZYA4kxWwAYk/cH51T4/sPzV9mCgQ==", + "requires": { + "prop-types": "^15.6.2" + } + }, "react-toastify": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-6.0.5.tgz", diff --git a/package.json b/package.json index 92342149..e686835f 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "react-cookies": "^0.1.1", "react-dom": "^16.12.0", "react-dropzone": "^11.0.1", - "react-icons": "^3.9.0", + "react-icons": "^3.10.0", "react-images": "^1.1.7", "react-lottie": "^1.2.3", "react-markdown-editor-lite": "^1.1.4", @@ -32,6 +32,7 @@ "react-router-dom": "^5.1.2", "react-scripts": "^3.4.0", "react-spinners": "^0.8.3", + "react-switch": "^5.0.1", "react-toastify": "^6.0.5", "redux": "^4.0.5", "redux-thunk": "^2.3.0", diff --git a/src/actions/adminAction.js b/src/actions/adminAction.js index 1504e9eb..6a15219c 100644 --- a/src/actions/adminAction.js +++ b/src/actions/adminAction.js @@ -40,6 +40,9 @@ export const loginAdmin = (adminInfo, history) => async (dispatch) => { localStorage.setItem('userId', decodedData._id) dispatch(setCurrentUser(decodedData)); + // update localStorage with admin status + localStorage.setItem('admin', true) + dispatch({ type: SET_ADMIN, payload: true diff --git a/src/actions/authAction.js b/src/actions/authAction.js index 543bb639..28687947 100644 --- a/src/actions/authAction.js +++ b/src/actions/authAction.js @@ -1,4 +1,4 @@ -import { SET_CURRENT_USER, GET_USER_PROFILE, PASSWORD_SUCCESSFULLY_CHANGED, PASSWORD_CHANGE_REQUEST_SUCCESS } from './types'; +import { SET_CURRENT_USER, GET_USER_PROFILE, PASSWORD_SUCCESSFULLY_CHANGED, PASSWORD_CHANGE_REQUEST_SUCCESS, SET_ADMIN } from './types'; import axios from 'axios'; import { setAuthToken } from '../utils/setAuthToken'; import jwt_decode from 'jwt-decode'; @@ -46,8 +46,19 @@ export const loginUser = (userInfo, history) => async (dispatch) => { const decodedData = await jwt_decode(token); localStorage.setItem('userId', decodedData._id) dispatch(setCurrentUser(decodedData)); - history.push("/dashboard"); + // update user role in localStorage + localStorage.setItem('admin', res.data.user.isAdmin) + + // store orgId in localStorage + localStorage.setItem('orgId', res.data.user.orgId); + + // if user is admin update admin in store + dispatch({ + type: SET_ADMIN, + payload: res.data.user.isAdmin + }) + history.push("/dashboard"); } } catch(error) { dispatch(errorHandler(error)); @@ -104,10 +115,10 @@ export const logoutUser = () => async (dispatch) => { // clear token from backend const res = await axios.post('/user/logout') if (res.status === 200) { - // remove token from the localStorage - localStorage.removeItem('jwtToken'); - // remove userID - localStorage.removeItem('userId') + // remove all keys from the localStorage except the orgId + const orgId = localStorage.getItem('orgId'); + localStorage.clear() + localStorage.setItem('orgId', orgId) // delete authorization from the header setAuthToken(false); // set user to {} diff --git a/src/actions/eventAction.js b/src/actions/eventAction.js index 5aa603a6..d680979b 100644 --- a/src/actions/eventAction.js +++ b/src/actions/eventAction.js @@ -80,4 +80,19 @@ export const getEventById = (eventId) => async (dispatch) => { } catch(error) { dispatch(errorHandler(error)) } +} + +// RSVP FOR EVENT SECTION +export const rsvpYes = (eventId, info) => async (dispatch) => { + try { + const res = await axios.patch(`/event/rsvp/${eventId}`, info); + dispatch(setRequestStatus(false)) + if(res.status === 200) { + dispatch(setRequestStatus(true)); + console.log('Doing rsvp for the event', res.data); + dispatch(getAllEvents()); + } + } catch (error) { + dispatch(errorHandler(error)) + } } \ No newline at end of file diff --git a/src/actions/orgAction.js b/src/actions/orgAction.js index 15a44800..c6470903 100644 --- a/src/actions/orgAction.js +++ b/src/actions/orgAction.js @@ -1,7 +1,7 @@ import axios from 'axios' import { setRequestStatus } from '../utils/setRequestStatus' import { errorHandler } from '../utils/errorHandler' -import { GET_ORG_PROFILE, UPDATE_ORG_PROFILE, DEACTIVATE_ORG, GET_ALL_MEMBERS } from './types' +import { GET_ORG_PROFILE, UPDATE_ORG_PROFILE, DEACTIVATE_ORG, GET_ALL_MEMBERS, TRIGGER_MAINTENANCE } from './types' // CREATE COMMUNITY export const registerCommunity = (orgInfo) => async (dispatch) => { @@ -120,4 +120,24 @@ export const deactivateOrg = () => async (dispatch) => { } catch(error) { dispatch(errorHandler(error)) } +} + +// TRIGGER MAINTENANCE MODE +export const TriggerMaintenance = () => async (dispatch) => { + try { + const orgId = localStorage.getItem('orgId') + const res = await axios.patch(`/org/${orgId}/maintenance`); + dispatch(setRequestStatus(false)) + if(res.status === 200) { + dispatch(setRequestStatus(true)) + // set maintenance to true in localStorage + localStorage.setItem('isMaintenance', res.data.maintenance); + dispatch({ + type: TRIGGER_MAINTENANCE, + payload: res.data.maintenance + }) + } + } catch (error) { + dispatch(errorHandler(error)) + } } \ No newline at end of file diff --git a/src/actions/postAction.js b/src/actions/postAction.js index f5b56f8c..83820d5d 100644 --- a/src/actions/postAction.js +++ b/src/actions/postAction.js @@ -37,4 +37,19 @@ export const getAllPinnedPosts = (pagination = 10, page = 1) => async (dispatch) } catch(error) { dispatch(errorHandler(error)) } -} \ No newline at end of file +} + +// UPVOTE POST +export const upVotePost = (postId) => async (dispatch) => { + try { + const res = await axios.patch(`/post/upvote/${postId}`) + dispatch(setRequestStatus(false)); + if(res.status === 200) { + dispatch(setRequestStatus(true)); + console.log('successfully upvoted post ', res.data) + dispatch(getAllPosts()); + } + } catch (error) { + dispatch(errorHandler(error)) + } +} diff --git a/src/actions/types.js b/src/actions/types.js index 8f945bdc..989dd57c 100644 --- a/src/actions/types.js +++ b/src/actions/types.js @@ -39,8 +39,8 @@ export const GET_EVENT_BY_ID = "GET_EVENT_BY_ID"; export const GET_ADMIN = "GET_ADMIN"; export const GET_COMMENTS_OF_A_POST = "GET_COMMENTS_OF_A_POST"; export const GET_SINGLE_PROJECT = "GET_SINGLE_PROJECT"; -export const PASSWORD_CHANGE_REQUEST_SUCCESS = - "PASSWORD_CHANGE_REQUEST_SUCCESS"; +export const PASSWORD_CHANGE_REQUEST_SUCCESS = "PASSWORD_CHANGE_REQUEST_SUCCESS"; export const PASSWORD_SUCCESSFULLY_CHANGED = "PASSWORD_SUCCESSFULLY_CHANGED"; export const GET_INVITE_LINK = "GET_INVITE_LINK"; export const PROCESS_INVITE_LINK = "PROCESS_INVITE_LINK"; +export const TRIGGER_MAINTENANCE = "TRIGGER_MAINTENANCE"; diff --git a/src/actions/usersAction.js b/src/actions/usersAction.js index 14fbe450..0e2c456a 100644 --- a/src/actions/usersAction.js +++ b/src/actions/usersAction.js @@ -1,4 +1,4 @@ -import { GET_USER_PROFILE, GET_ALL_MEMBERS, UPDATE_USER_PROFILE, GET_USER_EVENTS, GET_USER_PROJECTS, GET_USER_POSTS, GET_INVITE_LINK, PROCESS_INVITE_LINK } from './types' +import { GET_USER_PROFILE, GET_ALL_MEMBERS, UPDATE_USER_PROFILE, GET_USER_EVENTS, GET_USER_PROJECTS, GET_USER_POSTS, GET_INVITE_LINK, PROCESS_INVITE_LINK, SET_ADMIN } from './types' import { errorHandler } from '../utils/errorHandler' import axios from 'axios' import { setRequestStatus } from '../utils/setRequestStatus' @@ -15,6 +15,13 @@ export const getProfile = () => async (dispatch)=> { type: GET_USER_PROFILE, payload: res.data.user }) + // if user is admin + if(res.data.user.isAdmin === true) { + dispatch({ + type: SET_ADMIN, + payload: true + }) + } } } catch(error) { dispatch(errorHandler(error)) @@ -160,9 +167,9 @@ export const getPostsCreatedByUser = (pagination = 10, page = 1) => async (dispa } // GET INVITE LINK -export const getInviteLink = () => async (dispatch) => { +export const getInviteLink = (role) => async (dispatch) => { try { - const res = await axios.get('/user/invite') + const res = await axios.get(`/user/invite?role=${role}`) dispatch(setRequestStatus(false)); if(res.status === 200) { dispatch(setRequestStatus(true)); @@ -187,7 +194,7 @@ export const processInviteToken = (token) => async (dispatch) => { console.log('Processing the invite link ', res.data); dispatch({ type: PROCESS_INVITE_LINK, - payload: res.data.success || res.data.msg + payload: res.data.redirectTo || res.data.msg }) } } catch(error) { diff --git a/src/auth/login-form/login-form.scss b/src/auth/login-form/login-form.scss index ecdb7cf0..f5748c6c 100644 --- a/src/auth/login-form/login-form.scss +++ b/src/auth/login-form/login-form.scss @@ -2,7 +2,8 @@ padding: 15px 0; .form-group { label { - color: #00abff; + color: #1a73e8; + font-family: Inter; } } .cta-login { @@ -11,8 +12,9 @@ justify-content: center; margin-top: 30px; button { - padding: 8px 10px; - border-radius: 30px; + width: 104px; + background-color: #1a73e8; + // border-radius: 30px; } } } @@ -22,6 +24,7 @@ align-items: center; justify-content: center; margin-top: 10px; + color: #1a73e8; } #validation_msg { color: rgb(247, 134, 134); @@ -30,7 +33,7 @@ .loginbtn { border: 1px solid rgb(211, 220, 228); - border-radius: 3px; + // border-radius: 3px; width: 45%; } diff --git a/src/auth/login/login.js b/src/auth/login/login.js index 036c1070..dd068a8f 100644 --- a/src/auth/login/login.js +++ b/src/auth/login/login.js @@ -4,6 +4,8 @@ import LoginForm from "../login-form/login-form"; import SignUpForm from "../signup-form/signup-form"; import { DonutTitle } from "../../donutTitle/donutTitle"; import multipleDonuts from "../../images/extra-donuts.png"; +import GoogleLogin from '../../images/icons8-google-48.png' +import { FaGoogle, FaGithub } from 'react-icons/fa' import "./login.scss"; class Login extends Component { @@ -55,40 +57,24 @@ class Login extends Component { ? "Or Sign In with" : "Or SignUp with"}
-
{this.state.activeForm === "login"
? "Don't have an account? "
diff --git a/src/auth/login/login.scss b/src/auth/login/login.scss
index 97cc8757..7a53aac1 100644
--- a/src/auth/login/login.scss
+++ b/src/auth/login/login.scss
@@ -35,6 +35,7 @@
font-size: 20px;
font-weight: normal;
padding-right: 30px;
+ font-family: "Inter";
}
}
.user-details {
@@ -44,6 +45,7 @@
box-shadow: 0 8px 20px 0 rgba(0, 0, 0, 0.1);
min-height: 380px;
height: auto;
+ font-family: "Inter";
}
}
@media (min-width: 320px) and (max-width: 640px) {
@@ -74,7 +76,7 @@
}
.form-header {
- font-family: Playfair Display;
+ font-family: "Playfair Display";
font-style: normal;
font-weight: bold;
font-size: 34px;
@@ -98,7 +100,23 @@
text-align: center;
margin: 0 auto;
.selectorbtn {
+ font-family: "Inter";
border: 1px solid rgb(211, 220, 228);
width: 55%;
+ background-color: #1a73e8;
+ width: 104px;
+ height: 38px;
}
}
+
+.login__options {
+ display: flex;
+ justify-content: space-around;
+ .google__login {
+ height: 30px;
+ }
+ .github__login {
+ height: 30px;
+ width: 30px;
+ }
+}
\ No newline at end of file
diff --git a/src/auth/signup-form/signup-form.js b/src/auth/signup-form/signup-form.js
index 85843061..666848aa 100644
--- a/src/auth/signup-form/signup-form.js
+++ b/src/auth/signup-form/signup-form.js
@@ -28,7 +28,7 @@ class SignUpForm extends Component {
}
componentWillReceiveProps(nextProps) {
- if (nextProps.error?.msg.length > 0) {
+ if (nextProps.error?.msg?.length > 0) {
this.setState({
error: {
msg: "Something went wrong, Please recheck the input!",
diff --git a/src/auth/signup-form/signup-form.scss b/src/auth/signup-form/signup-form.scss
index a163a26f..439031de 100644
--- a/src/auth/signup-form/signup-form.scss
+++ b/src/auth/signup-form/signup-form.scss
@@ -1,8 +1,10 @@
.signup-details {
padding: 15px 0;
+ font-family: "Inter";
.form-group {
label {
- color: #00abff;
+ color: #1a73e8;
+ font-family: "Inter";
}
}
.cta-signup {
@@ -11,8 +13,12 @@
justify-content: center;
margin-top: 30px;
button {
- padding: 8px 10px;
- border-radius: 30px;
+ // padding: 8px 10px;
+ width: 104px;
+ height: 38px;
+ background-color: #1a73e8;
+ // border-radius: 30px;
+
}
}
.savebtn {
@@ -35,10 +41,11 @@
border: 1px solid rgb(211, 220, 228);
border-radius: 3px;
width: 45%;
+ background-color: #1a73e8;
}
.signupbtn-text {
- font-family: Inter;
+ font-family: "Inter";
font-style: normal;
font-size: 16px;
diff --git a/src/common/AdminRoute.js b/src/common/AdminRoute.js
new file mode 100644
index 00000000..3731f0ac
--- /dev/null
+++ b/src/common/AdminRoute.js
@@ -0,0 +1,44 @@
+import React, { useState, useEffect } from 'react'
+import PropTypes from 'prop-types';
+import { Route, Redirect } from 'react-router-dom';
+import { connect } from 'react-redux';
+
+function AdminRoute(props) {
+ // const [mount, setMount] = useState(false);
+ const [returnedRoute, setReturnedRoute] = useState("")
+
+ useEffect(() => {
+ switch(props.role) {
+ case "admin": {
+ return setReturnedRoute(
+ props.auth.isAuthenticated && (
+ props.auth.isAdmin ||
+ props.user.userProfile.isAdmin ||
+ props.admin.isAdmin ) ? (
+