Commit b350ec31 by jaymehta

permissions

1 parent 7cbeb538
...@@ -6,13 +6,14 @@ import { useDispatch, useSelector } from "react-redux"; ...@@ -6,13 +6,14 @@ import { useDispatch, useSelector } from "react-redux";
import { cleanImage } from "../../services/imageHandling"; import { cleanImage } from "../../services/imageHandling";
import { Button, Container, Form, Nav, Navbar } from "react-bootstrap"; import { Button, Container, Form, Nav, Navbar } from "react-bootstrap";
import { loadUser } from "../../redux/actions/userActions"; import { loadUser } from "../../redux/actions/userActions";
import { useRouter } from "next/router";
const Header = () => { const Header = () => {
const { user, error } = useSelector(state => state.loadedUser); const { user, error } = useSelector(state => state.loadedUser);
const dispatch = useDispatch(); const dispatch = useDispatch();
// console.log("user", user); // console.log("user", user);
const [isSticky, setIsSticky] = useState(false); const [isSticky, setIsSticky] = useState(false);
const router = useRouter();
useEffect(() => { useEffect(() => {
const handleScroll = () => { const handleScroll = () => {
// Check if the scroll position is greater than a certain threshold // Check if the scroll position is greater than a certain threshold
...@@ -66,8 +67,10 @@ const Header = () => { ...@@ -66,8 +67,10 @@ const Header = () => {
</div> </div>
<p>{user.phone}</p> <p>{user.phone}</p>
<Button <Button
onClick={() => { onClick={async () => {
signOut({ redirect: false }); signOut({ redirect: false });
await router.push("/")
window.location.reload()
}} }}
className="me-3" className="me-3"
variant="primary" variant="primary"
...@@ -77,10 +80,14 @@ const Header = () => { ...@@ -77,10 +80,14 @@ const Header = () => {
</div> </div>
) : ( ) : (
<div> <div>
<Button className="me-3" variant="primary"> <Button onClick={()=> {
router.push("/signup/user")
}} className="me-3" variant="primary">
Sign Up Sign Up
</Button> </Button>
<Button className="" variant="primary"> <Button onClick={()=> {
router.push("/login/user")
}} className="" variant="primary">
Log In Log In
</Button> </Button>
</div> </div>
......
...@@ -5,7 +5,7 @@ import Footer from "./Footer"; ...@@ -5,7 +5,7 @@ import Footer from "./Footer";
import { ToastContainer } from "react-toastify"; import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css"; import "react-toastify/dist/ReactToastify.css";
import { loadUser } from "../../redux/actions/userActions"; import { loadUser } from "../../redux/actions/userActions";
import { useDispatch } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
const Layout = ({ children, title = "Zango", description = "" }) => { const Layout = ({ children, title = "Zango", description = "" }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
......
import React, { useState, useRef } from "react"; import React, { useState, useRef, useEffect } from "react";
import { Formik } from "formik"; import { Formik } from "formik";
import Link from "next/link"; import Link from "next/link";
import { Fragment } from "react"; import { Fragment } from "react";
...@@ -18,14 +18,12 @@ import { Loader } from "react-bootstrap-typeahead"; ...@@ -18,14 +18,12 @@ import { Loader } from "react-bootstrap-typeahead";
const Signup = props => { const Signup = props => {
console.log(props.type); console.log(props.type);
const router = useRouter();
const [otp, setOtp] = useState(new Array(4).fill("")); const [otp, setOtp] = useState(new Array(4).fill(""));
const [isOtpSent, setOtpSent] = useState(false); const [isOtpSent, setOtpSent] = useState(false);
const [otpVerified, setOtpVerified] = useState(false); const [otpVerified, setOtpVerified] = useState(false);
const [loading, setLoading] = useState(); const [loading, setLoading] = useState();
const dispatch = useDispatch(); const dispatch = useDispatch();
const router = useRouter()
const otpValue = useRef(); const otpValue = useRef();
const changeOtpRef = value => { const changeOtpRef = value => {
console.log(otpValue); console.log(otpValue);
...@@ -76,7 +74,6 @@ const Signup = props => { ...@@ -76,7 +74,6 @@ const Signup = props => {
} }
}; };
// console.log("otp", otp);
return ( return (
<Fragment> <Fragment>
...@@ -252,7 +249,7 @@ const Signup = props => { ...@@ -252,7 +249,7 @@ const Signup = props => {
)} )}
<div className="input-group mb-0"> <div className="input-group mb-0">
<Button type="submit" className="btn btn-primary btn-submit" disabled={(!values.termsConditions && !isValid) || loading}> <Button type="submit" className="btn btn-primary btn-submit" disabled={(!values.termsConditions && !isValid) || loading}>
{loading ? <Loader/> : `${isOtpSent ? "Verify OTP" : "Sign Up Now"}`} {loading ? <Loader /> : `${isOtpSent ? "Verify OTP" : "Sign Up Now"}`}
</Button> </Button>
</div> </div>
</Form> </Form>
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
"react-icons": "^5.0.1", "react-icons": "^5.0.1",
"react-image-gallery": "^1.3.0", "react-image-gallery": "^1.3.0",
"react-js-pagination": "^3.0.3", "react-js-pagination": "^3.0.3",
"react-loading-icons": "^1.1.0",
"react-multi-carousel": "^2.8.2", "react-multi-carousel": "^2.8.2",
"react-otp-input": "^3.1.1", "react-otp-input": "^3.1.1",
"react-owl-carousel": "^2.3.3", "react-owl-carousel": "^2.3.3",
......
...@@ -21,17 +21,16 @@ export default function BusinessDetailsPage () { ...@@ -21,17 +21,16 @@ export default function BusinessDetailsPage () {
); );
}; };
/** For server side rendering */ /** For server side rendering */
export const getServerSideProps = wrapper.getServerSideProps(store => async ({ req, query }) => { export const getServerSideProps = wrapper.getServerSideProps(store => async ({ req, query }) => {
// Get the menu data. // Get the menu data.
// get the locations data. // get the locations data.
// await store.dispatch(getVendorDetails()) await store.dispatch(loadUser());
return { return {
props: {}, props: {}
}; };
}); });
\ No newline at end of file \ No newline at end of file
import Image from "next/image"; import Image from "next/image";
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import Sidebar from "../../../components/layout/VendorDashboardSidebar"; import Sidebar from "../../../components/layout/VendorDashboardSidebar";
import Layout from "../../../components/layout/Layout"; import Layout from "../../../components/layout/Layout";
import { Button } from "react-bootstrap"; import { Button } from "react-bootstrap";
import { FaPlus } from "react-icons/fa"; import { FaPlus } from "react-icons/fa";
import { useDispatch, useSelector } from "react-redux";
import { loadUser } from "../../../redux/actions/userActions";
import { wrapper } from "../../../redux/store";
import { useRouter } from "next/router";
const VendorDashboard = () => { const VendorDashboard = () => {
const { user, error } = useSelector(state => state.loadedUser);
const router = useRouter();
console.log("user", user);
const [collapsed, setCollapsed] = useState(false);
const [collapsed, setCollapsed] = useState(false); const toggleSidebar = () => {
setCollapsed(!collapsed);
};
const toggleSidebar = () => { const ApprovalStatus = () => {
setCollapsed(!collapsed); if (user) {
}; switch (user.approved) {
case "approved":
return <></>;
return ( case "rejected":
<Layout> return (
<div className="sidebarContainer"> <>
<Sidebar collapsed={collapsed} toggleSidebar={toggleSidebar} /> <div class="alert alert-danger" role="alert">
<div className="content"> Your profile has been rejected! Please contact the admin for more details!
<div className="row"> </div>
<div className="col-12 offset-lg-2 col-lg-8"> </>
<div className="infoSent"> );
<div className="bgCircleBlue">
<Image alt="" src="/images/vendor/icon-tick.svg" width="15" height="10" />
</div>
<div className="px-3">
<p className="p1">Business information sent successfully.</p>
<p className="p2">Kindly wait until we verify the details. You can start adding activities once your account is verified.</p>
</div>
<div>
<Image alt="" src="/images/vendor/icon-close.svg" width="14" height="14" />
</div>
</div>
</div>
<div className="d-flex justify-content-center py-4"> case "pending":
<span className="image-container"> return (
<Image alt="" layout="fill" src="/images/vendor/Isolation_Mode.png" className="image" /> <>
</span> <div className="col-12 offset-lg-2 col-lg-8 ">
</div> <div className="alert alert-danger alert-dismissible fade show text-center" role="alert">
<div className="text-center py-2 mb-5"> {/* <div className="bgCircleBlue">
<p className="p3">No information is available right now</p> <Image alt="" src="/images/vendor/icon-tick.svg" width="15" height="10" />
<Button type="button" variant="" className="btnAdd" disabled> </div> */}
<span className="image-container me-2"> <div className="text-center">
<Image alt="" layout="fill" src="/images/vendor/icon-plus.svg" width="14" height="14" className="image" /> <p className="p1 text-center">Business information sent successfully.</p>
</span> <p className="p2 text-center">Kindly wait until we verify the details. You can start adding activities once your account is verified.</p>
{/* <FaPlus className="me-2" /> */} </div>
<span>Add Activity</span> {/* <button type="button" className="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> */}
</Button>
<Button type="button" variant="" className="btnAdd">
<span className="image-container me-2">
<Image alt="" layout="fill" src="/images/vendor/icon-plus.svg" width="14" height="14" className="image" />
</span>
{/* <FaPlus className="me-2" /> */}
<span>Add Activity</span>
</Button>
</div>
</div>
</div> </div>
{/* <div className="infoSent">
<div className="bgCircleBlue">
<Image alt="" src="/images/vendor/icon-tick.svg" width="15" height="10" />
</div>
<div className="px-3">
<p className="p1">Business information sent successfully.</p>
<p className="p2">Kindly wait until we verify the details. You can start adding activities once your account is verified.</p>
</div>
<div>
<Image alt="" src="/images/vendor/icon-close.svg" width="14" height="14" />
</div>
</div> */}
</div>
</>
);
case "none":
return <></>;
default:
break;
}
}
};
return (
<Layout>
<div className="sidebarContainer">
<Sidebar collapsed={collapsed} toggleSidebar={toggleSidebar} />
<div className="content">
<div className="row">
<ApprovalStatus />
<div className="d-flex justify-content-center py-4">
<span className="image-container">
<Image alt="" layout="fill" src="/images/vendor/Isolation_Mode.png" className="image" />
</span>
</div>
<div className="text-center py-2 mb-5">
<p className="p3">No information is available right now</p>
<Button
onClick={() => {
router.push("/vendor/activity-details");
}}
type="button"
variant=""
className="btnAdd"
disabled={user?.approved != "approved"}
>
<span className="image-container me-2">
<Image alt="" layout="fill" src="/images/vendor/icon-plus.svg" width="14" height="14" className="image" />
</span>
{/* <FaPlus className="me-2" /> */}
<span>Add Activity</span>
</Button>
</div> </div>
</Layout> </div>
); </div>
</div>
</Layout>
);
}; };
export default VendorDashboard;
\ No newline at end of file \ No newline at end of file
export default VendorDashboard;
/** For server side rendering */
export const getServerSideProps = wrapper.getServerSideProps(store => async ({ req, query }) => {
// Get the menu data.
// get the locations data.
await store.dispatch(loadUser());
return {
props: {}
};
});
import axios from "axios";
import { getSession } from "next-auth/react";
import { CREATE_ACTIVITY_FAIL, CREATE_ACTIVITY_REQUEST, CREATE_ACTIVITY_SUCCESS } from "../constants/activitiesConstants";
export const createActivity = data => async dispatch => {
const session = await getSession();
try {
if (!session) {
return "You are not authenticated, please log in.";
}
dispatch({
type: CREATE_ACTIVITY_REQUEST,
loading: true
});
const config = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${session.jwt}`
}
};
let activityData = {
data: {
...data
}
};
const response = await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/experiences`);
dispatch({
type: CREATE_ACTIVITY_SUCCESS,
payload: response.data
});
return response.data;
} catch (error) {
dispatch({
type: CREATE_ACTIVITY_FAIL,
payload: error.response.data
});
}
};
...@@ -381,3 +381,26 @@ export const finishEndUserOtpVerification = async verificationData => { ...@@ -381,3 +381,26 @@ export const finishEndUserOtpVerification = async verificationData => {
return await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/end-users/finish-otp-verification`, verificationData, config); return await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/end-users/finish-otp-verification`, verificationData, config);
}; };
export const updateUserApprovalStatus = async ({ status }) => {
const session = await getSession();
if (!session) {
console.log("You are not authorized, please login");
}
const config = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${session.jwt}`
}
};
const response = await axios.put(
`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/users/${session.id}`,
{
approved: status
},
config
);
return response;
};
export const CREATE_ACTIVITY_REQUEST = "CREATE_ACTIVITY_REQUEST"
export const CREATE_ACTIVITY_SUCCESS = "CREATE_ACTIVITY_SUCCESS"
export const CREATE_ACTIVITY_FAIL = "CREATE_ACTIVITY_FAIL"
export const CLEAR_ERRORS = "CLEAR_ERRORS";
\ No newline at end of file \ No newline at end of file
import { CREATE_ACTIVITY_FAIL, CREATE_ACTIVITY_REQUEST, CREATE_ACTIVITY_SUCCESS } from "../constants/activitiesConstants";
import { CLEAR_ERRORS } from "../constants/vendorConstants";
export const createActivityReducer = (state = {}, action) => {
switch (action.type) {
case CREATE_ACTIVITY_REQUEST:
return { loading: true };
case CREATE_ACTIVITY_SUCCESS:
return {
loading: false,
activityData: action.payload
};
case CREATE_ACTIVITY_FAIL:
return {
loading: false,
error: action.payload.error.message
};
case CLEAR_ERRORS:
return {
...state,
error: null
};
default:
return state;
}
};
\ No newline at end of file \ No newline at end of file
...@@ -5,6 +5,7 @@ import { authReducer, forgotPasswordReducer, loadedUserReducer, resetPasswordRed ...@@ -5,6 +5,7 @@ import { authReducer, forgotPasswordReducer, loadedUserReducer, resetPasswordRed
import { enquiryReducer } from "./enquiryReducer"; import { enquiryReducer } from "./enquiryReducer";
import { displayEnquireNowReducer } from "./enquireNowModalReducer"; import { displayEnquireNowReducer } from "./enquireNowModalReducer";
import { getVendorDetailsReducer, loggedInVendorReducer, updateVendorReducer } from "./vendorReducers"; import { getVendorDetailsReducer, loggedInVendorReducer, updateVendorReducer } from "./vendorReducers";
import { createActivityReducer } from "./activitiesReducer";
const reducers = combineReducers({ const reducers = combineReducers({
townships: townshipsReducer, townships: townshipsReducer,
...@@ -22,6 +23,7 @@ const reducers = combineReducers({ ...@@ -22,6 +23,7 @@ const reducers = combineReducers({
loggedInVendor: loggedInVendorReducer, loggedInVendor: loggedInVendorReducer,
updatedVendorData: updateVendorReducer, updatedVendorData: updateVendorReducer,
vendorDetails: getVendorDetailsReducer, vendorDetails: getVendorDetailsReducer,
activityData: createActivityReducer,
}); });
export default reducers; export default reducers;
...@@ -2271,7 +2271,12 @@ footer hr { ...@@ -2271,7 +2271,12 @@ footer hr {
padding-right: 1rem; padding-right: 1rem;
} }
input:disabled {
cursor: not-allowed;
background-color: -internal-light-dark(rgba(239, 239, 239, 0.3), rgba(59, 59, 59, 0.3)) !important;
color: -internal-light-dark(rgb(84, 84, 84), rgb(170, 170, 170)) !important;
border-color: rgba(118, 118, 118, 0.3) !important;
}
@media (min-width: 992px) { @media (min-width: 992px) {
.navbar-expand-lg .navbar-nav .nav-link { .navbar-expand-lg .navbar-nav .nav-link {
......
...@@ -4030,6 +4030,11 @@ ...@@ -4030,6 +4030,11 @@
"resolved" "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz" "resolved" "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz"
"version" "3.0.4" "version" "3.0.4"
"react-loading-icons@^1.1.0":
"integrity" "sha512-Y9eZ6HAufmUd8DIQd6rFrx5Bt/oDlTM9Nsjvf8YpajTa3dI8cLNU8jUN5z7KTANU+Yd6/KJuBjxVlrU2dMw33g=="
"resolved" "https://registry.npmjs.org/react-loading-icons/-/react-loading-icons-1.1.0.tgz"
"version" "1.1.0"
"react-modal@^3.8.1": "react-modal@^3.8.1":
"integrity" "sha512-duB9bxOaYg7Zt6TMFldIFxQRtSP+Dg3F1ZX3FXxSUn+3tZZ/9JCgeAQKDg7rhZSAqopq8TFRw3yIbnx77gyFTw==" "integrity" "sha512-duB9bxOaYg7Zt6TMFldIFxQRtSP+Dg3F1ZX3FXxSUn+3tZZ/9JCgeAQKDg7rhZSAqopq8TFRw3yIbnx77gyFTw=="
"resolved" "https://registry.npmjs.org/react-modal/-/react-modal-3.15.1.tgz" "resolved" "https://registry.npmjs.org/react-modal/-/react-modal-3.15.1.tgz"
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!