From de3300af0224c5e430c8112a6a99f6f172bb2452 Mon Sep 17 00:00:00 2001 From: Raj-varu Date: Tue, 12 Mar 2024 16:07:39 +0530 Subject: [PATCH] Affiliate&Coupon Section added --- package.json | 1 + src/_nav.js | 21 ++ src/routes.js | 55 ++- src/views/Affiliate/AffiliateHistory.jsx | 225 +++++++++++ src/views/Affiliate/Affiliates.jsx | 391 +++++++++++++++++++ src/views/Affiliate/CouponHistory.jsx | 236 ++++++++++++ src/views/Affiliate/Coupons.jsx | 331 ++++++++++++++++ src/views/Affiliate/CreateAffiliate.jsx | 433 +++++++++++++++++++++ src/views/Affiliate/CreateCoupon.jsx | 355 ++++++++++++++++++ src/views/Affiliate/EditAffiliate.jsx | 458 +++++++++++++++++++++++ src/views/Affiliate/EditCoupon.jsx | 373 ++++++++++++++++++ src/views/Affiliate/PayAffiliate.jsx | 309 +++++++++++++++ 12 files changed, 3182 insertions(+), 6 deletions(-) create mode 100644 src/views/Affiliate/AffiliateHistory.jsx create mode 100644 src/views/Affiliate/Affiliates.jsx create mode 100644 src/views/Affiliate/CouponHistory.jsx create mode 100644 src/views/Affiliate/Coupons.jsx create mode 100644 src/views/Affiliate/CreateAffiliate.jsx create mode 100644 src/views/Affiliate/CreateCoupon.jsx create mode 100644 src/views/Affiliate/EditAffiliate.jsx create mode 100644 src/views/Affiliate/EditCoupon.jsx create mode 100644 src/views/Affiliate/PayAffiliate.jsx diff --git a/package.json b/package.json index f56c26e..3ed5dd9 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "bootstrap": "^5.1.3", "country-state-city": "^3.2.1", "md5": "^2.3.0", + "moment": "^2.30.1", "prop-types": "^15.7.2", "quill": "^1.3.7", "react": "18.0.0", diff --git a/src/_nav.js b/src/_nav.js index e55816f..4b49ef5 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -208,6 +208,27 @@ const _nav = [ }, ], }, + //Affiliate start + { + component: CNavGroup, + name: "Affiliate & Coupons", + icon: , + items: [ + { + component: CNavItem, + name: "Coupons", + icon: , + to: "/affiliate/coupons", + }, + { + component: CNavItem, + name: "Affiliates", + icon: , + to: "/affiliate/affiliates", + }, + ], + }, + //Affiliate end ]; export default _nav; diff --git a/src/routes.js b/src/routes.js index 187f7f1..56e9c3b 100644 --- a/src/routes.js +++ b/src/routes.js @@ -100,8 +100,16 @@ import Banners from "./views/Banner/banner"; import RegisterImage from "./views/Images/RegisterImage"; import LoginImage from "./views/Images/LoginImage"; import ShopImage from "./views/Images/ShopImage"; - - +//Affiliate +import Coupons from "./views/Affiliate/Coupons"; +import Affiliates from "./views/Affiliate/Affiliates"; +import CreateCoupon from "./views/Affiliate/CreateCoupon"; +import CreateAffiliate from "./views/Affiliate/CreateAffiliate"; +import EditAffiliate from "./views/Affiliate/EditAffiliate"; +import EditCoupon from "./views/Affiliate/EditCoupon"; +import PayAffiliate from "./views/Affiliate/PayAffiliate"; +import AffiliateHistory from "./views/Affiliate/AffiliateHistory"; +import CouponHistory from "./views/Affiliate/CouponHistory"; const routes = [ { path: "/", exact: true, name: "Home" }, @@ -391,11 +399,46 @@ const routes = [ path: "/seo/request/new", name: "seo Request", element: AddSeoRequest, - } - - - + }, // + //Affiliate Dashboard + { path: "/affiliate/coupons", name: "Coupon", element: Coupons }, + { path: "/affiliate/affiliates", name: "Affiliate", element: Affiliates }, + { + path: "/affiliate/coupons/create", + name: "Create Coupon", + element: CreateCoupon, + }, + { + path: "/affiliate/affiliates/create", + name: "Create Affiliate", + element: CreateAffiliate, + }, + { + path: "/affiliate/affiliates/edit/:id", + name: "Edit Affiliate", + element: EditAffiliate, + }, + { + path: "/affiliate/affiliates/pay/:id", + name: "Pay Affiliate", + element: PayAffiliate, + }, + { + path: "/affiliate/affiliates/history/:id", + name: "Pay Affiliate", + element: AffiliateHistory, + }, + { + path: "/affiliate/coupons/edit/:id", + name: "Edit Coupon", + element: EditCoupon, + }, + { + path: "/affiliate/coupons/history/:id", + name: "Edit Coupon", + element: CouponHistory, + }, ]; export default routes; diff --git a/src/views/Affiliate/AffiliateHistory.jsx b/src/views/Affiliate/AffiliateHistory.jsx new file mode 100644 index 0000000..dfb4c61 --- /dev/null +++ b/src/views/Affiliate/AffiliateHistory.jsx @@ -0,0 +1,225 @@ +import React, { useEffect, useState } from "react"; +import axios from "axios"; +import { Link, useNavigate, useParams } from "react-router-dom"; +import { Button, Pagination } from "@mui/material"; +import { isAutheticated } from "src/auth"; + +const AffiliateHistory = () => { + const id = useParams().id; + const token = isAutheticated(); + //Navigation + const navigate = useNavigate(); + const [apiData, setApiData] = useState([]); + const [name, setName] = useState(""); + const [loading, setLoading] = useState(true); + //Date format change function + const dateFormat = (inputDate) => { + const months = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ]; + const parts = inputDate.split("-"); + const rearrangedDate = `${parts[2]}-${months[parseInt(parts[1]) - 1]}-${ + parts[0] + }`; + // console.log(rearrangedDate); // Output: 11-Mar-2024 + return rearrangedDate; + }; + //Extract time from mongodb + const extractTime = (dateTimeString) => { + const date = new Date(dateTimeString); + const hours = date.getUTCHours().toString().padStart(2, "0"); + const minutes = date.getUTCMinutes().toString().padStart(2, "0"); + const seconds = date.getUTCSeconds().toString().padStart(2, "0"); + const time = `${hours}:${minutes}:${seconds}`; + // console.log(time); + return time; + }; + //Func to get all Affiliate data + const fetchHistoryData = () => { + axios + .get(`/api/v1/affiliate/history/${id}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((response) => { + // console.log(response.data.message.affiliate_pay_history); + setApiData(response.data.message.affiliate_pay_history); + setName(response.data.message.name); + setLoading(false); + }) + .catch((error) => { + setLoading(false); + const message = + error?.response?.data?.message || "Something went wrong!"; + console.log(message); + }); + }; + //Call api onLoad of page + useEffect(() => { + fetchHistoryData(); + }, []); + + //pagination related + const [itemPerPage, setItemPerPage] = useState(10); //pagination + const [page, setPage] = useState(1); //pagination + + const getPageCount = () => { + return Math.max(1, Math.ceil(apiData.length / itemPerPage)); + }; + + return ( +
+
+
+ {/* Coupon header start */} +
+
+
+
+

