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 */}
+
+
+
+
+ Transection ID |
+ Amount |
+ Date |
+ Time |
+
+
+
+ {!loading && apiData.length === 0 && (
+
+
+ No Data Available
+ |
+
+ )}
+ {loading ? (
+
+ Loading... |
+
+ ) : (
+ apiData &&
+ apiData
+ .slice(
+ (`${page}` - 1) * itemPerPage,
+ `${page}` * itemPerPage
+ )
+ .map((item, i) => (
+
+ {item.transecId} |
+ ₹{item.amount} |
+ {dateFormat(item.date)} |
+ {item.time} |
+
+ ))
+ )}
+
+
+
+ {/* Table End */}
+ {/* Pagination div Start*/}
+
+ {/* 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 */}
+
+
+
+
+ Affiliate |
+ Coupon Code |
+ Coupon Claimed |
+ Total Amount Earned |
+ Amount to be Paid |
+ Status |
+ Action |
+
+
+
+ {" "}
+ {!loading && apiData.length === 0 && (
+
+
+ No Data Available
+ |
+
+ )}
+ {loading ? (
+
+ Loading... |
+
+ ) : (
+ apiData &&
+ apiData
+ .slice(
+ (`${page}` - 1) * itemPerPage,
+ `${page}` * itemPerPage
+ )
+ .map((item, i) => (
+
+ {item.name} |
+ {item.coupon_code ? (
+ {item.coupon_code} |
+ ) : (
+ NONE |
+ )}
+ {item.coupon_claimed ? (
+ {item.coupon_claimed} |
+ ) : (
+ 0 |
+ )}
+ {item.total_earning ? (
+ ₹{item.total_earning} |
+ ) : (
+ ₹0 |
+ )}
+ {item.total_earning ? (
+ ₹{item.total_earning - item.paid_amount} |
+ ) : (
+ ₹0 |
+ )}
+ {item.is_affiliate_active ? (
+
+
+ {" "}
+ active
+
+ |
+ ) : (
+
+
+ {" "}
+ unactive
+
+ |
+ )}
+
+
+
+
+
+ {item.total_earning - item.paid_amount != 0 ? (
+
+
+
+ ) : (
+
+ )}
+
+
+
+ |
+
+ ))
+ )}
+
+
+
+ {/* Table End */}
+ {/* Pagination div Start*/}
+
+ {/* 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 */}
+
+
+
+
+ Order Id |
+ User Id |
+ Date |
+ Time |
+
+
+
+ {!loading && apiData.length === 0 && (
+
+
+ No Data Available
+ |
+
+ )}
+ {loading ? (
+
+ Loading... |
+
+ ) : (
+ apiData &&
+ apiData
+ ?.slice(
+ (`${page}` - 1) * itemPerPage,
+ `${page}` * itemPerPage
+ )
+ ?.map((item, i) => (
+
+ {item.orderId} |
+ {item.userId} |
+ {dateFormat(item.date)} |
+ {moment(item.date).format("HH:mm:ss")} |
+
+ ))
+ )}
+
+
+
+ {/* Table End */}
+ {/* Pagination div Start*/}
+
+ {/* 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 */}
+
+
+
+
+ Coupon Code |
+ Affiliate |
+ Discount |
+ Affilite Discount |
+ Status |
+ Action |
+
+
+
+ {" "}
+ {!loading && apiData.length === 0 && (
+
+
+ No Data Available
+ |
+
+ )}
+ {loading ? (
+
+ Loading... |
+
+ ) : (
+ apiData &&
+ apiData
+ .slice(
+ (`${page}` - 1) * itemPerPage,
+ `${page}` * itemPerPage
+ )
+ .map((item, i) => (
+
+
+
+ {item.coupon_code}
+
+ |
+
+ {item.name}
+ |
+
+ ₹{item.discount_amount}
+ |
+
+ ₹{item.affiliate_discount_amount}
+ |
+
+ {item.is_coupon_active ? (
+
+ {" "}
+ active
+
+ ) : (
+
+ {" "}
+ unactive
+
+ )}
+ |
+
+
+
+
+
+
+
+
+ |
+
+ ))
+ )}
+
+
+
+ {/* Table End */}
+ {/* Pagination div Start*/}
+
+ {/* 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
+
+ >
+ ) : (
+ <>>
+ )}{" "}
+
+
+
+
+
+
+
+ );
+};
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+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
+
+ >
+ ) : (
+ <>>
+ )}{" "}
+
+
+
+
+
+
+
+ );
+};
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+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}
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default PayAffiliate;