Commit eac818da by jaymehta

admin

1 parent 1f8452e1
import Image from "next/image"; import Image from "next/image";
import { Fragment } from "react" import { Fragment, useState } from "react";
import { Button, Modal } from "react-bootstrap"; import { Button, Modal } from "react-bootstrap";
import { Loader } from "react-bootstrap-typeahead";
import { toast } from "react-toastify";
import { updateActivityStatusAdmin } from "../../redux/actions/userActions";
const ActivityDetailsModal = ({ show, handleClose }) => { const ActivityDetailsModal = ({ show, handleClose, activityDetailInfo }) => {
return ( const [viewDesc, setViewDesc] = useState();
<Fragment> const [rejectPopUp, setrejectPopUp] = useState(false);
<Modal show={show} onHide={handleClose} size="xl" aria-labelledby="contained-modal-title-vcenter" const [rejectionReasonText, setrejectionReasonText] = useState("");
centered>
<Modal.Body> console.log("activityDetailInfo", activityDetailInfo);
<div className="vendorDetails"> return (
<div className="row"> <Fragment>
<div className="col-12 col-lg-12"> <Modal show={show} onHide={handleClose} size="xl" aria-labelledby="contained-modal-title-vcenter" centered>
<div className="d-flex align-items-center justify-content-between mb-4"> <Modal.Body>
<h4 className="mb-0">Activity Details</h4> {activityDetailInfo[0] ? (
<span className="image-container" style={{ cursor: "pointer" }} onClick={handleClose}> <div className="vendorDetails">
<Image width={13} height={13} alt="" src="/images/admin/icon-close.svg" className="image" /> <div className="row">
</span> <div className="col-12 col-lg-12">
</div> <div className="d-flex align-items-center justify-content-between mb-4">
</div> <h4 className="mb-0">Activity Details</h4>
</div> <span className="image-container" style={{ cursor: "pointer" }} onClick={handleClose}>
<div className="row"> <Image width={13} height={13} alt="" src="/images/admin/icon-close.svg" className="image" />
<div className="col-12 col-lg-4 borderRight"> </span>
<p className="phead">Basic Details</p> </div>
<div className="row"> </div>
<p className="col-12 col-lg-6">Category</p> </div>
<p className="col-12 col-lg-6">Adventure</p> <div className="row">
</div> <div className="col-12 col-lg-4 borderRight">
<div className="row"> <p className="phead">Basic Details</p>
<p className="col-12 col-lg-6">SubCategory</p> <div className="row">
<p className="col-12 col-lg-6">Rooftop</p> <p className="col-12 col-lg-6">Category</p>
</div> <p className="col-12 col-lg-6">*FEATURE TO BE ADDED*</p>
<div className="row"> </div>
<p className="col-12 col-lg-6">Activity Name</p> <div className="row">
<p className="col-12 col-lg-6">Edge City Climb</p> <p className="col-12 col-lg-6">SubCategory</p>
</div> <p className="col-12 col-lg-6">{activityDetailInfo[0].attributes.subCategory.data.attributes.name}</p>
<div className="row"> </div>
<p className="col-12 col-lg-6">Activity Description</p> <div className="row">
<p className="col-12 col-lg-6 pview">View</p> <p className="col-12 col-lg-6">Activity Name</p>
</div> <p className="col-12 col-lg-6">{activityDetailInfo[0].attributes.name}</p>
<div className="row"> </div>
<p className="col-12 col-lg-6">Location</p> <div className="row">
<p className="col-12 col-lg-6">Chelsea</p> <p className="col-12 col-lg-6">Activity Description</p>
</div> <p
<div className="row"> className="col-12 col-lg-6 pview"
<p className="col-12 col-lg-6">Address</p> onClick={() => {
<p className="col-12 col-lg-6">30 Hudson Yards, New York, NY 10001</p> setViewDesc(true);
</div> }}
<div className="row"> >
<p className="col-12 col-lg-6">Activity Name</p> View
<p className="col-12 col-lg-6">Edge City Climb</p> </p>
</div> </div>
<div className="row"> <div className="row">
<p className="col-12 col-lg-6">Price (per person)</p> <p className="col-12 col-lg-6">Location</p>
<p className="col-12 col-lg-6">$185</p> <p className="col-12 col-lg-6">---|---</p>
</div> </div>
<div className="row"> <div className="row">
<p className="col-12 col-lg-6">Tags</p> <p className="col-12 col-lg-6">Address</p>
<p className="col-12 col-lg-6"></p> <p className="col-12 col-lg-6">{activityDetailInfo[0].attributes.address}</p>
</div> </div>
<div className="row"> {/* <div className="row">
<p className="col-12 col-lg-6">Place</p> <p className="col-12 col-lg-6">Activity Name</p>
<p className="col-12 col-lg-6">Outdoor</p> <p className="col-12 col-lg-6">Edge City Climb</p>
</div> </div> */}
<div className="row"> <div className="row">
<p className="col-12 col-lg-6">Gifting to someone</p> <p className="col-12 col-lg-6">Price (per person)</p>
<p className="col-12 col-lg-6">Disallowed</p> <p className="col-12 col-lg-6">$ {activityDetailInfo[0].attributes.pricePerPerson}</p>
</div> </div>
</div> <div className="row">
<div className="col-12 col-lg-4 borderRight ps-4"> <p className="col-12 col-lg-6">Tags</p>
<div> <p className="col-12 col-lg-6"></p>
<p className="phead">Group Information</p> </div>
<div className="row"> <div className="row">
<p className="col-12 col-lg-6">Contact Person for the activity</p> <p className="col-12 col-lg-6">Place</p>
<p className="col-12 col-lg-6">Arnav</p> <p className="col-12 col-lg-6">{activityDetailInfo[0].attributes.activityType}</p>
</div> </div>
<div className="row"> <div className="row">
<p className="col-12 col-lg-6">Size of the Group</p> <p className="col-12 col-lg-6">Gifting to someone</p>
<p className="col-12 col-lg-6">2</p> <p className="col-12 col-lg-6">{activityDetailInfo[0].attributes.giftSomeone ? "Allowed" : "Disallowed"}</p>
</div> </div>
</div> </div>
<div> <div className="col-12 col-lg-4 borderRight ps-4">
<p className="phead">Availability</p> <div>
<div className="row"> <p className="phead">Group Information</p>
<p className="col-12 col-lg-6">Months</p> <div className="row">
<p className="col-12 col-lg-6">February</p> <p className="col-12 col-lg-6">Contact Person for the activity</p>
</div> <p className="col-12 col-lg-6">{activityDetailInfo[0].attributes.contactPersonForBooking}</p>
<div className="row"> </div>
<p className="col-12 col-lg-6">Time</p> <div className="row">
<p className="col-12 col-lg-6">9:45am-10:00pm</p> <p className="col-12 col-lg-6">Size of the Group</p>
</div> <p className="col-12 col-lg-6">
<div className="row"> {activityDetailInfo[0].attributes.minGroupSize} - {activityDetailInfo[0].attributes.maxGroupSize}
<p className="col-12 col-lg-6">Duration</p> </p>
<p className="col-12 col-lg-6">2-3 hours</p> </div>
</div> </div>
<div className="row"> <div>
<p className="col-12 col-lg-6">Age Group</p> <p className="phead">Availability</p>
<p className="col-12 col-lg-6">13+</p> {/* <div className="row">
</div> <p className="col-12 col-lg-6">Months</p>
</div> <p className="col-12 col-lg-6">February</p>
</div> </div> */}
<div className="col-12 col-lg-4 ps-4"> <div className="row">
<div> <p className="col-12 col-lg-6">Time</p>
<p className="phead">Booking & Activity Information</p> {activityDetailInfo[0].attributes.fromTime && activityDetailInfo[0].attributes.toTime && (
<div className="row"> <p className="col-12 col-lg-6">{activityDetailInfo[0].attributes.fromTime - activityDetailInfo[0].attributes.toTime}</p>
<p className="col-12 col-lg-6">Link of Booking</p> )}
<p className="col-12 col-lg-6 pview">https://www.zango.com</p> </div>
</div> <div className="row">
<div className="row"> <p className="col-12 col-lg-6">Duration</p>
<p className="col-12 col-lg-6">Images of Activities</p> <p className="col-12 col-lg-6">{activityDetailInfo[0].attributes.duration}</p>
<p className="col-12 col-lg-6 pview">View Images</p> </div>
</div> <div className="row">
<div className="row"> <p className="col-12 col-lg-6">Age Group</p>
<p className="col-12 col-lg-6">Brand Logo</p> <p className="col-12 col-lg-6">{activityDetailInfo[0].attributes.ageLowerLimit}+</p>
<p className="col-12 col-lg-6 pview">View Logo</p> </div>
</div> </div>
</div> </div>
<div> <div className="col-12 col-lg-4 ps-4">
<p className="phead">Policy & Terms</p> <div>
<div className="row"> <p className="phead">Booking & Activity Information</p>
<p className="col-12 col-lg-6">Cancellation Policy</p> <div className="row">
<p className="col-12 col-lg-6 pview">View</p> <p className="col-12 col-lg-6">Link of Booking</p>
</div> <p className="col-12 col-lg-6 pview">{activityDetailInfo[0].attributes.link}</p>
<div className="row">
<p className="col-12 col-lg-6">Terms & Conditions</p>
<p className="col-12 col-lg-6 pview">View</p>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-12 col-lg-12">
<div className="d-flex justify-content-center">
<Button variant="" className="btnAdd btnApprove m-0" onClick={handleClose}>
Approve
</Button>
<div className="px-1"></div>
<Button variant="" className="btnAdd btnReject m-0" onClick={handleClose}>
Reject
</Button>
</div>
</div>
</div>
</div> </div>
</Modal.Body>
</Modal>
</Fragment>
)
}
export default ActivityDetailsModal;
\ No newline at end of file \ No newline at end of file
<div className="row">
<p className="col-12 col-lg-6">Images of Activities</p>
<p className="col-12 col-lg-6 pview">View Images</p>
</div>
<div className="row">
<p className="col-12 col-lg-6">Brand Logo</p>
<p className="col-12 col-lg-6 pview">View Logo</p>
</div>
</div>
<div>
<p className="phead">Policy & Terms</p>
<div className="row">
<p className="col-12 col-lg-6">Cancellation Policy</p>
<p className="col-12 col-lg-6 pview">View</p>
</div>
<div className="row">
<p className="col-12 col-lg-6">Terms & Conditions</p>
<p className="col-12 col-lg-6 pview">View</p>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-12 col-lg-12">
<div className="d-flex justify-content-center">
<Button
variant=""
className="btnAdd btnApprove m-0"
onClick={async () => {
await updateActivityStatusAdmin({ status: true, activityId: activityDetailInfo[0].id, rejectionReason: "" });
toast.success("Activity approved.");
}}
>
Approve
</Button>
<div className="px-1"></div>
<Button
variant=""
className="btnAdd btnReject m-0"
onClick={async () => {
// setrejectionId()
setrejectPopUp(true);
// await updateActivityStatusAdmin({ status: false, activityId: activityDetailInfo[0].id, rejectionReason: "" });
}}
>
Reject
</Button>
</div>
</div>
</div>
</div>
) : (
<div className="text-center my-5 p-5">
<Loader />
</div>
)}
</Modal.Body>
</Modal>
<Modal show={viewDesc} onHide={() => setViewDesc(false)}>
<Modal.Header closeButton>Activity description</Modal.Header>
<Modal.Body>{activityDetailInfo[0].attributes.description}</Modal.Body>
</Modal>
<Modal
show={rejectPopUp}
onHide={() => {
// setrejectionId(null);
setrejectPopUp(false);
}}
>
<Modal.Header closeButton>Please mention reason for rejecting the activity.</Modal.Header>
<Modal.Body>
<div className="input-group">
<textarea
style={{ width: "100%" }}
rows={4}
className="p-2"
placeholder="Eg: Not appropriate for this age group."
name="comments"
onChange={e => {
e.preventDefault();
setrejectionReasonText(e.target.value);
}}
/>
</div>
<div className="my-4">
<div className="d-flex justify-content-center">
<Button
variant=""
className="btnAdd btnApprove m-0"
disabled={rejectionReasonText == ""}
onClick={async () => {
await updateActivityStatusAdmin({ status: false, activityId: activityDetailInfo[0].id, rejectionReason: rejectionReasonText });
// setrejectionId(null);
setrejectPopUp(false);
toast.success("Activity rejected.");
}}
>
Submit
</Button>
</div>
</div>
</Modal.Body>
</Modal>
</Fragment>
);
};
export default ActivityDetailsModal;
import { Fragment, useState } from "react"; import { SearchOutlined } from "@ant-design/icons";
import { Button, Image, Table } from "react-bootstrap"; import { Button, Input, Space, Table } from "antd";
import { Fragment, useEffect, useRef, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getActivitiesForAdmin } from "../../redux/actions/activityAction";
const ActivityListing = () => { const ActivityListing = () => {
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9]; const dispatch = useDispatch();
const [showMenuIndex, setShowMenuIndex] = useState(null); const { allActivitiesData } = useSelector(state => state.allActivitiesData);
useEffect(() => {
dispatch(getActivitiesForAdmin({}));
}, []);
console.log("allActivitiesData", allActivitiesData);
const [showMenuIndex, setShowMenuIndex] = useState(null);
const [data, setdata] = useState(null);
const toggleMenu = (index) => { const toggleMenu = index => {
setShowMenuIndex(index === showMenuIndex ? null : index); setShowMenuIndex(index === showMenuIndex ? null : index);
}; };
return ( useEffect(() => {
<Fragment> let allActivities = allActivitiesData && allActivitiesData.data.map(item => {
<div className="row"> return {
<div className="col-12 col-lg-12"> key: item.id,
<div className="rightContent"> name: item.attributes.name,
<div className="d-flex align-items-center justify-content-between px-2 mb-2"> category: "yet to map",
<div> pincode: item.attributes.masterPincode.data.attributes.name,
<h2>Activities</h2> price: item.attributes.pricePerPerson,
<p>View all the Activities</p> activityType: item.attributes.activityType,
</div> gift: item.attributes.giftSomeone ? "Allowed" : "Not allowed",
<div> vendorWebsite: item.attributes.link
<Button type="button" variant="" className="btnAdd m-0"> }
<Image alt="" width="16" height="16" src="/images/vendor/icon-filter.svg" className="me-2" /> Filter })
</Button>
</div> setdata(allActivities)
</div> }, [allActivitiesData]);
<Table responsive className="listingTable">
<thead> const [searchText, setSearchText] = useState("");
<tr> const [searchedColumn, setSearchedColumn] = useState("");
<th> const searchInput = useRef(null);
<label className="check-container mb-0 ps-2" htmlFor="checkh"> const handleSearch = (selectedKeys, confirm, dataIndex) => {
<input confirm();
type="checkbox" setSearchText(selectedKeys[0]);
id="checkh" setSearchedColumn(dataIndex);
className="check-box" };
/> const handleReset = clearFilters => {
<span className="checkmark"></span> clearFilters();
</label> setSearchText("");
</th> };
<th>Category</th> const getColumnSearchProps = dataIndex => ({
<th>Name</th> filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters, close }) => (
<th>Location</th> <div
<th>Price</th> style={{
<th>Place</th> padding: 8
<th>Gift</th> }}
<th>Vendor Website</th> onKeyDown={e => e.stopPropagation()}
<th></th> >
<th></th> <Input
</tr> ref={searchInput}
</thead> placeholder={`Search ${dataIndex}`}
<tbody> value={selectedKeys[0]}
{array.map((data, index) => ( onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
<tr key={index}> onPressEnter={() => handleSearch(selectedKeys, confirm, dataIndex)}
<td> style={{
<label className="check-container mb-0 ps-2" htmlFor={`check${index}`}> marginBottom: 8,
<input display: "block"
type="checkbox" }}
id={`check${index}`} />
className="check-box" <Space>
/> <Button
<span className="checkmark"></span> type="primary"
</label> onClick={() => handleSearch(selectedKeys, confirm, dataIndex)}
</td> icon={<SearchOutlined />}
<td><span>Adventure</span></td> size="small"
<td>Ice-Skating in NY</td> style={{
<td>North Avenue</td> width: 90
<td>$ 479</td> }}
<td>Outdoor</td> >
<td>Allowed</td> Search
<td><span style={{ color: "#0070BD", marginRight: ".5rem" }}>View Link</span> <Image alt="" width={17} height={17} src="/images/admin/icon-link.svg" /></td> </Button>
<td><Image alt="" width={20} height={20} src="/images/vendor/icon-view.svg" /></td> <Button
<td> onClick={() => clearFilters && handleReset(clearFilters)}
<div className="actions"> size="small"
<div className="ellipse" onClick={() => toggleMenu(index)}> style={{
<Image alt="" width={20} height={20} src="/images/vendor/icon-more-vertical.svg" /> width: 90
</div> }}
{showMenuIndex === index && ( >
<div className="menu"> Reset
<ul> </Button>
<li>Delete</li> <Button
</ul> type="link"
</div> size="small"
)} onClick={() => {
</div> confirm({
</td> closeDropdown: false
</tr> });
))} setSearchText(selectedKeys[0]);
<tr> setSearchedColumn(dataIndex);
<td colSpan={10}>Showing Results 10 of 1567</td> }}
</tr> >
</tbody> Filter
</Table> </Button>
</div> <Button
</div> type="link"
</div> size="small"
</Fragment> onClick={() => {
); close();
}}
>
close
</Button>
</Space>
</div>
),
filterIcon: filtered => (
<SearchOutlined
style={{
color: filtered ? "#1677ff" : undefined
}}
/>
),
onFilter: (value, record) => record[dataIndex].toString().toLowerCase().includes(value.toLowerCase()),
onFilterDropdownOpenChange: visible => {
if (visible) {
setTimeout(() => searchInput.current?.select(), 100);
}
},
render: text =>
searchedColumn === dataIndex ? (
<Highlighter
highlightStyle={{
backgroundColor: "#ffc069",
padding: 0
}}
searchWords={[searchText]}
autoEscape
textToHighlight={text ? text.toString() : ""}
/>
) : (
text
)
});
const columns = [
{
title: "Name",
dataIndex: "name",
key: "name",
width: "30%",
...getColumnSearchProps("name")
},
{
title: "Category",
dataIndex: "category",
key: "category",
width: "20%",
...getColumnSearchProps("category")
},
{
title: "Address",
dataIndex: "address",
key: "address",
...getColumnSearchProps("address"),
sorter: (a, b) => a.address.length - b.address.length,
sortDirections: ["descend", "ascend"]
}
];
return (
<Fragment>
<div className="row">
<Table columns={columns} dataSource={data} />
</div>
</Fragment>
);
}; };
export default ActivityListing; export default ActivityListing;
import { Formik } from "formik"; import { Formik } from "formik";
import { Fragment, useState } from "react"; import { Fragment, useState } from "react";
import { Button, Form, Modal } from "react-bootstrap"; import { Button, Form, Modal } from "react-bootstrap";
import { useDispatch } from "react-redux";
import ReactSelect from "react-select"; import ReactSelect from "react-select";
import * as Yup from "yup"; import * as Yup from "yup";
import { updateApprovalStatusAdmin } from "../../redux/actions/userActions";
import { getAllVendors } from "../../redux/actions/vendorActions";
const RejectModal = ({ show, handleClose }) => { const RejectModal = ({ show, handleClose, detail, setShowDetail }) => {
const formValidationSchema = Yup.object().shape({ const dispatch = useDispatch();
email: Yup.string().required("Email Id is Required").email("Please Enter An Valid Email Id"), console.log("detail", detail[0].attributes.email);
reason: Yup.string().required("Reason is Required"), const formValidationSchema = Yup.object().shape({
comments: Yup.string().required("Comment is Required"), email: Yup.string(),
}); reason: Yup.string().required("Reason is Required"),
comments: Yup.string()
});
const reasonOptions = [ const reasonOptions = [{ value: "Not listed", label: "Not listed" }];
{ value: "Not listed", label: "Not listed" } const [selectedOption, setSelectedOption] = useState(null);
] const [showComments, setshowComments] = useState(false);
const [selectedOption, setSelectedOption] = useState(null);
return ( return (
<Fragment> <Fragment>
<Modal show={show} onHide={handleClose} aria-labelledby="contained-modal-title-vcenter" <Modal show={show} onHide={handleClose} aria-labelledby="contained-modal-title-vcenter" centered>
centered> <Modal.Body>
<Modal.Body> <div className="row">
<div className="row"> <div className="col-12 col-lg-12">
<div className="col-12 col-lg-12"> <div className="px-3">
<div className="px-3"> <p className="mphead">Reject reason</p>
<p className="mphead">Reject reason</p> <div className="form-container">
<div className="form-container"> <Formik
<Formik initialValues={{
initialValues={{ email: detail[0].attributes.email,
email: "", reason: "",
reason: "", comments: ""
comments: "", }}
}} validationSchema={formValidationSchema}
validationSchema={formValidationSchema} onSubmit={async values => {
onSubmit={(values) => { console.log("values", values);
}} let data;
> if (showComments) {
{({ values, errors, touched, handleChange, handleBlur, handleSubmit }) => ( data = {
<Form email: values.email,
onSubmit={e => { rejectionReason: values.comments
e.preventDefault(); };
handleSubmit(); } else {
}} data = {
> email: values.email,
<div className="input-group"> rejectionReason: values.reason
<label>Email Id</label> };
<input type="text" name="email" onChange={handleChange} onBlur={handleBlur} value={values.email} placeholder="yourname@example.com" style={{ backgroundColor: "#EBEBEB", boxShadow: "1.63px 3.26px 4.07px 0px #FFFFFF40 inset", border: "none" }} /> }
{errors.email && touched.email && <span className="form-error">{errors.email}</span>} console.log(data);
</div>
<div className="input-group mb-1">
<label>Reason</label>
<select
name="reason"
onChange={handleChange}
onBlur={handleBlur}
value={values.reason}
>
<option value="">Select</option>
<option value="Not listed">Not listed</option>
</select>
{/* <ReactSelect
defaultValue={selectedOption}
onChange={setSelectedOption}
options={reasonOptions}
/> */}
{errors.reason && touched.reason && <span className="form-error">{errors.reason}</span>}
</div>
<div className="input-group">
<textarea rows={4} placeholder="Leave your comments here..." name="comments"
onChange={handleChange}
onBlur={handleBlur}
value={values.comments} />
{errors.comments && touched.comments && <span className="form-error">{errors.comments}</span>}
</div>
<div className="my-4"> let response = await updateApprovalStatusAdmin({ status: "rejected", userId: detail[0].attributes.user.data.id, rejectionReason: data.rejectionReason });
<div className="d-flex justify-content-center"> console.log(response.data);
<Button type="submit" variant="" className="btnAdd btnApprove m-0"> await dispatch(getAllVendors());
Submit handleClose()
</Button> setShowDetail(false);
<div className="px-1"></div> }}
<Button type="button" variant="" className="btnAdd btnReject m-0" onClick={handleClose}> >
Cancel {({ values, errors, touched, handleChange, handleBlur, handleSubmit }) => (
</Button> <Form
</div> onSubmit={e => {
</div> e.preventDefault();
</Form> handleSubmit();
)} }}
</Formik> >
</div> {/* {console.log("formik.values",values)} */}
</div> <div className="input-group">
<label>Email Id</label>
<input
disabled={true}
type="text"
name="email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
placeholder="yourname@example.com"
style={{ backgroundColor: "#EBEBEB", boxShadow: "1.63px 3.26px 4.07px 0px #FFFFFF40 inset", border: "none" }}
/>
{errors.email && touched.email && <span className="form-error">{errors.email}</span>}
</div> </div>
</div>
</Modal.Body>
</Modal>
</Fragment>
)
}
export default RejectModal;
\ No newline at end of file \ No newline at end of file
<div className="input-group mb-1">
<label>Reason</label>
<select
name="reason"
onChange={e => {
console.log(e);
handleChange(e);
if (e.target.value == "notListed") {
setshowComments(true);
} else {
setshowComments(false);
}
}}
onBlur={handleBlur}
value={values.reason}
>
<option value="">Select</option>
<option value="Invalid address details">Invalid address details</option>
<option value="Invalid business details">Invalid business details</option>
<option value="Bogus PAN number">Bogus PAN number</option>
<option value="notListed">Not listed</option>
</select>
{errors.reason && touched.reason && <span className="form-error">{errors.reason}</span>}
</div>
{showComments && (
<div className="input-group">
<textarea rows={4} placeholder="Leave your comments here..." name="comments" onChange={handleChange} onBlur={handleBlur} value={values.comments} />
{errors.comments && touched.comments && <span className="form-error">{errors.comments}</span>}
</div>
)}
<div className="my-4">
<div className="d-flex justify-content-center">
<Button type="submit" variant="" className="btnAdd btnApprove m-0" disabled={values.comments == "" && showComments}>
Submit
</Button>
<div className="px-1"></div>
<Button type="button" variant="" className="btnAdd btnReject m-0" onClick={handleClose}>
Cancel
</Button>
</div>
</div>
</Form>
)}
</Formik>
</div>
</div>
</div>
</div>
</Modal.Body>
</Modal>
</Fragment>
);
};
export default RejectModal;
import React from 'react'
import { Modal } from 'react-bootstrap'
import VendorDetails from './VendorDetails';
const VendorDetailModal = ({setShowDetail, showDetail, detail}) => {
console.log("detail", detail);
return (
<div>
{/* <Modal show={showDetail} onHide={()=>{setShowDetail(false)}}>
<Modal.Header closeButton>
<Modal.Title>{detail[0].attributes.businessName}</Modal.Title>
</Modal.Header>
<Modal.Body>
modal
</Modal.Body>
</Modal> */}
</div>
)
}
export default VendorDetailModal
\ No newline at end of file \ No newline at end of file
import React, { Fragment, useState } from "react" import React, { Fragment, useEffect, useState } from "react";
import { Button, Table } from "react-bootstrap"; import { Button, Table } from "react-bootstrap";
import { FaAngleLeft, FaArrowLeft } from "react-icons/fa"; import { FaAngleLeft, FaArrowLeft } from "react-icons/fa";
import ActivityDetailsModal from "./ActivityDetailsModal"; import ActivityDetailsModal from "./ActivityDetailsModal";
import Image from "next/image"; import Image from "next/image";
import RejectModal from "./RejectModal"; import RejectModal from "./RejectModal";
import ActivityListingRBAC from "../vendor/ActivityListingRBAC";
import { useDispatch, useSelector } from "react-redux";
import { getActivitiesByVendor, getActivitiesForAdmin } from "../../redux/actions/activityAction";
import { Tag } from "antd";
import { updateApprovalStatusAdmin } from "../../redux/actions/userActions";
import { getAllVendors } from "../../redux/actions/vendorActions";
import { toast } from "react-toastify";
const VendorDetails = ({ id, backClick }) => { const VendorDetails = ({ id, backClick, setShowDetail, showDetail, detail }) => {
const [showActivityDetailsModal, setShowActivityDetailsModal] = useState(false); const { allVendors } = useSelector(state => state.allVendors);
const [showRejectModal, setShowRejectModal] = useState(false);
const handleShowActivityDetails = () => {
setShowActivityDetailsModal(true)
}
const handleCloseActivityDetails = () => {
setShowActivityDetailsModal(false)
}
const handleShowRejectModal = () => {
setShowRejectModal(true)
}
const handleCloseRejectModal = () => {
setShowRejectModal(false)
}
return ( const dispatch = useDispatch();
<Fragment> useEffect(() => {
<div className="vendorDetails"> dispatch(getActivitiesForAdmin({ vendorId: detail[0].id }));
}, []);
useEffect(() => {
dispatch(getActivitiesForAdmin({ vendorId: detail[0].id }));
}, [allVendors]);
console.log("detail", detail);
const [showActivityDetailsModal, setShowActivityDetailsModal] = useState(false);
const [showRejectModal, setShowRejectModal] = useState(false);
const [activityDetailInfo, setactivityDetailInfo] = useState();
const handleShowActivityDetails = () => {
setShowActivityDetailsModal(true);
};
const handleCloseActivityDetails = () => {
setShowActivityDetailsModal(false);
};
const handleShowRejectModal = () => {
setShowRejectModal(true);
};
const handleCloseRejectModal = () => {
setShowRejectModal(false);
};
// const UserStatus = () => {
// if (!detail || !detail.length > 0) return;
// const currentStatus = detail[0].attributes.user.data.attributes.approved;
// let message;
// let color;
// switch (currentStatus) {
// case "approved":
// message = "Approved";
// color = "success";
// break;
// case "rejected":
// message = "Rejected";
// color = "error";
// break;
// case "pending":
// message = "Pending";
// color = "warning";
// break;
// default:
// break;
// }
// return <Tag color={color}>{message}</Tag>;
// };
return (
<Fragment>
<div className="vendorDetails">
<div className="row">
<div className="col-12 col-lg-12">
<div className="d-flex align-items-center justify-content-between">
<div className="backDiv">
<span className="backArrow">
<FaAngleLeft
onClick={() => {
setShowDetail(false);
}}
/>
</span>
<span>Vendors List</span>
</div>
</div>
</div>
<div className="col-8 col-lg-8 mt-4">
<h4>Business Information</h4>
<div className="row">
<div className="col-12 col-lg-4">
<p className="phead">Business Documents</p>
<div className="row">
<p className="col-12 col-lg-6">Business PAN No.</p>
<p className="col-12 col-lg-6">{detail[0].attributes.pan}</p>
</div>
<div className="row">
<p className="col-12 col-lg-6">PAN</p>
<p className="col-12 col-lg-6 pview">View</p>
</div>
<div className="row">
<p className="col-12 col-lg-6">GST Number</p>
<p className="col-12 col-lg-6">{detail[0].attributes.gst}</p>
</div>
<div className="row">
<p className="col-12 col-lg-6">GST Certificate</p>
<p className="col-12 col-lg-6 pview">View</p>
</div>
<div className="row"> <div className="row">
<div className="col-12 col-lg-12"> <p className="col-12 col-lg-6">Business Name</p>
<div className="d-flex align-items-center justify-content-between"> <p className="col-12 col-lg-6">{detail[0].attributes.businessName}</p>
<div className="backDiv">
<span className="backArrow" onClick={backClick}><FaAngleLeft /></span>
<span>Vendors List</span>
</div>
<div className="d-flex">
<Button variant="" className="btnAdd btnApprove my-0 me-2">
Approve
</Button>
<Button variant="" className="btnAdd btnReject m-0" onClick={handleShowRejectModal}>
Reject
</Button>
</div>
</div>
</div>
<div className="col-12 col-lg-12 mt-4">
<h4>Business Information</h4>
<div className="row">
<div className="col-12 col-lg-4">
<p className="phead">Business Documents</p>
<div className="row">
<p className="col-12 col-lg-6">Business PAN No.</p>
<p className="col-12 col-lg-6">BQYOG5528T</p>
</div>
<div className="row">
<p className="col-12 col-lg-6">PAN</p>
<p className="col-12 col-lg-6 pview">View</p>
</div>
<div className="row">
<p className="col-12 col-lg-6">GST Number</p>
<p className="col-12 col-lg-6">27AAGFL7781K2AX</p>
</div>
<div className="row">
<p className="col-12 col-lg-6">GST Certificate</p>
<p className="col-12 col-lg-6 pview">View</p>
</div>
<div className="row">
<p className="col-12 col-lg-6">Business Name</p>
<p className="col-12 col-lg-6">M S Adventures</p>
</div>
</div>
<div className="col-12 col-lg-5 borderLeft">
<p className="phead">Business Address</p>
<div className="row">
<p className="col-12 col-lg-4">Pincode</p>
<p className="col-12 col-lg-8">91006</p>
</div>
<div className="row">
<p className="col-12 col-lg-4">Country</p>
<p className="col-12 col-lg-8">United States</p>
</div>
<div className="row">
<p className="col-12 col-lg-4">State</p>
<p className="col-12 col-lg-8">California</p>
</div>
<div className="row">
<p className="col-12 col-lg-4">City</p>
<p className="col-12 col-lg-8">Los Angeles</p>
</div>
<div className="row">
<p className="col-12 col-lg-4">Address Line 1</p>
<p className="col-12 col-lg-8">5396 North Reese Avenue, Fresno</p>
</div>
<div className="row">
<p className="col-12 col-lg-4">Address Line 2</p>
<p className="col-12 col-lg-8">N/A</p>
</div>
</div>
</div>
</div>
<div className="col-12 col-lg-12 mt-4">
<h4 className="mb-1">Activities</h4>
<Table responsive className="listingTable">
<thead>
<tr>
<th>
<label className="check-container mb-0 ps-2" htmlFor="checkh">
<input
type="checkbox"
id="checkh"
className="check-box"
/>
<span className="checkmark"></span>
</label>
</th>
<th>Category</th>
<th>Sub Category</th>
<th>Name</th>
<th>Location</th>
<th>Price</th>
<th>Place</th>
<th>Gift</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{[1, 2].map((data, index) => (
<tr key={index}>
<td>
<label className="check-container mb-0 ps-2" htmlFor={`check${index}`}>
<input
type="checkbox"
id={`check${index}`}
className="check-box"
/>
<span className="checkmark"></span>
</label>
</td>
<td><span onClick={handleShowActivityDetails}>Adventure</span></td>
<td>Ice-Skating</td>
<td>Ice-Skating in NY</td>
<td>North Avenue</td>
<td>$ 479</td>
<td>Outdoor</td>
<td>Allowed</td>
<td><Image alt="" width={20} height={20} src="/images/vendor/icon-view.svg" /></td>
<td><Image alt="" width={20} height={20} src="/images/vendor/icon-more-vertical.svg" /></td>
</tr>
))}
<tr>
<td colSpan={10}>Showing Results 10 of 1567</td>
</tr>
</tbody>
</Table>
</div>
</div> </div>
</div>
<div className="col-12 col-lg-5 borderLeft">
<p className="phead">Business Address</p>
<div className="row">
<p className="col-12 col-lg-4">Pincode</p>
<p className="col-12 col-lg-8">{detail[0].attributes.pincode}</p>
</div>
<div className="row">
<p className="col-12 col-lg-4">Country</p>
<p className="col-12 col-lg-8">United States</p>
</div>
<div className="row">
<p className="col-12 col-lg-4">State</p>
<p className="col-12 col-lg-8">{detail[0].attributes.state}</p>
</div>
<div className="row">
<p className="col-12 col-lg-4">City</p>
<p className="col-12 col-lg-8">{detail[0].attributes.city}</p>
</div>
<div className="row">
<p className="col-12 col-lg-4">Address Line 1</p>
<p className="col-12 col-lg-8">{detail[0].attributes.addressLine1}</p>
</div>
<div className="row">
<p className="col-12 col-lg-4">Address Line 2</p>
<p className="col-12 col-lg-8">{detail[0].attributes.addressLine2 ? detail[0].attributes.addressLine2 : "N/A"}</p>
</div>
</div>
</div> </div>
</div>
<div className=" col-4">
<div className="row">
{/* <div className="col-12">
<div className="row">
<div className="col-6">Current status:</div>
<div className="col-6">
<UserStatus />
</div>
</div>
</div> */}
<Button
variant=""
className="btnAdd btnApprove col-6"
onClick={async () => {
await updateApprovalStatusAdmin({ status: "approved", userId: detail[0].attributes.user.data.id });
toast.success("User approved");
await dispatch(getAllVendors());
}}
>
Approve
</Button>
<Button variant="" className="btnAdd btnReject col-6" onClick={handleShowRejectModal}>
Reject
</Button>
</div>
</div>
<div className="col-12 col-lg-12 mt-4">
<h4 className="mb-1">Activities</h4>
<ActivityListingRBAC setactivityDetailInfo={setactivityDetailInfo} setShowActivityDetailsModal={setShowActivityDetailsModal} />
</div>
</div>
</div>
{showActivityDetailsModal && ( {showActivityDetailsModal && <ActivityDetailsModal show={showActivityDetailsModal} handleClose={handleCloseActivityDetails} activityDetailInfo={activityDetailInfo} />}
<ActivityDetailsModal show={showActivityDetailsModal} handleClose={handleCloseActivityDetails} />
)}
{showRejectModal && (
<RejectModal show={showRejectModal} handleClose={handleCloseRejectModal} />
)}
</Fragment>
)
}
export default VendorDetails;
\ No newline at end of file \ No newline at end of file
{showRejectModal && <RejectModal show={showRejectModal} handleClose={handleCloseRejectModal} detail={detail} setShowDetail={setShowDetail} />}
</Fragment>
);
};
export default VendorDetails;
import { Fragment, useState } from "react"; import { CheckOutlined, DeleteTwoTone, EyeTwoTone, StopOutlined, StopTwoTone } from "@ant-design/icons";
import { Button, Image, Table } from "react-bootstrap"; import { Space, Table, Tag } from "antd";
import { getSession } from "next-auth/react";
import { useRouter } from "next/router";
import { Fragment, useEffect, useState } from "react";
import { Button, Image } from "react-bootstrap";
import { useDispatch, useSelector } from "react-redux";
import { loadUser } from "../../redux/actions/userActions";
import { getAllVendors } from "../../redux/actions/vendorActions";
import VendorDetailModal from "./VendorDetailModal";
import VendorDetails from "./VendorDetails"; import VendorDetails from "./VendorDetails";
const VendorListing = () => { const VendorListing = () => {
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9]; // Hooks
const [showMenuIndex, setShowMenuIndex] = useState(null); const dispatch = useDispatch();
const router = useRouter();
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// useState
const [session, setSession] = useState();
const [loading, setLoading] = useState(true);
const [showMenuIndex, setShowMenuIndex] = useState(null);
const [restriction, setRestriction] = useState(false);
const [data, setData] = useState([]);
const [showDetail, setShowDetail] = useState(false);
const [detail, setDetail] = useState();
const toggleMenu = (index) => { // selectors
setShowMenuIndex(index === showMenuIndex ? null : index); const { loadedUser } = useSelector(state => state.loadedUser);
}; const { allVendors } = useSelector(state => state.allVendors);
const toggleMenu = index => {
setShowMenuIndex(index === showMenuIndex ? null : index);
};
const [vendorId, setVendorId] = useState(null); // Session
const [showVendorDetails, setShowVendorDetails] = useState(false); // useEffect(() => {
const handleShowVendorDetails = () => { // const fetchSession = async () => {
setShowVendorDetails(true) // setSession(await getSession());
} // };
const handleCloseVendorDetails = () => { // fetchSession();
setShowVendorDetails(false) // // dispatch(getLoggedInVendor());
// }, []);
// useEffects
useEffect(() => {
dispatch(loadUser());
// console.log(">>", loadedUser);
// if (!loadedUser) {
// router.push("/admin/login")
// }
if (loadedUser && loadedUser.role.name != "admin") {
setRestriction(true);
setLoading(true);
} else {
setRestriction(false);
setLoading(false);
} }
// if (!loadedUser) {
// setRestriction(true);
// return
// }
}, []);
// console.log("session", loadedUser);
return ( useEffect(() => {
<Fragment> if (!loadedUser) return;
{!showVendorDetails && ( dispatch(getAllVendors());
<div className="row"> }, [loadedUser]);
<div className="col-12 col-lg-12">
<div className="rightContent"> console.log("allVendors", allVendors);
<div className="d-flex align-items-center justify-content-between px-2 mb-2"> const [vendorId, setVendorId] = useState(null);
<div> const [showVendorDetails, setShowVendorDetails] = useState(false);
<h2>Vendors</h2> const handleShowVendorDetails = () => {
<p>View all the vendors</p> setShowVendorDetails(true);
</div> };
<div> const handleCloseVendorDetails = () => {
<Button type="button" variant="" className="btnAdd m-0"> setShowVendorDetails(false);
<Image alt="" width="16" height="16" src="/images/vendor/icon-filter.svg" className="me-2" /> Filter };
</Button>
</div> // useEffect
</div>
<Table responsive className="listingTable"> useEffect(() => {
<thead> setLoading(true);
<tr> let initialData =
<th> allVendors &&
<label className="check-container mb-0 ps-2" htmlFor="checkh"> allVendors.map(item => {
<input return {
type="checkbox" key: item.id,
id="checkh" name: item.attributes.name,
className="check-box" businessName: item.attributes.businessName,
/> status: [item.attributes.user.data.attributes.approved],
<span className="checkmark"></span> confirmed: item.attributes.user.data.attributes.confirmed
</label> };
</th> });
<th>Vendor</th> console.log("initialData", initialData);
<th>Vendor Id</th> setData(initialData);
<th>Contact Person</th> setLoading(false);
<th>Phone Number</th> }, [allVendors]);
<th>Email Address</th>
<th>Status</th> const columns = [
<th></th> {
</tr> title: "Name",
</thead> dataIndex: "name",
<tbody> key: "name",
{array.map((data, index) => ( render: text => <a>{text}</a>
<tr key={index}> },
<td> {
<label className="check-container mb-0 ps-2" htmlFor={`check${index}`}> title: "Business Name",
<input dataIndex: "businessName",
type="checkbox" key: "businessName"
id={`check${index}`} },
className="check-box" {
/> title: "OTP verified",
<span className="checkmark"></span> dataIndex: "confirmed",
</label> key: "confirmed",
</td> render: (_, { confirmed }) => (
<td> <>
<span onClick={() => { <>{confirmed ? <CheckOutlined /> : <StopOutlined />}</>
setVendorId(1); </>
handleShowVendorDetails(); )
}}> },
M S Adventure {
</span> title: "Approved",
</td> key: "status",
<td>VN_ET9797</td> dataIndex: "status",
<td>Ridge Johnson</td> render: (_, { status }) => (
<td>+91 9865 43210</td> <>
<td>adventuretrails@example.com</td> {status.map(tag => {
<td><div className={`statusDiv ${index % 2 ? "inactive" : "active"}`}>{index % 2 ? "Inactive" : "Active"}</div></td> // console.log("tag", tag);
<td> let color;
<div className="actions"> // if (tag === "loser") {
<div className="ellipse" onClick={() => toggleMenu(index)}> // color = "volcano";
<Image alt="" width={20} height={20} src="/images/vendor/icon-more-vertical.svg" /> // }
</div> switch (tag) {
{showMenuIndex === index && ( case "approved":
<div className="menu"> color = "green";
<ul> break;
<li>View</li> case "pending":
<li>Deactivate</li> color = "orange";
<li>Delete</li> break;
</ul>
</div> case "none":
)} color = "red";
</div> break;
</td>
</tr> case "rejected":
))} color = "red";
<tr> break;
<td colSpan={7}>Showing Results 10 of 1567</td>
</tr> default:
</tbody> break;
</Table> }
</div> // console.log("color", color);
</div> return (
</div> <Tag color={color} key={tag}>
)} {tag.toString().toUpperCase()}
</Tag>
);
})}
</>
)
},
{
title: "Action",
key: "action",
render: (_, record) => (
<Space size="middle">
{/* <DeleteTwoTone style={{ fontSize: '22px' }} twoToneColor="red"/> */}
<EyeTwoTone
style={{ fontSize: "22px" }}
onClick={() => {
setShowDetail(true);
setDetail(allVendors.filter(item => item.id == record.key));
}}
/>
<StopTwoTone style={{ fontSize: "20px" }} twoToneColor="red" />
</Space>
)
}
];
{vendorId && showVendorDetails && ( return (
<VendorDetails id={vendorId} backClick={handleCloseVendorDetails} /> <Fragment>
<div className={restriction ? "overlay" : ""}>
{restriction ? (
<div className="d-flex justify-content-center align-items-center" style={{ color: "#FFF", fontSize: "50px", height: "100%" }}>
Access restricted! Only admin is allowed to view the data.
</div>
) : (
<div>
{!showDetail ? (
<Table loading={loading} columns={columns} dataSource={data} />
) : (
// <VendorDetailModal />
<VendorDetails setShowDetail={setShowDetail} showDetail={showDetail} detail={detail} />
)} )}
<div></div>
</div>
)}
</div>
</Fragment>
// <Fragment>
// {!showVendorDetails && (
// <div className="row">
// <div className="col-12 col-lg-12">
// <div className="rightContent">
// <div className="d-flex align-items-center justify-content-between px-2 mb-2">
// <div>
// <h2>Vendors</h2>
// <p>View all the vendors</p>
// </div>
// <div>
// <Button type="button" variant="" className="btnAdd m-0">
// <Image alt="" width="16" height="16" src="/images/vendor/icon-filter.svg" className="me-2" /> Filter
// </Button>
// </div>
// </div>
// <Table responsive className="listingTable">
// <thead>
// <tr>
// <th>
// <label className="check-container mb-0 ps-2" htmlFor="checkh">
// <input type="checkbox" id="checkh" className="check-box" />
// <span className="checkmark"></span>
// </label>
// </th>
// <th>Vendor</th>
// <th>Vendor Id</th>
// <th>Contact Person</th>
// <th>Phone Number</th>
// <th>Email Address</th>
// <th>Status</th>
// <th></th>
// </tr>
// </thead>
// <tbody>
// {array.map((data, index) => (
// <tr key={index}>
// <td>
// <label className="check-container mb-0 ps-2" htmlFor={`check${index}`}>
// <input type="checkbox" id={`check${index}`} className="check-box" />
// <span className="checkmark"></span>
// </label>
// </td>
// <td>
// <span
// onClick={() => {
// setVendorId(1);
// handleShowVendorDetails();
// }}
// >
// M S Adventure
// </span>
// </td>
// <td>VN_ET9797</td>
// <td>Ridge Johnson</td>
// <td>+91 9865 43210</td>
// <td>adventuretrails@example.com</td>
// <td>
// <div className={`statusDiv ${index % 2 ? "inactive" : "active"}`}>{index % 2 ? "Inactive" : "Active"}</div>
// </td>
// <td>
// <div className="actions">
// <div className="ellipse" onClick={() => toggleMenu(index)}>
// <Image alt="" width={20} height={20} src="/images/vendor/icon-more-vertical.svg" />
// </div>
// {showMenuIndex === index && (
// <div className="menu">
// <ul>
// <li>View</li>
// <li>Deactivate</li>
// <li>Delete</li>
// </ul>
// </div>
// )}
// </div>
// </td>
// </tr>
// ))}
// <tr>
// <td colSpan={7}>Showing Results 10 of 1567</td>
// </tr>
// </tbody>
// </Table>
// </div>
// </div>
// </div>
// )}
</Fragment> // {vendorId && showVendorDetails && <VendorDetails id={vendorId} backClick={handleCloseVendorDetails} />}
); // </Fragment>
);
}; };
export default VendorListing; export default VendorListing;
...@@ -9,9 +9,9 @@ import { loadUser } from "../../redux/actions/userActions"; ...@@ -9,9 +9,9 @@ import { loadUser } from "../../redux/actions/userActions";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
const Header = () => { const Header = () => {
const { user, error } = useSelector(state => state.loadedUser); const { loadedUser } = useSelector(state => state.loadedUser);
const dispatch = useDispatch(); const dispatch = useDispatch();
// console.log("user", user); // console.log("user", loadedUser);
const [isSticky, setIsSticky] = useState(false); const [isSticky, setIsSticky] = useState(false);
const router = useRouter(); const router = useRouter();
useEffect(() => { useEffect(() => {
...@@ -60,12 +60,12 @@ const Header = () => { ...@@ -60,12 +60,12 @@ const Header = () => {
</div> </div>
</Form> </Form>
{/* {console.log(user.id)} */} {/* {console.log(user.id)} */}
{user && user.id ? ( {loadedUser && loadedUser.id ? (
<div> <div>
<div> <div>
<p>Brand Logo</p> <p>Brand Logo</p>
</div> </div>
<p>{user.phone}</p> <p>{loadedUser.phone}</p>
<Button <Button
onClick={async () => { onClick={async () => {
signOut({ redirect: false }); signOut({ redirect: false });
......
...@@ -9,6 +9,8 @@ import { useDispatch, useSelector } from "react-redux"; ...@@ -9,6 +9,8 @@ import { useDispatch, useSelector } from "react-redux";
const Layout = ({ children, title = "Zango", description = "Zango" }) => { const Layout = ({ children, title = "Zango", description = "Zango" }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
// const { loadedUser } = useSelector(state => state.loadedUser);
// console.log(">>>", loadedUser);
useEffect(() => { useEffect(() => {
dispatch(loadUser()); dispatch(loadUser());
}, []); }, []);
......
...@@ -24,7 +24,7 @@ const Login = props => { ...@@ -24,7 +24,7 @@ const Login = props => {
<div className="row"> <div className="row">
<div className="col-11 col-lg-4 login-div"> <div className="col-11 col-lg-4 login-div">
<div className=""> <div className="">
<h2>{props.type == "user" ? "Login to Experience" : (props.type == "vendor" ? "Vendor Login" : "Admin Login")}</h2> <h2>{props.type == "user" ? "Login to Experience" : "Vendor Login"}</h2>
<div className="form-container"> <div className="form-container">
<Formik <Formik
initialValues={{ initialValues={{
......
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { Button, Input, Space, Table } from "antd"; import { Button, Dropdown, Input, Space, Table } from "antd";
import { useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import Highlighter from "react-highlight-words"; import Highlighter from "react-highlight-words";
import { DeleteTwoTone, EditTwoTone, SearchOutlined } from "@ant-design/icons"; import { DeleteTwoTone, DownCircleOutlined, EditTwoTone, SearchOutlined } from "@ant-design/icons";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { getActivitiesByVendor } from "../../redux/actions/activityAction";
import { loadUser, updateActivityStatusAdmin } from "../../redux/actions/userActions";
import { Modal } from "react-bootstrap";
import { toast } from "react-toastify";
const onChange = (pagination, filters, sorter, extra) => { const onChange = (pagination, filters, sorter, extra) => {
console.log("params", pagination, filters, sorter, extra); console.log("params", pagination, filters, sorter, extra);
}; };
export const ActivityListingRBAC = () => { export const ActivityListingRBAC = ({setactivityDetailInfo, setShowActivityDetailsModal}) => {
const router = useRouter() const router = useRouter();
const dispatch = useDispatch();
// let columns = [] // let columns = []
// useSelectors // useSelectors
const { allActivitiesData } = useSelector(state => state.allActivitiesData); const { allActivitiesData } = useSelector(state => state.allActivitiesData);
const { loadedUser } = useSelector(state => state.loadedUser);
const { categories } = useSelector(state => state.categories); const { categories } = useSelector(state => state.categories);
const { subCategories } = useSelector(state => state.subCategories); const { subCategories } = useSelector(state => state.subCategories);
// console.log("loadedUser", loadedUser);
// useStates // useStates
const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [columns, setcolumns] = useState([]); const [columns, setcolumns] = useState([]);
const [data, setdata] = useState([]); const [data, setdata] = useState([]);
const [rejectPopUp, setrejectPopUp] = useState(false);
const [searchText, setSearchText] = useState(""); const [searchText, setSearchText] = useState("");
const [searchedColumn, setSearchedColumn] = useState(""); const [searchedColumn, setSearchedColumn] = useState("");
const [rejectionReasonText, setrejectionReasonText] = useState("");
const [rejectionId, setrejectionId] = useState("");
// functions // functions
const onSelectChange = newSelectedRowKeys => { const onSelectChange = newSelectedRowKeys => {
...@@ -134,21 +142,32 @@ export const ActivityListingRBAC = () => { ...@@ -134,21 +142,32 @@ export const ActivityListingRBAC = () => {
text text
) )
}); });
let IS_ADMIN = false;
// useEffects // useEffects
useEffect(() => { useEffect(() => {
let initialData = allActivitiesData.data.map((item, index) => { if (loadedUser && loadedUser.role.type == "admin") {
return { IS_ADMIN = true;
key: item.id, }
name: item.attributes.name, }, [loadedUser]);
category: item.attributes.subCategory.data.attributes.category.data.attributes.name,
subCategory: item.attributes.subCategory.data.attributes.name, useEffect(() => {
location: item.attributes.masterPincode.data.attributes.name, // dispatch(loadUser());
price: item.attributes.pricePerPerson,
place: item.attributes.activityType, let initialData =
gift: item.attributes.giftSomeone ? "Yes" : "No" allActivitiesData &&
}; allActivitiesData.data.map((item, index) => {
}); return {
key: item.id,
name: item.attributes.name,
category: item.attributes.subCategory?.data.attributes.category.data.attributes.name,
subCategory: item.attributes.subCategory?.data.attributes.name,
location: item.attributes.masterPincode.data.attributes.name,
price: item.attributes.pricePerPerson,
place: item.attributes.activityType,
gift: item.attributes.giftSomeone ? "Yes" : "No"
};
});
const categoryFilterArray = categories.data.map((item, index) => { const categoryFilterArray = categories.data.map((item, index) => {
return { text: item.attributes.name, value: item.attributes.name }; return { text: item.attributes.name, value: item.attributes.name };
...@@ -157,129 +176,183 @@ export const ActivityListingRBAC = () => { ...@@ -157,129 +176,183 @@ export const ActivityListingRBAC = () => {
return { text: item.attributes.name, value: item.attributes.name }; return { text: item.attributes.name, value: item.attributes.name };
}); });
setdata(initialData); setdata(initialData);
setcolumns([ if (loadedUser && !loadedUser.role.type == "admin") {
{ setcolumns([
title: "Category", {
dataIndex: "category", title: "Category",
filters: categoryFilterArray, dataIndex: "category",
filterMode: "tree", filters: categoryFilterArray,
filterSearch: true, filterMode: "tree",
onFilter: (value, record) => record.category.startsWith(value), filterSearch: true,
width: "15%" onFilter: (value, record) => record.category.startsWith(value),
}, width: "15%"
{ },
title: "Sub-category", {
dataIndex: "subCategory", title: "Sub-category",
filters: subCategoryFilterArray, dataIndex: "subCategory",
filterSearch: true, filters: subCategoryFilterArray,
onFilter: (value, record) => record.subCategory.startsWith(value), filterSearch: true,
width: "15%" onFilter: (value, record) => record.subCategory.startsWith(value),
width: "15%"
},
{
title: "Name",
dataIndex: "name",
key: "name",
...getColumnSearchProps("name"),
width: "15%"
},
{
title: "Location",
dataIndex: "location",
width: "15%"
},
{
title: "Price",
dataIndex: "price",
width: "15%"
},
{
title: "Place",
dataIndex: "place",
// sorter: (a, b) => a.age - b.age width: "15%"
}, },
{ {
title: "Name", title: "Edit record",
dataIndex: "name", render: (_, record) => (
key: "name", <Space size="middle">
...getColumnSearchProps("name"), {/* <a>Invite {record.name}</a> */}
width: "15%" <EditTwoTone
}, style={{ fontSize: "22px" }}
{ onClick={() => {
title: "Location", router.push(`/vendor/activities/${record.key}`);
dataIndex: "location", console.log(record);
// key: "location", }}
// ...getColumnSearchProps('location'), />
// filters: [ {/* <DeleteTwoTone
// { twoToneColor="#FF0000"
// text: "London", style={{ fontSize: "22px" }}
// value: "London" onClick={() => {
// }, console.log(record);
// { }}
// text: "New York", /> */}
// value: "New York" </Space>
// } ),
// ], width: "10%"
// onFilter: (value, record) => record.address.startsWith(value), }
// filterSearch: true, ]);
width: "15%" }
}, if (loadedUser && loadedUser.role.type == "admin") {
{ setcolumns([
title: "Price", {
dataIndex: "price", title: "Category",
// filters: [ dataIndex: "category",
// { filters: categoryFilterArray,
// text: "London", filterMode: "tree",
// value: "London" filterSearch: true,
// }, onFilter: (value, record) => record.category.startsWith(value),
// { width: "15%"
// text: "New York", },
// value: "New York" {
// } title: "Sub-category",
// ], dataIndex: "subCategory",
// onFilter: (value, record) => record.address.startsWith(value), filters: subCategoryFilterArray,
// filterSearch: true, filterSearch: true,
width: "15%" onFilter: (value, record) => record.subCategory.startsWith(value),
}, width: "15%"
{ },
title: "Place", {
dataIndex: "place", title: "Name",
// filters: [ dataIndex: "name",
// { key: "name",
// text: "London", ...getColumnSearchProps("name"),
// value: "London" width: "15%"
// }, },
// { {
// text: "New York", title: "Location",
// value: "New York" dataIndex: "location",
// } width: "15%"
// ], },
// onFilter: (value, record) => record.address.startsWith(value), {
// filterSearch: true, title: "Price",
dataIndex: "price",
width: "15%"
},
{
title: "Place",
dataIndex: "place",
width: "15%" width: "15%"
}, },
// { {
// title: "Gift", title: "Action",
// dataIndex: "gift", render: (_, record) => (
// // filters: [ <Space size="middle">
// // { {/* <a>Invite {record.name}</a> */}
// // text: "London", <Dropdown
// // value: "London" menu={{
// // }, items: [
// // { {
// // text: "New York", key: "1",
// // value: "New York" label: (
// // } <a
// // ], rel="noopener noreferrer"
// // onFilter: (value, record) => record.address.startsWith(value), onClick={() => {
// // filterSearch: true, adminActions({type:"view", activityId: record.key})
// width: "10%" // console.log(record);
// }, }}
{ >
title: "Edit record", View Details
render: (_, record) => ( </a>
<Space size="middle"> )
{/* <a>Invite {record.name}</a> */} },
<EditTwoTone style={{ fontSize: "22px" }} {
onClick={() => { key: "2",
router.push(`/vendor/activities/${record.key}`) label: (
console.log(record); <a
}}/> rel="noopener noreferrer"
{/* <DeleteTwoTone onClick={() => {
twoToneColor="#FF0000" setrejectionId(record.key);
style={{ fontSize: "22px" }} adminActions({ type: "reject", activityId: record.key });
onClick={() => { }}
console.log(record); >
}} Reject
/> */} </a>
</Space> )
), },
width: "10%" {
} key: "3",
]); label: (
}, []); <a
target="_blank"
rel="noopener noreferrer"
onClick={() => {
// setrejectionId(record.key);
adminActions({ type: "approve", activityId: record.key });
}}
>
Approve
</a>
)
}
]
}}
placement="bottomLeft"
>
<Button style={{ border: "none" }}>
<DownCircleOutlined style={{ fontSize: "20px", color: "#08c" }} onClick={() => {}} />
</Button>
</Dropdown>
</Space>
),
width: "10%"
}
]);
}
}, [allActivitiesData, loadedUser]);
console.log("allActivitiesData", allActivitiesData); // console.log("allActivitiesData", allActivitiesData);
const rowSelection = { const rowSelection = {
selectedRowKeys, selectedRowKeys,
...@@ -318,9 +391,64 @@ export const ActivityListingRBAC = () => { ...@@ -318,9 +391,64 @@ export const ActivityListingRBAC = () => {
} }
] ]
}; };
const adminActions = async ({ type, activityId }) => {
if (type == "approve") {
await updateActivityStatusAdmin({ status: true, activityId, rejectionReason: "" });
}
if (type == "reject") {
setrejectPopUp(true);
}
if (type == "view") {
let data = allActivitiesData.data.filter(item => item.id == activityId)
setactivityDetailInfo(data)
setShowActivityDetailsModal(true)
}
};
return ( return (
<div> <div>
<Table rowSelection={rowSelection} columns={columns} dataSource={data} onChange={onChange} /> <Table rowSelection={rowSelection} columns={columns} dataSource={data} onChange={onChange} />
<Modal
show={rejectPopUp}
onHide={() => {
setrejectionId(null);
setrejectPopUp(false);
}}
>
<Modal.Header closeButton>Please mention reason for rejecting the activity.</Modal.Header>
<Modal.Body>
<div className="input-group">
<textarea
style={{ width: "100%" }}
rows={4}
className="p-2"
placeholder="Eg: Not appropriate for this age group."
name="comments"
onChange={e => {
e.preventDefault();
setrejectionReasonText(e.target.value);
}}
/>
</div>
<div className="my-4">
<div className="d-flex justify-content-center">
<Button
variant=""
className="btnAdd btnApprove m-0"
disabled={rejectionReasonText == ""}
onClick={async () => {
await updateActivityStatusAdmin({ status: false, activityId: rejectionId, rejectionReason: rejectionReasonText });
setrejectionId(null);
setrejectPopUp(false);
toast.success("Activity rejected.")
}}
>
Submit
</Button>
</div>
</div>
</Modal.Body>
</Modal>
</div> </div>
); );
}; };
......
...@@ -17,21 +17,21 @@ const BusinessDetails = () => { ...@@ -17,21 +17,21 @@ const BusinessDetails = () => {
const router = useRouter() const router = useRouter()
const { loggedInVendor } = useSelector(state => state.loggedInVendor); const { loggedInVendor } = useSelector(state => state.loggedInVendor);
const { vendorDetails } = useSelector(state => state.vendorDetails); const { vendorDetails } = useSelector(state => state.vendorDetails);
const { user, error } = useSelector(state => state.loadedUser); const { loadedUser, error } = useSelector(state => state.loadedUser);
// const [pincodeData, setPinCodeData] = useState() // const [pincodeData, setPinCodeData] = useState()
// const ref = useRef(null); // const ref = useRef(null);
// console.log("vendorDetails", vendorDetails); console.log("vendorDetails", vendorDetails);
const [disableFields, setdisableFields] = useState(); const [disableFields, setdisableFields] = useState();
useEffect(() => { useEffect(() => {
console.log("user", user); console.log("user", loadedUser);
if (user) { if (loadedUser) {
if (user.approved == "approved" || user.approved == "rejected") { if (loadedUser.approved == "approved" || loadedUser.approved == "rejected") {
setdisableFields(false); setdisableFields(false);
} else if (user.approved == "pending") { } else if (loadedUser.approved == "pending") {
setdisableFields(true); setdisableFields(true);
} }
} }
}, [user]); }, [loadedUser]);
// console.log("userStatus", userStatus); // console.log("userStatus", userStatus);
useEffect(() => { useEffect(() => {
const fetchSession = async () => { const fetchSession = async () => {
...@@ -82,8 +82,8 @@ const BusinessDetails = () => { ...@@ -82,8 +82,8 @@ const BusinessDetails = () => {
} }
const ApprovalStatus = () => { const ApprovalStatus = () => {
if (user) { if (loadedUser) {
switch (user.approved) { switch (loadedUser.approved) {
case "approved": case "approved":
return <></>; return <></>;
...@@ -116,7 +116,7 @@ const BusinessDetails = () => { ...@@ -116,7 +116,7 @@ const BusinessDetails = () => {
// vendorDetails && console.log("vendorData", vendorData, vendorDetails.length > 0); // vendorDetails && console.log("vendorData", vendorData, vendorDetails.length > 0);
return ( return (
<Fragment> <Fragment>
{user && ( {loadedUser && (
<div className="container p-5"> <div className="container p-5">
<div className="row"> <div className="row">
<div className="col-12 col-lg-8"> <div className="col-12 col-lg-8">
......
import React from "react"; import React, { useEffect, useState } from "react";
import Layout from "../../../components/layout/Layout"; import Layout from "../../../components/layout/Layout";
import Sidebar from "../../../components/layout/AdminDashboardSidebar"; import Sidebar from "../../../components/layout/AdminDashboardSidebar";
import ActivityListing from "../../../components/admin/ActivityListing"; import ActivityListing from "../../../components/admin/ActivityListing";
import ActivityListingRBAC from "../../../components/vendor/ActivityListingRBAC";
import { wrapper } from "../../../redux/store";
import { loadUser } from "../../../redux/actions/userActions";
import { getAllCategories, getAllSubCategories } from "../../../redux/actions/categoriesAction";
import { useDispatch } from "react-redux";
import { getActivitiesForAdmin } from "../../../redux/actions/activityAction";
import ActivityDetailsModal from "../../../components/admin/ActivityDetailsModal";
export default function ActivityListingPage() { export default function ActivityListingPage() {
const [activityDetailInfo, setactivityDetailInfo] = useState();
const [showActivityDetailsModal, setShowActivityDetailsModal] = useState(false);
return ( const handleCloseActivityDetails = () => {
<Layout> setShowActivityDetailsModal(false);
<div className="sidebarContainer"> };
<Sidebar />
<div className="content"> const dispatch = useDispatch();
<ActivityListing /> useEffect(() => {
</div> dispatch(getActivitiesForAdmin({}));
</div> }, []);
</Layout> return (
); <Layout>
}; <div className="sidebarContainer">
<Sidebar />
<div className="content">
{/* <ActivityListing /> */}
<ActivityListingRBAC setactivityDetailInfo={setactivityDetailInfo} setShowActivityDetailsModal={setShowActivityDetailsModal} />
{showActivityDetailsModal && (
<ActivityDetailsModal show={showActivityDetailsModal} handleClose={handleCloseActivityDetails} activityDetailInfo={activityDetailInfo} />
)}
</div>
</div>
</Layout>
);
}
/** For server side rendering */
export const getServerSideProps = wrapper.getServerSideProps(store => async ({ req, query }) => {
await store.dispatch(loadUser());
// await store.dispatch(getActivitiesByVendor());
await store.dispatch(getAllCategories());
await store.dispatch(getAllSubCategories());
// get the locations data.
// await store.dispatch(getVendorDetails())
return {
props: {}
};
});
import React, { useState } from "react";
import { Formik } from "formik";
import Image from "next/image";
import Link from "next/link";
import { Fragment } from "react";
import { Button, Form } from "react-bootstrap";
import * as Yup from "yup";
import { useRouter } from "next/router";
import { signIn } from "next-auth/react";
import { toast } from "react-toastify";
import { Loader } from "react-bootstrap-typeahead";
import { renderImage } from "../../services/imageHandling";
const AdminLogin = () => {
const [loading, setLoading] = useState(false);
const loginValidationSchema = Yup.object().shape({
email: Yup.string().required("Email Id is Required").email("Please Enter An Valid Email Id"),
password: Yup.string().required("Password is Required").min(6, "Password must be minimum 6 characters")
});
const router = useRouter();
return (
<div>
<Fragment>
<div className="contaier-fluid login-banner-image">
<div className="row">
{/* <div className="text-center">
<h1 style={{fontSize: "4rem"}}>Zango Admin Login</h1>
</div> */}
<div className="col-11 col-lg-4 login-div">
<div className="">
<h2 className="text-center">Zango Admin Login</h2>
<div className="form-container">
<Formik
initialValues={{
email: "",
password: ""
}}
validationSchema={loginValidationSchema}
// enableReinitialize={true}
onSubmit={async values => {
setLoading(true);
console.log("login values", values);
const signInResponse = await signIn("credentials", {
email: values.email,
password: values.password,
redirect: false
});
console.log("signInResponse", signInResponse);
if (!signInResponse.ok) {
toast.error(signInResponse.error);
setLoading(false);
return;
}
if (signInResponse.ok) {
setLoading(false);
router.push("/admin/vendors");
}
// router.push("")
}}
>
{({ values, errors, touched, handleChange, handleBlur, handleSubmit }) => (
<Form
onSubmit={e => {
e.preventDefault();
handleSubmit();
}}
>
<div className="input-group">
<label>Email Id</label>
<input type="text" name="email" onChange={handleChange} onBlur={handleBlur} value={values.email} placeholder="yourname@example.com" />
{errors.email && touched.email && <span className="form-error">{errors.email}</span>}
</div>
<div className="input-group">
<label>Password</label>
<input type="password" name="password" onChange={handleChange} onBlur={handleBlur} value={values.password} placeholder="#@$!%@#" />
{errors.password && touched.password && <span className="form-error">{errors.password}</span>}
</div>
<div className="input-group">
<Button type="submit" className="btn btn-primary btn-submit" disabled={loading}>
{loading ? <Loader /> : "Login"}
</Button>
</div>
</Form>
)}
</Formik>
{/* <div className="input-group justify-content-center">
<p className="text-center mb-0">
or{" "}
<Link href={`../signup/${}`}>
<span style={{ textDecoration: "underline", cursor: "pointer" }}>Create a new account</span>
</Link>
</p>
</div> */}
{/* {props && props.type == "user" && (
<>
<div className="input-group mb-0">
<div className="btn-continue">
<span className="col-1 image-container">
<Image src={renderImage("/images/login/icon-google.png")} layout="fill" className="image" />
</span>
<span className="col-10 text-center">Continue with Google</span>
</div>
</div>
<div className="input-group mb-0">
<div className="btn-continue">
<span className="col-1 image-container">
<Image src={renderImage("/images/login/icon-fb1.png")} layout="fill" className="image" />
</span>
<span className="col-10 text-center">Continue with Facebook</span>
</div>
</div>
<div className="input-group mb-0">
<div className="btn-continue mb-0">
<span className="col-1 image-container">
<Image src={renderImage("/images/login/icon-apple.png")} layout="fill" className="image" />
</span>
<span className="col-10 text-center">Continue with Apple</span>
</div>
</div>
</>
)} */}
</div>
</div>
</div>
</div>
</div>
</Fragment>
</div>
);
};
export default AdminLogin;
...@@ -2,17 +2,46 @@ import React from "react"; ...@@ -2,17 +2,46 @@ import React from "react";
import Layout from "../../../components/layout/Layout"; import Layout from "../../../components/layout/Layout";
import Sidebar from "../../../components/layout/AdminDashboardSidebar"; import Sidebar from "../../../components/layout/AdminDashboardSidebar";
import VendorListing from "../../../components/admin/VendorListing"; import VendorListing from "../../../components/admin/VendorListing";
import { wrapper } from "../../../redux/store";
import { getAllVendors } from "../../../redux/actions/vendorActions";
import { loadUser } from "../../../redux/actions/userActions";
import { getAllCategories, getAllSubCategories } from "../../../redux/actions/categoriesAction";
export default function VendorListingPage() { export default function VendorListingPage() {
return (
<Layout>
<div className="sidebarContainer">
<Sidebar />
<div className="content">
<VendorListing />
</div>
</div>
</Layout>
);
}
return ( /** For server side rendering */
<Layout> // export const getServerSideProps = wrapper.getServerSideProps(store => async ({ req, query }) => {
<div className="sidebarContainer"> // // Get the menu data.
<Sidebar />
<div className="content"> // // get the locations data.
<VendorListing /> // await store.dispatch(loadUser());
</div> // await store.dispatch(getAllVendors());
</div>
</Layout> // return {
); // props: {}
}; // };
// });
/** For server side rendering */
export const getServerSideProps = wrapper.getServerSideProps(store => async ({ req, query }) => {
// await store.dispatch(loadUser());
// await store.dispatch(getAllVendors());
await store.dispatch(loadUser());
// await store.dispatch(getActivitiesByVendor());
await store.dispatch(getAllCategories());
await store.dispatch(getAllSubCategories());
return {
props: {}
};
});
...@@ -73,7 +73,13 @@ export default NextAuth({ ...@@ -73,7 +73,13 @@ export default NextAuth({
// } // }
// } // }
return { ...userResponse.data.user, name: userResponse.data.user.email, jwt: userResponse.data.jwt, email: userResponse.data.user.email, user: userResponse.data.user }; return {
...userResponse.data.user,
name: userResponse.data.user.email,
jwt: userResponse.data.jwt,
email: userResponse.data.user.email,
user: userResponse.data.user
};
} catch (error) { } catch (error) {
console.log("Error while fetching credentials:"); console.log("Error while fetching credentials:");
console.log(error.response.data); console.log(error.response.data);
......
import Home from "../components/home/Home"; import Home from "../components/home/Home";
import Layout from "../components/layout/Layout"; import Layout from "../components/layout/Layout";
import { getActivitiesByVendor } from "../redux/actions/activityAction"; import { getActivitiesByVendor, getActivitiesForEndUser } from "../redux/actions/activityAction";
import { getAllCategories } from "../redux/actions/categoriesAction"; import { getAllCategories } from "../redux/actions/categoriesAction";
import { getHomeBanner } from "../redux/actions/homeBannerAction"; import { getHomeBanner } from "../redux/actions/homeBannerAction";
import { getTestimonial } from "../redux/actions/testimonialAction"; import { getTestimonial } from "../redux/actions/testimonialAction";
...@@ -29,7 +29,7 @@ export const getServerSideProps = wrapper.getServerSideProps(store => async ({ r ...@@ -29,7 +29,7 @@ export const getServerSideProps = wrapper.getServerSideProps(store => async ({ r
try { try {
await store.dispatch(getAllCategories()) await store.dispatch(getAllCategories())
await store.dispatch(getTestimonial()) await store.dispatch(getTestimonial())
await store.dispatch(getActivitiesByVendor()) await store.dispatch(getActivitiesForEndUser())
await store.dispatch(getHomeBanner()) await store.dispatch(getHomeBanner())
return { return {
......
import React from "react"; import React, { useEffect } from "react";
import Layout from "../../../components/layout/Layout"; import Layout from "../../../components/layout/Layout";
import { wrapper } from "../../../redux/store"; import { wrapper } from "../../../redux/store";
import Sidebar from "../../../components/layout/VendorDashboardSidebar"; import Sidebar from "../../../components/layout/VendorDashboardSidebar";
...@@ -7,10 +7,16 @@ import ActivityListingRBAC from "../../../components/vendor/ActivityListingRBAC" ...@@ -7,10 +7,16 @@ import ActivityListingRBAC from "../../../components/vendor/ActivityListingRBAC"
import { getAllCategories, getAllSubCategories } from "../../../redux/actions/categoriesAction"; import { getAllCategories, getAllSubCategories } from "../../../redux/actions/categoriesAction";
import { getActivitiesByVendor } from "../../../redux/actions/activityAction"; import { getActivitiesByVendor } from "../../../redux/actions/activityAction";
import { loadUser } from "../../../redux/actions/userActions"; import { loadUser } from "../../../redux/actions/userActions";
import { useDispatch } from "react-redux";
// import { loadUser } from "../redux/actions/userActions"; // import { loadUser } from "../redux/actions/userActions";
// import { wrapper } from "../redux/store"; // import { wrapper } from "../redux/store";
export default function ActivityListingPage() { export default function ActivityListingPage() {
const dispatch = useDispatch();
useEffect(() => {
dispatch(getActivitiesByVendor());
}, []);
return ( return (
<Layout> <Layout>
<div className="sidebarContainer"> <div className="sidebarContainer">
...@@ -26,7 +32,7 @@ export default function ActivityListingPage() { ...@@ -26,7 +32,7 @@ export default function ActivityListingPage() {
/** 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 }) => {
await store.dispatch(loadUser()); await store.dispatch(loadUser());
await store.dispatch(getActivitiesByVendor()); // await store.dispatch(getActivitiesByVendor());
await store.dispatch(getAllCategories()); await store.dispatch(getAllCategories());
await store.dispatch(getAllSubCategories()); await store.dispatch(getAllSubCategories());
// get the locations data. // get the locations data.
......
...@@ -8,29 +8,27 @@ import { wrapper } from "../../../redux/store"; ...@@ -8,29 +8,27 @@ import { wrapper } from "../../../redux/store";
// import { loadUser } from "../redux/actions/userActions"; // import { loadUser } from "../redux/actions/userActions";
// import { wrapper } from "../redux/store"; // import { wrapper } from "../redux/store";
export default function BusinessDetailsPage () { export default function BusinessDetailsPage() {
const dispatch = useDispatch() const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
dispatch(getVendorDetails()) dispatch(getVendorDetails());
}, []) }, []);
return ( return (
<Layout> <Layout>
<BusinessDetails /> <BusinessDetails />
</Layout> </Layout>
); );
}; }
/** 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 locations data.
await store.dispatch(loadUser());
return {
props: {}
};
});
\ No newline at end of file \ No newline at end of file
// Get the menu data.
// get the locations data.
await store.dispatch(loadUser());
return {
props: {}
};
});
...@@ -62,32 +62,32 @@ export const getActivitiesByVendor = () => async dispatch => { ...@@ -62,32 +62,32 @@ export const getActivitiesByVendor = () => async dispatch => {
const session = await getSession(); const session = await getSession();
console.log("session", session); console.log("session", session);
try { try {
// const vendorConfig = { const vendorConfig = {
// headers: { headers: {
// "Content-Type": "application/json", "Content-Type": "application/json",
// Authorization: `Bearer ${session.jwt}` Authorization: `Bearer ${session.jwt}`
// } }
// }; };
// const vendorQuery = { const vendorQuery = {
// filters: { filters: {
// user: { user: {
// id: { $eq: session.id } id: { $eq: session.id }
// } }
// } }
// }; };
// const vendorQueryString = qs.stringify(vendorQuery, { const vendorQueryString = qs.stringify(vendorQuery, {
// encodeValuesOnly: true encodeValuesOnly: true
// }); });
// const vendorResponse = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/vendors/?${vendorQueryString}`, vendorConfig); const vendorResponse = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/vendors/?${vendorQueryString}`, vendorConfig);
// console.log("vendorResponse",vendorResponse.data) console.log("vendorResponse", vendorResponse.data.data[0].id);
// const loggedinVendor = await getLoggedInVendor() // const loggedinVendor = await getLoggedInVendor()
// console.log("loggedinVendor", loggedinVendor); // console.log("loggedinVendor", loggedinVendor);
// if (!session) { if (!session) {
// return "You are not authenticated, please log in."; return "You are not authenticated, please log in.";
// } }
dispatch({ dispatch({
type: GET_ACTIVITIES_REQUEST, type: GET_ACTIVITIES_REQUEST,
loading: true loading: true
...@@ -101,7 +101,13 @@ export const getActivitiesByVendor = () => async dispatch => { ...@@ -101,7 +101,13 @@ export const getActivitiesByVendor = () => async dispatch => {
}; };
const query = { const query = {
filters: {}, filters: {
vendor: {
id: {
$eq: vendorResponse.data.data[0].id
}
}
},
populate: ["masterMonths", "subCategory", "subCategory.category", "timeSlots", "masterPincode", "vendor", "image"] populate: ["masterMonths", "subCategory", "subCategory.category", "timeSlots", "masterPincode", "vendor", "image"]
}; };
...@@ -193,7 +199,7 @@ export const updateActivityById = ...@@ -193,7 +199,7 @@ export const updateActivityById =
}; };
// const query = {} // const query = {}
const updateResponse = await axios.put(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/experiences/${activityId}`, {data: updatedData}, config); const updateResponse = await axios.put(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/experiences/${activityId}`, { data: updatedData }, config);
dispatch({ dispatch({
type: UPDATE_ACTIVITY_BY_ID_SUCCESS, type: UPDATE_ACTIVITY_BY_ID_SUCCESS,
...@@ -208,3 +214,106 @@ export const updateActivityById = ...@@ -208,3 +214,106 @@ export const updateActivityById =
}); });
} }
}; };
export const getActivitiesForAdmin =
({ vendorId }) =>
async dispatch => {
try {
dispatch({
type: GET_ACTIVITIES_REQUEST,
loading: true
});
const config = {
headers: {
"Content-Type": "application/json"
// Authorization: `Bearer ${session.jwt}`
}
};
const query = {
filters: {
vendor: {
id: {
$eq: vendorId
}
}
},
populate: ["masterMonths", "subCategory", "subCategory.category", "timeSlots", "masterPincode", "vendor", "image"]
};
const queryString = qs.stringify(query, {
encodeValuesOnly: true
});
// let activityData = {
// data: {
// ...data
// }
// };
const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/experiences?${queryString}`, config);
// console.log("Response", response.data);
dispatch({
type: GET_ACTIVITIES_SUCCESS,
payload: response.data
});
return response.data;
} catch (error) {
dispatch({
type: GET_ACTIVITIES_FAIL,
payload: error.response.data
});
}
};
export const getActivitiesForEndUser =
() =>
async dispatch => {
try {
dispatch({
type: GET_ACTIVITIES_REQUEST,
loading: true
});
const config = {
headers: {
"Content-Type": "application/json"
// Authorization: `Bearer ${session.jwt}`
}
};
const query = {
// filters: {
// vendor: {
// id: {
// $eq: vendorId
// }
// }
// },
populate: ["masterMonths", "subCategory", "subCategory.category", "timeSlots", "masterPincode", "vendor", "image"]
};
const queryString = qs.stringify(query, {
encodeValuesOnly: true
});
// let activityData = {
// data: {
// ...data
// }
// };
const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/experiences?${queryString}`, config);
// console.log("Response", response.data);
dispatch({
type: GET_ACTIVITIES_SUCCESS,
payload: response.data
});
return response.data;
} catch (error) {
dispatch({
type: GET_ACTIVITIES_FAIL,
payload: error.response.data
});
}
};
...@@ -106,8 +106,8 @@ const registerVendor = async vendorData => { ...@@ -106,8 +106,8 @@ const registerVendor = async vendorData => {
// register a new user. // register a new user.
export const loadUser = () => async dispatch => { export const loadUser = () => async dispatch => {
const session = await getSession(); const session = await getSession();
if (session) { if (session) {
console.log("session", session);
try { try {
dispatch({ dispatch({
type: LOAD_USER_REQUEST type: LOAD_USER_REQUEST
...@@ -120,8 +120,8 @@ export const loadUser = () => async dispatch => { ...@@ -120,8 +120,8 @@ export const loadUser = () => async dispatch => {
}; };
// Load the user. // Load the user.
const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/users/me?populate[0]=profileImage`, config); const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/users/me?populate[0]=profileImage&populate[1]=role`, config);
console.log("response session", response);
dispatch({ dispatch({
type: LOAD_USER_SUCCESS, type: LOAD_USER_SUCCESS,
payload: { ...response.data } payload: { ...response.data }
...@@ -404,3 +404,57 @@ export const updateUserApprovalStatus = async ({ status }) => { ...@@ -404,3 +404,57 @@ export const updateUserApprovalStatus = async ({ status }) => {
return response; return response;
}; };
export const updateApprovalStatusAdmin = async ({ status, userId, rejectionReason }) => {
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}`
}
};
if (!status == "rejected") {
rejectionReason = "";
}
const response = await axios.put(
`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/users/${userId}`,
{
approved: status,
rejectionReason
},
config
);
return response;
};
export const updateActivityStatusAdmin = async ({ status, activityId, rejectionReason }) => {
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}`
}
};
if (status) {
rejectionReason = "";
}
const response = await axios.put(
`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/experiences/${activityId}`,
{
data: {
approved: status,
rejectionReason
}
},
config
);
return response;
};
...@@ -2,6 +2,9 @@ import axios from "axios"; ...@@ -2,6 +2,9 @@ import axios from "axios";
import { getSession } from "next-auth/react"; import { getSession } from "next-auth/react";
import qs from "qs"; import qs from "qs";
import { import {
GET_ALL_VENDORS_FAIL,
GET_ALL_VENDORS_REQUEST,
GET_ALL_VENDORS_SUCCESS,
GET_LOGGED_IN_VENDOR_FAIL, GET_LOGGED_IN_VENDOR_FAIL,
GET_LOGGED_IN_VENDOR_REQUEST, GET_LOGGED_IN_VENDOR_REQUEST,
GET_LOGGED_IN_VENDOR_SUCCESS, GET_LOGGED_IN_VENDOR_SUCCESS,
...@@ -179,3 +182,53 @@ export const getVendorDetails = () => async dispatch => { ...@@ -179,3 +182,53 @@ export const getVendorDetails = () => async dispatch => {
}); });
} }
}; };
export const getAllVendors = () => async dispatch => {
const session = await getSession();
try {
dispatch({
type: GET_ALL_VENDORS_REQUEST
});
// console.log("here 1", session);
const config = {
headers: {
"Content-Type": "Application/json",
Authorization: `Bearer ${session.jwt}`
}
};
// console.log("here 2");
if (!session) {
return;
}
const query = {
// filters: {
// user: {
// id: {
// $eq: session.id
// }
// }
// },
populate: ["user", "experiences"]
};
// console.log("here 3", query);
const queryString = qs.stringify(query, {
encodeValuesOnly: true
});
console.log("session", session, session.id);
const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/vendors/?${queryString}`, config);
console.log("response", response);
dispatch({
type: GET_ALL_VENDORS_SUCCESS,
payload: response.data.data
});
return response.data.data[0];
} catch (error) {
dispatch({
type: GET_ALL_VENDORS_FAIL,
payload: error.response.data
});
}
};
...@@ -10,4 +10,8 @@ export const GET_VENDOR_DETAILS_REQUEST = "GET_VENDOR_DETAILS_REQUEST" ...@@ -10,4 +10,8 @@ export const GET_VENDOR_DETAILS_REQUEST = "GET_VENDOR_DETAILS_REQUEST"
export const GET_VENDOR_DETAILS_SUCCESS = "GET_VENDOR_DETAILS_SUCCESS" export const GET_VENDOR_DETAILS_SUCCESS = "GET_VENDOR_DETAILS_SUCCESS"
export const GET_VENDOR_DETAILS_FAIL = "GET_VENDOR_DETAILS_FAIL" export const GET_VENDOR_DETAILS_FAIL = "GET_VENDOR_DETAILS_FAIL"
export const GET_ALL_VENDORS_REQUEST = "GET_ALL_VENDORS_REQUEST"
export const GET_ALL_VENDORS_SUCCESS = "GET_ALL_VENDORS_SUCCESS"
export const GET_ALL_VENDORS_FAIL = "GET_ALL_VENDORS_FAIL"
export const CLEAR_ERRORS = "CLEAR_ERRORS"; export const CLEAR_ERRORS = "CLEAR_ERRORS";
\ No newline at end of file \ No newline at end of file
...@@ -4,7 +4,7 @@ import { townshipReducer, townshipsReducer } from "./townshipsReducer"; ...@@ -4,7 +4,7 @@ import { townshipReducer, townshipsReducer } from "./townshipsReducer";
import { authReducer, forgotPasswordReducer, loadedUserReducer, resetPasswordReducer, userReducer } from "./userReducers"; import { authReducer, forgotPasswordReducer, loadedUserReducer, resetPasswordReducer, userReducer } from "./userReducers";
import { enquiryReducer } from "./enquiryReducer"; import { enquiryReducer } from "./enquiryReducer";
import { displayEnquireNowReducer } from "./enquireNowModalReducer"; import { displayEnquireNowReducer } from "./enquireNowModalReducer";
import { getVendorDetailsReducer, loggedInVendorReducer, updateVendorReducer } from "./vendorReducers"; import { getAllVendorsReducer, getVendorDetailsReducer, loggedInVendorReducer, updateVendorReducer } from "./vendorReducers";
import { createActivityReducer, getActivitiesReducer, getActivityByIdReducer, updateActivityByIdReducer } from "./activitiesReducer"; import { createActivityReducer, getActivitiesReducer, getActivityByIdReducer, updateActivityByIdReducer } from "./activitiesReducer";
import { getAllCategoriesReducer, getAllSubCategoriesReducer } from "./categoryReducer"; import { getAllCategoriesReducer, getAllSubCategoriesReducer } from "./categoryReducer";
import { getAllTestimonialReducer } from "./testimonialReducer"; import { getAllTestimonialReducer } from "./testimonialReducer";
...@@ -37,6 +37,7 @@ const reducers = combineReducers({ ...@@ -37,6 +37,7 @@ const reducers = combineReducers({
blogs: blogsReducer, blogs: blogsReducer,
blog: blogReducer, blog: blogReducer,
homeBanner: getAllHomeBannerReducer, homeBanner: getAllHomeBannerReducer,
allVendors: getAllVendorsReducer,
}); });
export default reducers; export default reducers;
...@@ -52,7 +52,7 @@ export const authReducer = (state = { loading: false, success: false, user: null ...@@ -52,7 +52,7 @@ export const authReducer = (state = { loading: false, success: false, user: null
}; };
// Load user reducer // Load user reducer
export const loadedUserReducer = (state = { loading: true, success: false, user: null }, action) => { export const loadedUserReducer = (state = { loading: true, success: false, loadedUser: null }, action) => {
switch (action.type) { switch (action.type) {
case LOAD_USER_REQUEST: case LOAD_USER_REQUEST:
return { return {
...@@ -64,7 +64,7 @@ export const loadedUserReducer = (state = { loading: true, success: false, user: ...@@ -64,7 +64,7 @@ export const loadedUserReducer = (state = { loading: true, success: false, user:
return { return {
loading: false, loading: false,
isAuthenticated: true, isAuthenticated: true,
user: action.payload loadedUser: action.payload
}; };
case LOAD_USER_FAIL: case LOAD_USER_FAIL:
......
import { UPDATE_VENDOR_DETAILS_FAIL, UPDATE_VENDOR_DETAILS_REQUEST, UPDATE_VENDOR_DETAILS_SUCCESS, CLEAR_ERRORS, GET_LOGGED_IN_VENDOR_REQUEST, GET_LOGGED_IN_VENDOR_SUCCESS, GET_LOGGED_IN_VENDOR_FAIL, GET_VENDOR_DETAILS_FAIL, GET_VENDOR_DETAILS_SUCCESS, GET_VENDOR_DETAILS_REQUEST } from "../constants/vendorConstants"; import { UPDATE_VENDOR_DETAILS_FAIL, UPDATE_VENDOR_DETAILS_REQUEST, UPDATE_VENDOR_DETAILS_SUCCESS, CLEAR_ERRORS, GET_LOGGED_IN_VENDOR_REQUEST, GET_LOGGED_IN_VENDOR_SUCCESS, GET_LOGGED_IN_VENDOR_FAIL, GET_VENDOR_DETAILS_FAIL, GET_VENDOR_DETAILS_SUCCESS, GET_VENDOR_DETAILS_REQUEST, GET_ALL_VENDORS_REQUEST, GET_ALL_VENDORS_SUCCESS, GET_ALL_VENDORS_FAIL } from "../constants/vendorConstants";
// Load user reducer // Load user reducer
...@@ -94,4 +94,34 @@ export const getVendorDetailsReducer = (state = { loading: true, success: false, ...@@ -94,4 +94,34 @@ export const getVendorDetailsReducer = (state = { loading: true, success: false,
default: default:
return state; return state;
} }
};
export const getAllVendorsReducer = (state = { loading: true, success: false, allVendors: null }, action) => {
switch (action.type) {
case GET_ALL_VENDORS_REQUEST:
return {
loading: true,
};
case GET_ALL_VENDORS_SUCCESS:
return {
loading: false,
allVendors: action.payload
};
case GET_ALL_VENDORS_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
...@@ -1775,8 +1775,8 @@ span.form-error, ...@@ -1775,8 +1775,8 @@ span.form-error,
} }
.btnAdd.btnReject { .btnAdd.btnReject {
background-color: #ececec !important; background-color: #e02424 !important;
color: #161616 !important; color: #ffff !important;
} }
.btnAdd.btnReject:focus, .btnAdd.btnReject:focus,
...@@ -2823,6 +2823,18 @@ input[type="number"]::-webkit-outer-spin-button { ...@@ -2823,6 +2823,18 @@ input[type="number"]::-webkit-outer-spin-button {
color: #d1d1d1; color: #d1d1d1;
} }
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8); /* Semi-transparent black background */
z-index: 999; /* Ensure the overlay appears above other content */
}
@media (min-width: 992px) { @media (min-width: 992px) {
.navbar-expand-lg .navbar-nav .nav-link { .navbar-expand-lg .navbar-nav .nav-link {
margin: 0 2rem; margin: 0 2rem;
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!