Payment History :{name}

+
+ +
+ + + +
+
+
+
+ {/* Coupon header End */} + {/* Coupon main body Start*/} +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ {/* Table Start */} +
+ + + + + + + + + + + {!loading && apiData.length === 0 && ( + + + + )} + {loading ? ( + + + + ) : ( + apiData && + apiData + .slice( + (`${page}` - 1) * itemPerPage, + `${page}` * itemPerPage + ) + .map((item, i) => ( + + + + + + + )) + )} + +
Transection IDAmountDateTime
+
No Data Available
+
Loading...
{item.transecId}₹{item.amount}{dateFormat(item.date)}{item.time}
+
+ {/* Table End */} + {/* Pagination div Start*/} +
+ setPage(value)} + /> +
+ {/* Pagination div End*/} + {/* Coupon main body End */} +
+
+
+ ); +}; + +export default AffiliateHistory; diff --git a/src/views/Affiliate/Affiliates.jsx b/src/views/Affiliate/Affiliates.jsx new file mode 100644 index 0000000..8ec890f --- /dev/null +++ b/src/views/Affiliate/Affiliates.jsx @@ -0,0 +1,391 @@ +import React, { useEffect, useState } from "react"; +import axios from "axios"; +import { Link, useNavigate } from "react-router-dom"; +import { Button, Pagination } from "@mui/material"; +import { isAutheticated } from "src/auth"; + +const Affiliates = () => { + const token = isAutheticated(); + //Navigation + const navigate = useNavigate(); + const [apiData, setApiData] = useState([]); + const [loading, setLoading] = useState(true); + + const handelSuspend = (id, active) => { + axios + .patch( + "api/v1/affiliate/suspend", + { + id: id, + is_affiliate_active: !active, + }, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ) + .then((res) => { + // Fetch data again after updating kind of updating page + fetchAffiliateData(); + }) + .catch((error) => { + const message = + error?.response?.data?.message || "Something went wrong!"; + console.log(message); + }); + }; + //Func to get all Affiliate data + const fetchAffiliateData = () => { + axios + .get("/api/v1/affiliate/getall", { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((response) => { + // console.log(response.data.message); + setLoading(false); + setApiData(response.data.message); + }) + .catch((error) => { + setLoading(false); + const message = + error?.response?.data?.message || "Something went wrong!"; + console.log(message); + }); + }; + //Call api onLoad of page + useEffect(() => { + fetchAffiliateData(); + }, []); + + //pagination related + const [itemPerPage, setItemPerPage] = useState(10); //pagination + const [page, setPage] = useState(1); //pagination + + //Create navigation + const navigCreate = () => { + navigate("/affiliate/affiliates/create"); + }; + const style = { + position: "absolute", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + width: 400, + bgcolor: "background.paper", + borderRadius: "0.5rem", + boxShadow: 24, + width: "500px", + padding: "1rem", + }; + const InputSpace = { + marginBottom: "1rem", + }; + + const getPageCount = () => { + return Math.max(1, Math.ceil(apiData.length / itemPerPage)); + }; + + return ( +
+
+
+ {/* Coupon header start */} +
+
+
+
+ Affiliates +
+ +
+ +
+
+
+
+ {/* Coupon header End */} + {/* Coupon main body Start*/} +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ {/* Table Start */} +
+ + + + + + + + + + + + + + {" "} + {!loading && apiData.length === 0 && ( + + + + )} + {loading ? ( + + + + ) : ( + apiData && + apiData + .slice( + (`${page}` - 1) * itemPerPage, + `${page}` * itemPerPage + ) + .map((item, i) => ( + + + {item.coupon_code ? ( + + ) : ( + + )} + {item.coupon_claimed ? ( + + ) : ( + + )} + {item.total_earning ? ( + + ) : ( + + )} + {item.total_earning ? ( + + ) : ( + + )} + {item.is_affiliate_active ? ( + + ) : ( + + )} + + + )) + )} + +
Affiliate Coupon CodeCoupon ClaimedTotal Amount EarnedAmount to be PaidStatusAction
+
No Data Available
+
Loading...
{item.name}{item.coupon_code}NONE{item.coupon_claimed}0₹{item.total_earning}₹0₹{item.total_earning - item.paid_amount}₹0 +

+ {" "} + active +

+
+

+ {" "} + unactive +

+
+ + + + + {item.total_earning - item.paid_amount != 0 ? ( + + + + ) : ( + + )} + + + +
+
+ {/* Table End */} + {/* Pagination div Start*/} +
+ setPage(value)} + /> +
+ {/* Pagination div End*/} + {/* Coupon main body End */} +
+
+
+ ); +}; + +export default Affiliates; diff --git a/src/views/Affiliate/CouponHistory.jsx b/src/views/Affiliate/CouponHistory.jsx new file mode 100644 index 0000000..8b7e88f --- /dev/null +++ b/src/views/Affiliate/CouponHistory.jsx @@ -0,0 +1,236 @@ +import React, { useEffect, useState } from "react"; +import axios from "axios"; +import { Link, useNavigate, useParams } from "react-router-dom"; +import { Button, Pagination } from "@mui/material"; +import { isAutheticated } from "src/auth"; +import moment from "moment"; + +const CouponHistory = () => { + const id = useParams().id; + const token = isAutheticated(); + //Navigation + const navigate = useNavigate(); + const [apiData, setApiData] = useState([]); + const [couponName, setCouponName] = useState([]); + const [loading, setLoading] = useState(true); //only for testing + //Date format change function + const dateFormat = (inputDate) => { + // Split the date string by spaces to get individual components + const dateComponents = inputDate.split(" "); + + // Extract day, month, and year from the components + const day = dateComponents[2]; + const monthName = dateComponents[1]; + const year = dateComponents[3]; + + // Map month names to their respective indexes + const monthsMap = { + Jan: "01", + Feb: "02", + Mar: "03", + Apr: "04", + May: "05", + Jun: "06", + Jul: "07", + Aug: "08", + Sep: "09", + Oct: "10", + Nov: "11", + Dec: "12", + }; + + // Get the numerical representation of the month + const month = monthsMap[monthName]; + + // Create the rearranged date string + const rearrangedDate = `${day} ${month} ${year}`; + + return rearrangedDate; + }; + //Extract time from mongodb + const extractTime = (dateTimeString) => { + const date = new Date(dateTimeString); + const hours = date.getUTCHours().toString().padStart(2, "0"); + const minutes = date.getUTCMinutes().toString().padStart(2, "0"); + const seconds = date.getUTCSeconds().toString().padStart(2, "0"); + const time = `${hours}:${minutes}:${seconds}`; + return time; + }; + //Func to get all Affiliate data + const fetchHistoryData = () => { + axios + .get(`/api/v1/coupon/history/${id}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((response) => { + // console.log(response.data.message.coupon_used_history); + setLoading(false); + setApiData(response.data.message.coupon_used_history); + setCouponName(response.data.message.coupon_used_history[0].couponCode); + }) + .catch((error) => { + setLoading(false); + const message = + error?.response?.data?.message || "Something went wrong!"; + console.log(message); + }); + }; + //Call api onLoad of page + useEffect(() => { + fetchHistoryData(); + }, []); + + //pagination related + const [itemPerPage, setItemPerPage] = useState(10); //pagination + const [page, setPage] = useState(1); //pagination + // console.log(apiData); + + const getPageCount = () => { + return Math.max(1, Math.ceil(apiData.length / itemPerPage)); + }; + + return ( +
+
+
+ {/* Coupon header start */} +
+
+
+
+ Coupon History {couponName} +
+ +
+ + + +
+
+
+
+ {/* Coupon header End */} + {/* Coupon main body Start*/} +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ {/* Table Start */} +
+ + + + + + + + + + + {!loading && apiData.length === 0 && ( + + + + )} + {loading ? ( + + + + ) : ( + apiData && + apiData + ?.slice( + (`${page}` - 1) * itemPerPage, + `${page}` * itemPerPage + ) + ?.map((item, i) => ( + + + + + + + )) + )} + +
Order IdUser IdDateTime
+
No Data Available
+
Loading...
{item.orderId}{item.userId}{dateFormat(item.date)}{moment(item.date).format("HH:mm:ss")}
+
+ {/* Table End */} + {/* Pagination div Start*/} +
+ setPage(value)} + /> +
+ {/* Pagination div End*/} + {/* Coupon main body End */} +
+
+
+ ); +}; + +export default CouponHistory; diff --git a/src/views/Affiliate/Coupons.jsx b/src/views/Affiliate/Coupons.jsx new file mode 100644 index 0000000..7456056 --- /dev/null +++ b/src/views/Affiliate/Coupons.jsx @@ -0,0 +1,331 @@ +import React, { useEffect, useState } from "react"; +import { Link, useNavigate } from "react-router-dom"; +import axios from "axios"; +import { Button, Pagination } from "@mui/material"; +import { isAutheticated } from "src/auth"; +const Coupons = () => { + const token = isAutheticated(); + //Navigation + const navigate = useNavigate(); + //pagination related + const [loading, setLoading] = useState(true); //only for testing + const [itemPerPage, setItemPerPage] = useState(10); //pagination + const [page, setPage] = useState(1); //pagination + const [apiData, setApiData] = useState([]); + //Handel Suspend + const handelSuspend = (id, active) => { + axios + .patch( + "api/v1/coupon/suspend", + { + id: id, + is_coupon_active: !active, + }, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ) + .then((res) => { + // Fetch data again after updating + getAllCoupon(); + }) + .catch((error) => { + const message = + error?.response?.data?.message || "Something went wrong!"; + console.log(message); + }); + }; + //Get all Coupons from the api + const getAllCoupon = () => { + axios + .get("/api/v1/coupon/getall", { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((response) => { + setLoading(false); + setApiData(response.data.message); + }) + .catch((error) => { + setLoading(false); + const message = + error?.response?.data?.message || "Something went wrong!"; + console.log(message); + }); + }; + //Calling api Onload of page + useEffect(() => { + getAllCoupon(); + }, []); + //Create navigation + const navigCreate = () => { + navigate("/affiliate/coupons/create"); + }; + const style = { + position: "absolute", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + width: 400, + bgcolor: "background.paper", + borderRadius: "0.5rem", + boxShadow: 24, + width: "500px", + padding: "1rem", + }; + const InputSpace = { + marginBottom: "1rem", + }; + + const getPageCount = () => { + return Math.max(1, Math.ceil(apiData?.length / itemPerPage)); + }; + return ( +
+
+
+ {/* Coupon header start */} +
+
+
+
+ Coupons +
+ +
+ +
+
+
+
+ {/* Coupon header End */} + {/* Coupon main body Start*/} +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ {/* Table Start */} +
+ + + + + + + + + + + + + {" "} + {!loading && apiData.length === 0 && ( + + + + )} + {loading ? ( + + + + ) : ( + apiData && + apiData + .slice( + (`${page}` - 1) * itemPerPage, + `${page}` * itemPerPage + ) + .map((item, i) => ( + + + + + + + + + )) + )} + +
Coupon Code AffiliateDiscountAffilite DiscountStatusAction
+
No Data Available
+
Loading...
+

+ {item.coupon_code} +

+
+

{item.name}

+
+

₹{item.discount_amount}

+
+

₹{item.affiliate_discount_amount}

+
+ {item.is_coupon_active ? ( +

+ {" "} + active +

+ ) : ( +

+ {" "} + unactive +

+ )} +
+ + + + + + + +
+
+ {/* Table End */} + {/* Pagination div Start*/} +
+ setPage(value)} + /> +
+ {/* Pagination div End*/} + {/* Coupon main body End */} +
+
+
+ ); +}; + +export default Coupons; diff --git a/src/views/Affiliate/CreateAffiliate.jsx b/src/views/Affiliate/CreateAffiliate.jsx new file mode 100644 index 0000000..4e3d1c2 --- /dev/null +++ b/src/views/Affiliate/CreateAffiliate.jsx @@ -0,0 +1,433 @@ +import React, { useEffect, useState } from "react"; +import Button from "@material-ui/core/Button"; +import { Link } from "react-router-dom"; +import swal from "sweetalert"; +import { Country, State, City } from "country-state-city"; +import axios from "axios"; +import { isAutheticated } from "src/auth"; + +const CreateAffiliate = () => { + const token = isAutheticated(); + const [loading, setLoading] = useState(false); + + //My states + const [name, setName] = useState(""); + const [mobile, setMobile] = useState(); + const [email, setEmail] = useState(""); + const [country, setCountry] = useState(""); + const [state, setState] = useState(""); + const [city, setCity] = useState(""); + const [address, setAddress] = useState(""); + const [pincode, setPincode] = useState(); + const [nameAsBank, setNameAsBank] = useState(""); + const [accountNo, setAccountNo] = useState(); + const [ifsc, setIfsc] = useState(""); + const [bankName, setBankName] = useState(""); + const [branchName, setBranchName] = useState(""); + //Handeling Country State City + const [stateListData, setStateListData] = useState(); + const [cityListData, setCityListData] = useState(); + + //Handel City State Country + const countrieList = Country.getAllCountries(); + // const stateList = State.getStatesOfCountry(); + // const cityList = City.getCitiesOfState("IN", "CT"); + // console.log("Cityyyyyyyyyyy", cityList); + useEffect(() => { + const countryCode = countrieList.find((item) => item.name === country); + if (countryCode) { + const states = State.getStatesOfCountry(countryCode.isoCode); + setStateListData(states); + } + }, [country, countrieList]); + + useEffect(() => { + if (state) { + const stateCode = stateListData.find((item) => item.name === state); + // console.log(stateCode); + if (stateCode) { + const cities = City.getCitiesOfState( + stateCode.countryCode, + stateCode.isoCode + ); + // console.log(cities); + setCityListData(cities); + } + } + }, [state, stateListData]); + //Handel Mobile Number + const handelNumber = (e) => { + if (!(e.target.value.length > 10)) { + setMobile(e.target.value); + } + }; + const handleCountry = async (e) => { + await setCountry(e.target.value); + if (stateListData || cityListData) { + setCity(""); + setState(""); + setCityListData([]); + setCountry(e.target.value); + } + }; + + const handleSubmit = () => { + if ( + name === "" || + mobile === 0 || + email == "" || + country === "" || + address === "" || + pincode === 0 || + nameAsBank === "" || + accountNo === 0 || + ifsc === "" || + bankName === "" || + branchName === "" + ) { + swal({ + title: "Warning", + text: "Fill all mandatory fields", + icon: "error", + button: "Close", + dangerMode: true, + }); + + return; + } + setLoading(true); + const formDataObject = { + name: name, + mobile: mobile, + email: email, + country: country, + state: state, + city: city, + address: address, + pincode: pincode, + nameAsBank: nameAsBank, + accountNo: accountNo, + ifsc: ifsc, + bankName: bankName, + branchName: branchName, + }; + + axios + .post("/api/v1/affiliate/create", formDataObject, { + headers: { + Authorization: `Bearer ${token}`, + + "Access-Control-Allow-Origin": "*", + }, + }) + .then((data) => { + // Handle the data returned by the server + setLoading(false); + setName(""); + setMobile(""); + setEmail(""); + setCountry(""); + setState(""); + setCity(""); + setAddress(""); + setPincode(""); + setNameAsBank(""); + setAccountNo(""); + setIfsc(""); + setBankName(""); + setBranchName(""); + swal({ + title: "Congratulations!!", + text: "The Coupon was Created successfully!", + icon: "success", + button: "OK", + }); + return; + }) + .catch((err) => { + // Handle errors + setLoading(false); + const message = err.response?.data?.message + ? err.response?.data?.message + : "Something went wrong!"; + swal({ + title: "Warning", + text: message, + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + }; + + return ( +
+
+
+
+
+ Add Affiliate +
+
+

+
+ +
+ + + + +
+
+
+
+
+
+
+
+
+ + setName(e.target.value)} + /> + {name ? ( + <> + + {25 - name.length} characters left + + + ) : ( + <> + )}{" "} +
+ +
+ + +
+ +
+ + setEmail(e.target.value)} + /> +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + setAddress(e.target.value)} + /> + {name ? ( + <> + + {25 - name.length} characters left + + + ) : ( + <> + )}{" "} +
+
+ + setPincode(e.target.value)} + /> + {name ? ( + <> + + {25 - name.length} characters left + + + ) : ( + <> + )}{" "} +
+
+
+
+
+
+
+
+ + setNameAsBank(e.target.value)} + /> +
+
+ + setAccountNo(e.target.value)} + /> +
+
+ + setIfsc(e.target.value)} + /> +
+
+ + setBankName(e.target.value)} + /> +
+
+ + setBranchName(e.target.value)} + /> +
+
+
+
+
+
+ ); +}; + +export default CreateAffiliate; diff --git a/src/views/Affiliate/CreateCoupon.jsx b/src/views/Affiliate/CreateCoupon.jsx new file mode 100644 index 0000000..602dd36 --- /dev/null +++ b/src/views/Affiliate/CreateCoupon.jsx @@ -0,0 +1,355 @@ +import React, { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import axios from "axios"; +import toast, { Toaster } from "react-hot-toast"; +import { Button, Box, TextField, Typography } from "@mui/material"; +import { isAutheticated } from "src/auth"; +const CreateCoupon = () => { + const token = isAutheticated(); + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); //only for testing + const [itemPerPage, setItemPerPage] = useState(10); //pagination + const [page, setPage] = useState(1); //pagination + //Form States + const [open, setOpen] = useState(false); + const [coupon, setCoupon] = useState(""); + const [discount, setDiscount] = useState(""); + const [affiliateDiscountAmt, setAffiliateDiscountAmt] = useState(""); + const [valid, setValid] = useState(""); + const [affiliate, setAffiliate] = useState(""); + //Form error states + const [couponError, setCouponError] = useState(false); + const [discountError, setDiscountError] = useState(false); + const [validError, setValidError] = useState(false); + const [affiliateError, setAffiliateError] = useState(false); + const [affiliateDiscountAmtError, setAffiliateDiscountAmtError] = + useState(false); + const [apiData, setApiData] = useState([]); + //Discount limit + const handelDiscount = (event) => { + let value = event.target.value; + if (parseInt(value) >= 9999) { + setDiscount(9999); + setDiscountError(true); + } else if (parseInt(value) < 0) { + setDiscount(0); + } else { + setDiscountError(false); + setDiscount(value); + } + }; + const handelAffilateDiscount = (event) => { + let value = event.target.value; + if (parseInt(value) >= 9999) { + setAffiliateDiscountAmt(9999); + setAffiliateDiscountAmtError(true); + } else if (parseInt(value) < 0) { + setDiscount(0); + } else { + setAffiliateDiscountAmtError(false); + setAffiliateDiscountAmt(value); + } + }; + //Handel Form Submition + const handelCreate = (e) => { + e.preventDefault(); + if (!(coupon.length === 8)) { + setCouponError(true); + toast.error("Code should be of 8 charecter"); + return; + } + if (valid === "") { + setValidError(true); + toast.error("Valid till is required"); + return; + } + if (affiliate === "") { + setAffiliateError(true); + toast.error("Affiliate is required"); + return; + } + if (discount == "") { + setDiscountError(true); + toast.error("Discount amount is required"); + return; + } + if (affiliateDiscountAmt == "") { + setAffiliateDiscountAmtError(true); + toast.error("Affiliate Discount Amount is required"); + return; + } + //Sending api Obj-------------------- + let formDataObject = { + coupon_code: coupon, + discount_amount: discount, + affiliate_discount_amount: affiliateDiscountAmt, + valid_till: valid, + is_coupon_active: true, + id: affiliate, + }; + + axios + .patch("/api/v1/coupon/create", formDataObject, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((data) => { + //reset Inputs + setDiscount(""); + setCoupon(""); + setValid(""); + setAffiliate(""); + fetchAffiliate(); + setCouponError(false); + setDiscountError(false); + setValidError(false); + setAffiliateError(false); + setAffiliateDiscountAmtError(false); + swal({ + title: "Congratulations!!", + text: "The Coupon was Created successfully!", + icon: "success", + button: "OK", + }); + }) + .catch((error) => { + // Handle errors + const message = error.response?.data?.message + ? error.response?.data?.message + : "Something went wrong!"; + toast.error(message); + console.error("There was a problem with your fetch operation:", error); + }) + .finally(() => { + // Reset the affiliate and affiliateError state + setAffiliateError(false); + // Show success message + // console.log(coupon, discount, valid, affiliate); + }); + }; + const InputSpace = { + marginBottom: "1rem", + width: "20rem ", + height: "45px", + }; + //Back to Coupons + const handelBack = () => { + navigate("/affiliate/coupons"); + }; + //Calling api to get Affiliates + const fetchAffiliate = () => { + axios + .get("/api/v1/coupon/getaffiliate", { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((response) => { + setApiData(response.data.message); + }) + .catch((error) => { + console.log(error.message); + }); + }; + //Calling api + useEffect(() => { + fetchAffiliate(); + }, []); + return ( +
+
+
+

Coupons

+
+
+
+ +
+
+ +
+
+
+
+
+
+ + + Coupon Code (Must be 8 digit) + + { + setCoupon(e.target.value); + }} + error={couponError} + style={{ width: "100%" }} + /> + {couponError ? ( + 8 characters required + ) : ( + "" + )} + + Discount Amount +
+
+ +
+ +
+ + Affiliate Discount Amount + +
+
+ +
+ +
+ + {affiliateDiscountAmtError ? ( + Max Amount Rs.9999 + ) : ( + "" + )} + + Coupon Valid Till: + { + setValid(e.target.value); + }} + type="date" + /> + {validError ? ( + + Validity Date is Required + + ) : ( + "" + )} + Select Affiliate + + {affiliateError ? ( + Affiliation is Required + ) : ( + "" + )} +
+
+
+
+
+
+ ); +}; + +export default CreateCoupon; diff --git a/src/views/Affiliate/EditAffiliate.jsx b/src/views/Affiliate/EditAffiliate.jsx new file mode 100644 index 0000000..c1ac546 --- /dev/null +++ b/src/views/Affiliate/EditAffiliate.jsx @@ -0,0 +1,458 @@ +import React, { useEffect, useState } from "react"; +import Button from "@material-ui/core/Button"; +import { Link, useNavigate, useParams } from "react-router-dom"; +import swal from "sweetalert"; +import { Country, State, City } from "country-state-city"; +import axios from "axios"; +import { isAutheticated } from "src/auth"; + +const EditAffiliate = () => { + const token = isAutheticated(); + const navigate = useNavigate(); + const id = useParams().id; + const [loading, setLoading] = useState(false); + + //My states + const [name, setName] = useState(""); + const [mobile, setMobile] = useState(); + const [email, setEmail] = useState(""); + const [country, setCountry] = useState(""); + const [state, setState] = useState(""); + const [city, setCity] = useState(""); + const [address, setAddress] = useState(""); + const [pincode, setPincode] = useState(); + const [nameAsBank, setNameAsBank] = useState(""); + const [accountNo, setAccountNo] = useState(); + const [ifsc, setIfsc] = useState(""); + const [bankName, setBankName] = useState(""); + const [branchName, setBranchName] = useState(""); + //Handel Mobile Number + const handelNumber = (e) => { + if (!(e.target.value.length > 10)) { + setMobile(e.target.value); + } + }; + //Handeling Country State City + const [stateListData, setStateListData] = useState(); + const [cityListData, setCityListData] = useState(); + const handleCountry = async (e) => { + await setCountry(e.target.value); + if (stateListData || cityListData) { + setCity(""); + setState(""); + setCityListData([]); + setCountry(e.target.value); + } + }; + //Handel City State Country + const countrieList = Country.getAllCountries(); + // const stateList = State.getStatesOfCountry(); + // const cityList = City.getCitiesOfState("IN", "CT"); + // console.log("Cityyyyyyyyyyy", cityList); + useEffect(() => { + const countryCode = countrieList.find((item) => item.name === country); + if (countryCode) { + const states = State.getStatesOfCountry(countryCode.isoCode); + setStateListData(states); + } + }, [country, countrieList]); + + useEffect(() => { + if (state) { + const stateCode = stateListData?.find((item) => item.name === state); + // console.log(stateCode); + if (stateCode) { + const cities = City.getCitiesOfState( + stateCode.countryCode, + stateCode.isoCode + ); + // console.log(cities); + setCityListData(cities); + } + } + }, [state, stateListData]); + //Calling to Fill form + useEffect(() => { + axios + .get(`/api/v1/affiliate/getone/${id}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + // console.log(res.data.message); + setName(res.data.message.name); + setMobile(res.data.message.mobile); + setEmail(res.data.message.email); + setCountry(res.data.message.country); + setState(res.data.message.state); + setCity(res.data.message.city); + setAddress(res.data.message.address); + setPincode(res.data.message.pincode); + setNameAsBank(res.data.message.nameAsBank); + setAccountNo(res.data.message.accountNo); + setIfsc(res.data.message.ifsc); + setBankName(res.data.message.bankName); + setBranchName(res.data.message.branchName); + }) + .catch((error) => { + const message = + error?.response?.data?.message || "Something went wrong!"; + console.log(message); + }); + }, []); + + //On form submit + const handleSubmit = () => { + if ( + name === "" || + mobile === 0 || + email == "" || + country === "" || + address === "" || + pincode === 0 || + nameAsBank === "" || + accountNo === 0 || + ifsc === "" || + bankName === "" || + branchName === "" + ) { + swal({ + title: "Warning", + text: "Fill all mandatory fields", + icon: "error", + button: "Close", + dangerMode: true, + }); + return; + } + setLoading(true); + const formDataObject = { + name: name, + mobile: mobile, + email: email, + country: country, + state: state, + city: city, + address: address, + pincode: pincode, + nameAsBank: nameAsBank, + accountNo: accountNo, + ifsc: ifsc, + bankName: bankName, + branchName: branchName, + }; + axios + .patch(`/api/v1/affiliate/edit/${id}`, formDataObject, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((data) => { + // Handle the data returned by the server + setLoading(false); + //Resetting Inputs + setName(""); + setMobile(""); + setEmail(""); + setCountry(""); + setState(""); + setCity(""); + setAddress(""); + setPincode(""); + setNameAsBank(""); + setAccountNo(""); + setIfsc(""); + setBankName(""); + setBranchName(""); + swal({ + title: "Congratulations!!", + text: "The Coupon was Created successfully!", + icon: "success", + button: "OK", + }); + navigate("/affiliate/affiliates"); + return; + }) + .catch((error) => { + setLoading(false); + const message = + error?.response?.data?.message || "Something went wrong!"; + console.log(message); + }); + }; + + return ( +
+
+
+
+
+ Edit Affiliate +
+
+

+
+ +
+ + + + +
+
+
+
+
+
+
+
+
+ + setName(e.target.value)} + /> + {name ? ( + <> + + {25 - name.length} characters left + + + ) : ( + <> + )}{" "} +
+ +
+ + +
+ +
+ + setEmail(e.target.value)} + /> +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + setAddress(e.target.value)} + /> + {name ? ( + <> + + {25 - name.length} characters left + + + ) : ( + <> + )}{" "} +
+
+ + setPincode(e.target.value)} + /> + {name ? ( + <> + + {25 - name.length} characters left + + + ) : ( + <> + )}{" "} +
+
+
+
+
+
+
+
+ + setNameAsBank(e.target.value)} + /> +
+
+ + setAccountNo(e.target.value)} + /> +
+
+ + setIfsc(e.target.value)} + /> +
+
+ + setBankName(e.target.value)} + /> +
+
+ + setBranchName(e.target.value)} + /> +
+
+
+
+
+
+ ); +}; + +export default EditAffiliate; diff --git a/src/views/Affiliate/EditCoupon.jsx b/src/views/Affiliate/EditCoupon.jsx new file mode 100644 index 0000000..7415d45 --- /dev/null +++ b/src/views/Affiliate/EditCoupon.jsx @@ -0,0 +1,373 @@ +import React, { useEffect, useState } from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import axios from "axios"; +import toast, { Toaster } from "react-hot-toast"; +import { Button, Box, TextField, Typography } from "@mui/material"; +import { isAutheticated } from "src/auth"; +const EditCoupon = () => { + const token = isAutheticated(); + const id = useParams().id; + const navigate = useNavigate(); + //Style for inputs + const InputSpace = { + marginBottom: "1rem", + width: "20rem ", + height: "45px", + }; + //Pagination Related + const [loading, setLoading] = useState(false); //only for testing + const [itemPerPage, setItemPerPage] = useState(10); //pagination + const [page, setPage] = useState(1); //pagination + //Form related + const [open, setOpen] = useState(false); + const [coupon, setCoupon] = useState(""); + const [discount, setDiscount] = useState(); + const [affiliateDiscountAmt, setAffiliateDiscountAmt] = useState(); + const [valid, setValid] = useState(""); + const [affiliate, setAffiliate] = useState(""); + //Form error states + const [couponError, setCouponError] = useState(false); + const [discountError, setDiscountError] = useState(false); + const [validError, setValidError] = useState(false); + const [affiliateError, setAffiliateError] = useState(false); + const [affiliateDiscountAmtError, setAffiliateDiscountAmtError] = + useState(false); + //Start of Page + const [apiData, setApiData] = useState([]); + //Discount limit + const handelDiscount = (event) => { + let value = event.target.value; + if (parseInt(value) >= 9999) { + setDiscount(9999); + setDiscountError(true); + } else if (parseInt(value) < 0) { + setDiscount(0); + } else { + setDiscountError(false); + setDiscount(value); + } + }; + //Affiliate Earning Handler + const handelAffilateDiscount = (event) => { + let value = event.target.value; + if (parseInt(value) >= 9999) { + setAffiliateDiscountAmt(9999); + setAffiliateDiscountAmtError(true); + } else if (parseInt(value) < 0) { + setDiscount(0); + } else { + setAffiliateDiscountAmtError(false); + setAffiliateDiscountAmt(value); + } + }; + //Handel Form Submition + const handelCreate = (e) => { + e.preventDefault(); + if (!(coupon.length === 8)) { + setCouponError(true); + toast.error("Code should be of 8 charecter"); + return; + } + if (valid === "") { + setValidError(true); + toast.error("Valid till is required"); + return; + } + if (affiliate === "") { + setAffiliateError(true); + toast.error("Affiliate is required"); + return; + } + if (discount === 0) { + setDiscountError(true); + toast.error("Discount amount is required"); + return; + } + //Testing Validation for Affiliate Amount + if (!affiliateDiscountAmt) { + setAffiliateDiscountAmtError(true); + toast.error("Affiliate Discount Amount is required"); + return; + } + if (affiliateDiscountAmt === 0 || affiliateDiscountAmt === "") { + setAffiliateDiscountAmtError(true); + toast.error("Affiliate Discount Amount is required"); + return; + } + //Sending api -------------------- + let formDataObject = { + coupon_code: coupon, + discount_amount: discount, + affiliate_discount_amount: affiliateDiscountAmt, + valid_till: valid, + is_coupon_active: true, + id: affiliate, + }; + //PATCH REQUEST + axios + .patch(`/api/v1/coupon/edit/${id}`, formDataObject, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((data) => { + //Reset Inputs + // console.log("Response:", data); + setDiscount(""); + setCoupon(""); + setValid(""); + setAffiliate(""); + setAffiliateDiscountAmt(""); + // fetchCoupon(); + setCouponError(false); + setDiscountError(false); + setValidError(false); + setAffiliateError(false); + setAffiliateDiscountAmtError(false); + swal({ + title: "Congratulations!!", + text: "The Coupon was Edited successfully!", + icon: "success", + button: "OK", + }); + navigate("/affiliate/coupons"); + }) + .catch((error) => { + // Handle errors + const message = error.response?.data?.message + ? error.response?.data?.message + : "Something went wrong!"; + + toast.error(message); + console.error("There was a problem with your fetch operation:", error); + }) + .finally(() => { + setAffiliateError(false); + }); + }; + + //Back to Coupons + const handelBack = () => { + navigate("/affiliate/coupons"); + }; + + //Fetch coupon data + const fetchCoupon = () => { + axios + .get(`/api/v1/coupon/getone/${id}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + setCoupon(res.data.message.coupon_code); + setDiscount(res.data.message.discount_amount); + setAffiliateDiscountAmt(res.data.message.affiliate_discount_amount); + setValid(res.data.message.valid_till); + setApiData({ + name: res.data.message.name, + mobile: res.data.message.mobile, + }); + setAffiliate(id); + }) + .catch((error) => { + const message = + error?.response?.data?.message || "Something went wrong!"; + console.log(message); + }); + }; + + //Calling to fill form and Affiliate + useEffect(() => { + fetchCoupon(); + }, []); + + return ( +
+
+
+

Edit Coupons

+
+
+
+ +
+
+ +
+
+
+
+
+
+ + Coupon Code + { + setCoupon(e.target.value); + }} + error={couponError} + style={{ width: "100%" }} + /> + {couponError ? ( + 8 characters required + ) : ( + "" + )} + + Discount Amount +
+
+ +
+ +
+ + Affiliate Discount Amount + +
+
+ +
+ +
+ + {affiliateDiscountAmtError ? ( + Max Amount Rs.9999 + ) : ( + "" + )} + + Coupon Valid Till: + { + setValid(e.target.value); + }} + type="date" + /> + {validError ? ( + + Validity Date is Required + + ) : ( + "" + )} + Select Affiliate + + {affiliateError ? ( + Affiliation is Required + ) : ( + "" + )} +
+
+
+
+
+
+ ); +}; + +export default EditCoupon; diff --git a/src/views/Affiliate/PayAffiliate.jsx b/src/views/Affiliate/PayAffiliate.jsx new file mode 100644 index 0000000..7349921 --- /dev/null +++ b/src/views/Affiliate/PayAffiliate.jsx @@ -0,0 +1,309 @@ +import React, { useEffect, useState } from "react"; +import { Link, useNavigate, useParams } from "react-router-dom"; +import axios from "axios"; +import toast, { Toaster } from "react-hot-toast"; +import { Button, Box, TextField, Typography } from "@mui/material"; +import { isAutheticated } from "src/auth"; +const PayAffiliate = () => { + const token = isAutheticated(); + const id = useParams().id; + const navigate = useNavigate(); + //Style for inputs + const InputSpace = { + marginBottom: "1rem", + width: "20rem ", + height: "45px", + }; + //Set Affiliate Data + const [affiliate, setAffiliate] = useState(""); + const [affiliateID, setAffiliateID] = useState(""); + const [noOfCoupons, setNoOfCoupons] = useState(""); + const [amountToPay, setAmountToPay] = useState(""); + const [coupon, setCoupon] = useState(""); + const [nameAsBank, setNameAsBank] = useState(""); + const [accountNo, setAccountNo] = useState(""); + const [ifsc, setIfsc] = useState(""); + const [bankName, setBankName] = useState(""); + const [branchName, setBranchName] = useState(""); + const [affiliateDiscountAmt, setAffiliateDiscountAmt] = useState(); + //Form related + const [amount, setAmount] = useState(); + const [transecId, setTransecId] = useState(""); + const [date, setDate] = useState(""); + const [time, setTime] = useState(""); + //Handel Pay + const handlePay = (e) => { + e.preventDefault(); + // console.log(amount, transecId, date); + const formDataObject = { + noOfCoupons, + amountToPay, + amount, + transecId, + date, + time, + }; + axios + .post(`/api/v1/affiliate/pay/${id}`, formDataObject, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((data) => { + swal({ + title: "Congratulations!!", + text: "Successfully Payed!", + icon: "success", + button: "OK", + }); + navigate("/affiliate/affiliates"); + }) + .catch((error) => { + // Handle errors + const message = error.response?.data?.message + ? error.response?.data?.message + : "Something went wrong!"; + toast.error(message); + console.error("Error in Payment:", error); + }); + }; + + //Fetch coupon data + const fetchPayData = () => { + axios + .get(`/api/v1/affiliate/getpay/${id}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + // console.log(res.data.message); + setAffiliate(res.data.message.name); + setNoOfCoupons( + res.data.message?.coupon_claimed - res.data.message?.no_of_paid_coupon + ); + setAmountToPay( + res.data.message.total_earning - res.data.message.paid_amount + ); + setAmount( + res.data.message.total_earning - res.data.message.paid_amount + ); + setCoupon(res.data.message.coupon_code); + setAffiliateDiscountAmt(res.data.message.affiliate_discount_amount); + setAffiliateID(id); + setNameAsBank(res.data.message.nameAsBank); + setAccountNo(res.data.message.accountNo); + setIfsc(res.data.message.ifsc); + setBankName(res.data.message.bankName); + setBranchName(res.data.message.branchName); + }) + .catch((error) => { + const message = + error?.response?.data?.message || "Something went wrong!"; + console.log(message); + }); + }; + + //Calling to fill form and Affiliate + useEffect(() => { + fetchPayData(); + }, []); + + return ( + <> +
+ + + +
+
+
+
+
+
+
+ + Affiliate Name: + {affiliate} + + + Coupon Code: + {coupon} + + + + Per coupon price:{" "} + + ₹{affiliateDiscountAmt} + + + + No of coupon paying for:{" "} + + {noOfCoupons} Units + + + + Amount to be paid:{" "} + + ₹{amountToPay} + +
+
+
+
+
+
+
+
+
+
+ + + Name as per Bank records:{" "} + + {nameAsBank} + + + Account Number: + {accountNo} + + + IFSC Code: + {ifsc} + + + Bank Name: + {bankName} + + + Branch Name: + {branchName} + +
+
+
+
+
+
+
+
+
+
+
+
+ + setTransecId(e.target.value)} + required="true" + type="text" + className="form-control mb-3 col-lg-4 col-md-12 col-sm-12 mr-5" + id="ifsc" + /> + + setDate(e.target.value)} + className="form-control mb-3 col-lg-3 col-md-12 col-sm-12" + id="ifsc" + /> +
+ +
+
+ + setTime(e.target.value)} + className="form-control mb-3 col-lg-3 col-md-12 col-sm-12 mr-5" + id="ifsc" + /> + {/* */} + + Amount Rs. + + setAmount(e.target.value)} + id="amount" + /> + + +
+
+
+
+
+
+
+ + ); +}; + +export default PayAffiliate;