Affiliate&Coupon Section added
This commit is contained in:
parent
248e0f05e0
commit
de3300af02
@ -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",
|
||||
|
21
src/_nav.js
21
src/_nav.js
@ -208,6 +208,27 @@ const _nav = [
|
||||
},
|
||||
],
|
||||
},
|
||||
//Affiliate start
|
||||
{
|
||||
component: CNavGroup,
|
||||
name: "Affiliate & Coupons",
|
||||
icon: <CIcon icon={cilCart} customClassName="nav-icon" />,
|
||||
items: [
|
||||
{
|
||||
component: CNavItem,
|
||||
name: "Coupons",
|
||||
icon: <CIcon icon={cilNotes} customClassName="nav-icon" />,
|
||||
to: "/affiliate/coupons",
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: "Affiliates",
|
||||
icon: <CIcon icon={cilNotes} customClassName="nav-icon" />,
|
||||
to: "/affiliate/affiliates",
|
||||
},
|
||||
],
|
||||
},
|
||||
//Affiliate end
|
||||
];
|
||||
|
||||
export default _nav;
|
||||
|
@ -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;
|
||||
|
225
src/views/Affiliate/AffiliateHistory.jsx
Normal file
225
src/views/Affiliate/AffiliateHistory.jsx
Normal file
@ -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 (
|
||||
<div className="main-content">
|
||||
<div className="my-3 page-content">
|
||||
<div className="container-fluid">
|
||||
{/* Coupon header start */}
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div
|
||||
style={{ fontSize: "22px", fontWeight: "bold" }}
|
||||
className="fw-bold"
|
||||
>
|
||||
<p>Payment History :{name}</p>
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Link to="/affiliate/affiliates">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
marginRight: "1rem",
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Coupon header End */}
|
||||
{/* Coupon main body Start*/}
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
<div className="col-sm-12 col-md-12">
|
||||
<div className="dataTables_length">
|
||||
<label className="w-100">
|
||||
Show
|
||||
<select
|
||||
style={{ width: "10%" }}
|
||||
onChange={(e) => setItemPerPage(e.target.value)}
|
||||
className="
|
||||
select-w
|
||||
custom-select custom-select-sm
|
||||
form-control form-control-sm
|
||||
"
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
entries
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Table Start */}
|
||||
<div className="table-responsive table-shoot mt-3">
|
||||
<table
|
||||
className="table table-centered table-nowrap"
|
||||
style={{ border: "1px solid" }}
|
||||
>
|
||||
<thead
|
||||
className="thead-info"
|
||||
style={{ background: "rgb(140, 213, 213)" }}
|
||||
>
|
||||
<tr>
|
||||
<th>Transection ID</th>
|
||||
<th>Amount</th>
|
||||
<th>Date</th>
|
||||
<th>Time</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{!loading && apiData.length === 0 && (
|
||||
<tr className="text-center">
|
||||
<td>
|
||||
<h5>No Data Available</h5>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td className="text-center">Loading...</td>
|
||||
</tr>
|
||||
) : (
|
||||
apiData &&
|
||||
apiData
|
||||
.slice(
|
||||
(`${page}` - 1) * itemPerPage,
|
||||
`${page}` * itemPerPage
|
||||
)
|
||||
.map((item, i) => (
|
||||
<tr key={i}>
|
||||
<td>{item.transecId}</td>
|
||||
<td>₹{item.amount}</td>
|
||||
<td>{dateFormat(item.date)}</td>
|
||||
<td>{item.time}</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/* Table End */}
|
||||
{/* Pagination div Start*/}
|
||||
<div style={{ display: "flex", justifyContent: "right" }}>
|
||||
<Pagination
|
||||
style={{ margin: "2rem" }}
|
||||
variant="outlined"
|
||||
size="large"
|
||||
count={getPageCount()}
|
||||
color="primary"
|
||||
onChange={(event, value) => setPage(value)}
|
||||
/>
|
||||
</div>
|
||||
{/* Pagination div End*/}
|
||||
{/* Coupon main body End */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AffiliateHistory;
|
391
src/views/Affiliate/Affiliates.jsx
Normal file
391
src/views/Affiliate/Affiliates.jsx
Normal file
@ -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 (
|
||||
<div className="main-content">
|
||||
<div className="my-3 page-content">
|
||||
<div className="container-fluid">
|
||||
{/* Coupon header start */}
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div
|
||||
style={{ fontSize: "22px", fontWeight: "bold" }}
|
||||
className="fw-bold"
|
||||
>
|
||||
Affiliates
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
onClick={navigCreate}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
>
|
||||
Add New Affiliate
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Coupon header End */}
|
||||
{/* Coupon main body Start*/}
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
<div className="col-sm-12 col-md-12">
|
||||
<div className="dataTables_length">
|
||||
<label className="w-100">
|
||||
Show
|
||||
<select
|
||||
style={{ width: "10%" }}
|
||||
onChange={(e) => setItemPerPage(e.target.value)}
|
||||
className="
|
||||
select-w
|
||||
custom-select custom-select-sm
|
||||
form-control form-control-sm
|
||||
"
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
entries
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Table Start */}
|
||||
<div className="table-responsive table-shoot mt-3">
|
||||
<table
|
||||
className="table table-centered table-nowrap"
|
||||
style={{ border: "1px solid" }}
|
||||
>
|
||||
<thead
|
||||
className="thead-info"
|
||||
style={{ background: "rgb(140, 213, 213)" }}
|
||||
>
|
||||
<tr>
|
||||
<th> Affiliate</th>
|
||||
<th> Coupon Code</th>
|
||||
<th>Coupon Claimed</th>
|
||||
<th>Total Amount Earned</th>
|
||||
<th>Amount to be Paid</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{" "}
|
||||
{!loading && apiData.length === 0 && (
|
||||
<tr className="text-center">
|
||||
<td>
|
||||
<h5>No Data Available</h5>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td className="text-center">Loading...</td>
|
||||
</tr>
|
||||
) : (
|
||||
apiData &&
|
||||
apiData
|
||||
.slice(
|
||||
(`${page}` - 1) * itemPerPage,
|
||||
`${page}` * itemPerPage
|
||||
)
|
||||
.map((item, i) => (
|
||||
<tr key={i}>
|
||||
<td>{item.name}</td>
|
||||
{item.coupon_code ? (
|
||||
<td>{item.coupon_code}</td>
|
||||
) : (
|
||||
<td>NONE</td>
|
||||
)}
|
||||
{item.coupon_claimed ? (
|
||||
<td>{item.coupon_claimed}</td>
|
||||
) : (
|
||||
<td>0</td>
|
||||
)}
|
||||
{item.total_earning ? (
|
||||
<td>₹{item.total_earning}</td>
|
||||
) : (
|
||||
<td>₹0</td>
|
||||
)}
|
||||
{item.total_earning ? (
|
||||
<td>₹{item.total_earning - item.paid_amount}</td>
|
||||
) : (
|
||||
<td>₹0</td>
|
||||
)}
|
||||
{item.is_affiliate_active ? (
|
||||
<td>
|
||||
<p
|
||||
style={{
|
||||
backgroundColor: "green",
|
||||
color: "white",
|
||||
display: "inline-block",
|
||||
padding: "2px",
|
||||
width: "65px",
|
||||
borderRadius: "8px",
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
{" "}
|
||||
active
|
||||
</p>
|
||||
</td>
|
||||
) : (
|
||||
<td>
|
||||
<p
|
||||
style={{
|
||||
backgroundColor: "red",
|
||||
color: "white",
|
||||
display: "inline-block",
|
||||
padding: "2px",
|
||||
width: "65px",
|
||||
textAlign: "center",
|
||||
borderRadius: "8px",
|
||||
}}
|
||||
>
|
||||
{" "}
|
||||
unactive
|
||||
</p>
|
||||
</td>
|
||||
)}
|
||||
<td>
|
||||
<Link to={`/affiliate/affiliates/edit/${item._id}`}>
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
}}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-primary btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</Link>
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
background: `${
|
||||
item.is_affiliate_active ? "red" : "green"
|
||||
}`,
|
||||
}}
|
||||
onClick={() =>
|
||||
handelSuspend(item._id, item.is_affiliate_active)
|
||||
}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
{item.is_affiliate_active ? "Suspend" : "Activate"}
|
||||
</button>
|
||||
{item.total_earning - item.paid_amount != 0 ? (
|
||||
<Link to={`/affiliate/affiliates/pay/${item._id}`}>
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
background: "green",
|
||||
}}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
Pay
|
||||
</button>
|
||||
</Link>
|
||||
) : (
|
||||
<button
|
||||
disabled
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
background: "green",
|
||||
}}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
Pay
|
||||
</button>
|
||||
)}
|
||||
<Link
|
||||
to={`/affiliate/affiliates/history/${item._id}`}
|
||||
>
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
background: "grey",
|
||||
}}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
History
|
||||
</button>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/* Table End */}
|
||||
{/* Pagination div Start*/}
|
||||
<div style={{ display: "flex", justifyContent: "right" }}>
|
||||
<Pagination
|
||||
style={{ margin: "2rem" }}
|
||||
variant="outlined"
|
||||
size="large"
|
||||
count={getPageCount()}
|
||||
color="primary"
|
||||
onChange={(event, value) => setPage(value)}
|
||||
/>
|
||||
</div>
|
||||
{/* Pagination div End*/}
|
||||
{/* Coupon main body End */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Affiliates;
|
236
src/views/Affiliate/CouponHistory.jsx
Normal file
236
src/views/Affiliate/CouponHistory.jsx
Normal file
@ -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 (
|
||||
<div className="main-content">
|
||||
<div className="my-3 page-content">
|
||||
<div className="container-fluid">
|
||||
{/* Coupon header start */}
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div
|
||||
style={{ fontSize: "22px", fontWeight: "bold" }}
|
||||
className="fw-bold"
|
||||
>
|
||||
Coupon History {couponName}
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Link to="/affiliate/affiliates">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Coupon header End */}
|
||||
{/* Coupon main body Start*/}
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
<div className="col-sm-12 col-md-12">
|
||||
<div className="dataTables_length">
|
||||
<label className="w-100">
|
||||
Show
|
||||
<select
|
||||
style={{ width: "10%" }}
|
||||
onChange={(e) => setItemPerPage(e.target.value)}
|
||||
className="
|
||||
select-w
|
||||
custom-select custom-select-sm
|
||||
form-control form-control-sm
|
||||
"
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
entries
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Table Start */}
|
||||
<div className="table-responsive table-shoot mt-3">
|
||||
<table
|
||||
className="table table-centered table-nowrap"
|
||||
style={{ border: "1px solid" }}
|
||||
>
|
||||
<thead
|
||||
className="thead-info"
|
||||
style={{ background: "rgb(140, 213, 213)" }}
|
||||
>
|
||||
<tr>
|
||||
<th>Order Id</th>
|
||||
<th>User Id</th>
|
||||
<th>Date</th>
|
||||
<th>Time</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{!loading && apiData.length === 0 && (
|
||||
<tr className="text-center">
|
||||
<td>
|
||||
<h5>No Data Available</h5>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td className="text-center">Loading...</td>
|
||||
</tr>
|
||||
) : (
|
||||
apiData &&
|
||||
apiData
|
||||
?.slice(
|
||||
(`${page}` - 1) * itemPerPage,
|
||||
`${page}` * itemPerPage
|
||||
)
|
||||
?.map((item, i) => (
|
||||
<tr key={i}>
|
||||
<td>{item.orderId}</td>
|
||||
<td>{item.userId}</td>
|
||||
<td>{dateFormat(item.date)}</td>
|
||||
<td>{moment(item.date).format("HH:mm:ss")}</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/* Table End */}
|
||||
{/* Pagination div Start*/}
|
||||
<div style={{ display: "flex", justifyContent: "right" }}>
|
||||
<Pagination
|
||||
style={{ margin: "2rem" }}
|
||||
variant="outlined"
|
||||
size="large"
|
||||
count={getPageCount()}
|
||||
color="primary"
|
||||
onChange={(event, value) => setPage(value)}
|
||||
/>
|
||||
</div>
|
||||
{/* Pagination div End*/}
|
||||
{/* Coupon main body End */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CouponHistory;
|
331
src/views/Affiliate/Coupons.jsx
Normal file
331
src/views/Affiliate/Coupons.jsx
Normal file
@ -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 (
|
||||
<div className="main-content">
|
||||
<div className="my-3 page-content">
|
||||
<div className="container-fluid">
|
||||
{/* Coupon header start */}
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: "22px" }} className="fw-bold">
|
||||
Coupons
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
onClick={navigCreate}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
>
|
||||
Add New Coupon
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Coupon header End */}
|
||||
{/* Coupon main body Start*/}
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
<div className="col-sm-12 col-md-12">
|
||||
<div className="dataTables_length">
|
||||
<label className="w-100">
|
||||
Show
|
||||
<select
|
||||
style={{ width: "10%" }}
|
||||
onChange={(e) => setItemPerPage(e.target.value)}
|
||||
className="
|
||||
select-w
|
||||
custom-select custom-select-sm
|
||||
form-control form-control-sm
|
||||
"
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
entries
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Table Start */}
|
||||
<div className="table-responsive table-shoot mt-3">
|
||||
<table
|
||||
className="table table-centered table-nowrap"
|
||||
style={{ border: "1px solid" }}
|
||||
>
|
||||
<thead
|
||||
className="thead-info"
|
||||
style={{ background: "rgb(140, 213, 213)" }}
|
||||
>
|
||||
<tr>
|
||||
<th> Coupon Code</th>
|
||||
<th> Affiliate</th>
|
||||
<th>Discount</th>
|
||||
<th>Affilite Discount</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{" "}
|
||||
{!loading && apiData.length === 0 && (
|
||||
<tr className="text-center">
|
||||
<td>
|
||||
<h5>No Data Available</h5>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td className="text-center">Loading...</td>
|
||||
</tr>
|
||||
) : (
|
||||
apiData &&
|
||||
apiData
|
||||
.slice(
|
||||
(`${page}` - 1) * itemPerPage,
|
||||
`${page}` * itemPerPage
|
||||
)
|
||||
.map((item, i) => (
|
||||
<tr key={i}>
|
||||
<td>
|
||||
<p style={{ fontWeight: "bold" }}>
|
||||
{item.coupon_code}
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>{item.name}</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>₹{item.discount_amount}</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>₹{item.affiliate_discount_amount}</p>
|
||||
</td>
|
||||
<td>
|
||||
{item.is_coupon_active ? (
|
||||
<p
|
||||
style={{
|
||||
backgroundColor: "green",
|
||||
color: "white",
|
||||
display: "inline-block",
|
||||
padding: "2px",
|
||||
width: "65px",
|
||||
borderRadius: "8px",
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
{" "}
|
||||
active
|
||||
</p>
|
||||
) : (
|
||||
<p
|
||||
style={{
|
||||
backgroundColor: "red",
|
||||
color: "white",
|
||||
display: "inline-block",
|
||||
padding: "2px",
|
||||
width: "65px",
|
||||
textAlign: "center",
|
||||
borderRadius: "8px",
|
||||
}}
|
||||
>
|
||||
{" "}
|
||||
unactive
|
||||
</p>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<Link to={`/affiliate/coupons/edit/${item._id}`}>
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
}}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-primary btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</Link>
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
background: `${
|
||||
item.is_coupon_active ? "red" : "green"
|
||||
}`,
|
||||
}}
|
||||
onClick={() =>
|
||||
handelSuspend(item._id, item.is_coupon_active)
|
||||
}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
{item.is_coupon_active ? "Suspend" : "Activate"}
|
||||
</button>
|
||||
<Link to={`/affiliate/coupons/history/${item._id}`}>
|
||||
<button
|
||||
style={{
|
||||
color: "white",
|
||||
marginRight: "1rem",
|
||||
background: "grey",
|
||||
}}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
History
|
||||
</button>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/* Table End */}
|
||||
{/* Pagination div Start*/}
|
||||
<div style={{ display: "flex", justifyContent: "right" }}>
|
||||
<Pagination
|
||||
style={{ margin: "2rem" }}
|
||||
variant="outlined"
|
||||
size="large"
|
||||
count={getPageCount()}
|
||||
color="primary"
|
||||
onChange={(event, value) => setPage(value)}
|
||||
/>
|
||||
</div>
|
||||
{/* Pagination div End*/}
|
||||
{/* Coupon main body End */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Coupons;
|
433
src/views/Affiliate/CreateAffiliate.jsx
Normal file
433
src/views/Affiliate/CreateAffiliate.jsx
Normal file
@ -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 (
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: "22px" }} className="fw-bold">
|
||||
Add Affiliate
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: "1rem" }}>
|
||||
<h4 className="mb-0"></h4>
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
marginRight: "5px",
|
||||
}}
|
||||
onClick={() => handleSubmit()}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? "Loading" : "Save"}
|
||||
</Button>
|
||||
<Link to="/affiliate/affiliates">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-6 col-md-6 col-sm-12 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="name"
|
||||
value={name}
|
||||
maxLength={25}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
{name ? (
|
||||
<>
|
||||
<small className="charLeft mt-4 fst-italic">
|
||||
{25 - name.length} characters left
|
||||
</small>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}{" "}
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Mobile
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="mobile"
|
||||
value={mobile}
|
||||
onChange={handelNumber}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
className="form-control"
|
||||
id="email"
|
||||
value={email}
|
||||
maxLength="100"
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="categorySelect">Select a Country</label>
|
||||
<select
|
||||
id="country"
|
||||
className="form-control"
|
||||
style={{ width: "100%" }}
|
||||
value={country}
|
||||
onChange={handleCountry}
|
||||
>
|
||||
<option value={"None"}>None</option>
|
||||
{countrieList.map((country) => (
|
||||
<option key={country.isoCode} value={country.name}>
|
||||
{country.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="categorySelect">Select a State</label>
|
||||
<select
|
||||
id="state"
|
||||
className="form-control"
|
||||
style={{ width: "100%" }}
|
||||
value={state}
|
||||
onChange={(e) => setState(e.target.value)}
|
||||
>
|
||||
<option value={""}>None</option>
|
||||
{stateListData?.map((states) => (
|
||||
<option key={states.isoCode}>{states.name}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="categorySelect">Select a City</label>
|
||||
<select
|
||||
id="city"
|
||||
className="form-control"
|
||||
style={{ width: "100%" }}
|
||||
value={city}
|
||||
onChange={(e) => setCity(e.target.value)}
|
||||
>
|
||||
<option value={""}>None</option>
|
||||
{cityListData?.map((city) => (
|
||||
<option value={city.isoCode}>{city.name}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Address
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="address"
|
||||
value={address}
|
||||
maxLength={25}
|
||||
onChange={(e) => setAddress(e.target.value)}
|
||||
/>
|
||||
{name ? (
|
||||
<>
|
||||
<small className="charLeft mt-4 fst-italic">
|
||||
{25 - name.length} characters left
|
||||
</small>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}{" "}
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Pincode
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="pincode"
|
||||
value={pincode}
|
||||
maxLength={25}
|
||||
onChange={(e) => setPincode(e.target.value)}
|
||||
/>
|
||||
{name ? (
|
||||
<>
|
||||
<small className="charLeft mt-4 fst-italic">
|
||||
{25 - name.length} characters left
|
||||
</small>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}{" "}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6 col-md-6 col-sm-12 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3 me-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Name as per Bank records
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="nameasbank"
|
||||
value={nameAsBank}
|
||||
onChange={(e) => setNameAsBank(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3 me-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Account Number
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="accountno"
|
||||
value={accountNo}
|
||||
onChange={(e) => setAccountNo(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3 me-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
IFSC Code
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="ifsc"
|
||||
value={ifsc}
|
||||
onChange={(e) => setIfsc(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3 me-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Bank Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="bankname"
|
||||
value={bankName}
|
||||
onChange={(e) => setBankName(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3 me-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Branch Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="branchname"
|
||||
value={branchName}
|
||||
onChange={(e) => setBranchName(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateAffiliate;
|
355
src/views/Affiliate/CreateCoupon.jsx
Normal file
355
src/views/Affiliate/CreateCoupon.jsx
Normal file
@ -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 (
|
||||
<div className="container">
|
||||
<div
|
||||
className=" page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
flex-direction-row"
|
||||
>
|
||||
<div>
|
||||
<h3>Coupons</h3>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
<div>
|
||||
<Button
|
||||
className="mx-2"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
onClick={handelCreate}
|
||||
>
|
||||
Create
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
onClick={handelBack}
|
||||
variant="contained"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
backgroundColor: "red",
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div
|
||||
style={{
|
||||
padding: "2rem",
|
||||
borderRadius: "0.5rem",
|
||||
backgroundColor: "white",
|
||||
marginBottom: "1rem",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
width: "80%",
|
||||
margin: "auto",
|
||||
}}
|
||||
className="border"
|
||||
>
|
||||
<div style={{ width: "100%" }}>
|
||||
<Box>
|
||||
<Typography className="mb-1">
|
||||
Coupon Code (Must be 8 digit)
|
||||
</Typography>
|
||||
<TextField
|
||||
className="mb-3"
|
||||
required={true}
|
||||
sx={InputSpace}
|
||||
value={coupon}
|
||||
InputProps={{
|
||||
inputProps: {
|
||||
maxLength: 8,
|
||||
minLength: 8,
|
||||
},
|
||||
}}
|
||||
onChange={(e) => {
|
||||
setCoupon(e.target.value);
|
||||
}}
|
||||
error={couponError}
|
||||
style={{ width: "100%" }}
|
||||
/>
|
||||
{couponError ? (
|
||||
<small style={{ color: "red" }}>8 characters required</small>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
|
||||
<Typography className="mb-1">Discount Amount</Typography>
|
||||
<div className="d-flex align-items-center">
|
||||
<div
|
||||
style={{
|
||||
marginRight: "5px",
|
||||
}}
|
||||
className="d-flex justify-content-center"
|
||||
>
|
||||
<span style={{ fontSize: "1.7rem" }}>₹</span>
|
||||
</div>
|
||||
<TextField
|
||||
className="mb-3"
|
||||
required={true}
|
||||
error={discountError}
|
||||
type="number"
|
||||
value={discount}
|
||||
sx={InputSpace}
|
||||
onChange={handelDiscount}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
</div>
|
||||
<Typography className="mb-1">
|
||||
Affiliate Discount Amount
|
||||
</Typography>
|
||||
<div className="d-flex align-items-center">
|
||||
<div
|
||||
style={{
|
||||
marginRight: "5px",
|
||||
}}
|
||||
className="d-flex justify-content-center"
|
||||
>
|
||||
<span style={{ fontSize: "1.7rem" }}>₹</span>
|
||||
</div>
|
||||
<TextField
|
||||
className="mb-3"
|
||||
required={true}
|
||||
error={discountError}
|
||||
type="number"
|
||||
value={affiliateDiscountAmt}
|
||||
sx={InputSpace}
|
||||
onChange={handelAffilateDiscount}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{affiliateDiscountAmtError ? (
|
||||
<small style={{ color: "red" }}>Max Amount Rs.9999</small>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
|
||||
<Typography className="mb-1">Coupon Valid Till: </Typography>
|
||||
<input
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "50px",
|
||||
outline: validError ? "1px solid red" : "",
|
||||
}}
|
||||
className="mb-2"
|
||||
value={valid}
|
||||
sx={InputSpace}
|
||||
onChange={(e) => {
|
||||
setValid(e.target.value);
|
||||
}}
|
||||
type="date"
|
||||
/>
|
||||
{validError ? (
|
||||
<small style={{ color: "red" }}>
|
||||
Validity Date is Required
|
||||
</small>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
<Typography className="mb-1">Select Affiliate</Typography>
|
||||
<select
|
||||
onChange={(e) => {
|
||||
setAffiliate(e.target.value);
|
||||
}}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "50px",
|
||||
outline: validError ? "1px solid red" : "",
|
||||
}}
|
||||
>
|
||||
<option value="">None</option>
|
||||
{apiData?.length > 0 &&
|
||||
apiData.map((data) => {
|
||||
return (
|
||||
<option value={data._id} key={data._id}>
|
||||
{data.name}-{data.mobile}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
{affiliateError ? (
|
||||
<small style={{ color: "red" }}>Affiliation is Required</small>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
<br />
|
||||
</Box>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateCoupon;
|
458
src/views/Affiliate/EditAffiliate.jsx
Normal file
458
src/views/Affiliate/EditAffiliate.jsx
Normal file
@ -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 (
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: "22px" }} className="fw-bold">
|
||||
Edit Affiliate
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: "1rem" }}>
|
||||
<h4 className="mb-0"></h4>
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
marginRight: "5px",
|
||||
}}
|
||||
onClick={() => handleSubmit()}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? "Loading" : "Save"}
|
||||
</Button>
|
||||
<Link to="/affiliate/affiliates">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-6 col-md-6 col-sm-12 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="name"
|
||||
value={name}
|
||||
maxLength={25}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
{name ? (
|
||||
<>
|
||||
<small className="charLeft mt-4 fst-italic">
|
||||
{25 - name.length} characters left
|
||||
</small>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}{" "}
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Mobile
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="mobile"
|
||||
value={mobile}
|
||||
maxLength="100"
|
||||
onChange={handelNumber}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
className="form-control"
|
||||
id="email"
|
||||
value={email}
|
||||
maxLength="100"
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="categorySelect">Select a Country</label>
|
||||
<select
|
||||
id="country"
|
||||
className="form-control"
|
||||
style={{ width: "100%" }}
|
||||
value={country}
|
||||
onChange={handleCountry}
|
||||
>
|
||||
<option value={"None"}>None</option>
|
||||
{countrieList.map((country) => (
|
||||
<option key={country.isoCode} value={country.name}>
|
||||
{country.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="categorySelect">Select a State</label>
|
||||
<select
|
||||
id="state"
|
||||
className="form-control"
|
||||
style={{ width: "100%" }}
|
||||
value={state}
|
||||
onChange={(e) => setState(e.target.value)}
|
||||
>
|
||||
<option value={""}>None</option>
|
||||
{stateListData?.map((states, i) => (
|
||||
<option key={states.isoCode}>{states.name}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="categorySelect">Select a City</label>
|
||||
<select
|
||||
id="city"
|
||||
className="form-control"
|
||||
style={{ width: "100%" }}
|
||||
value={city}
|
||||
onChange={(e) => setCity(e.target.value)}
|
||||
>
|
||||
<option value={""}>None</option>
|
||||
{cityListData?.map((city, i) => (
|
||||
<option key={i} value={city.isoCode}>
|
||||
{city.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Address
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="address"
|
||||
value={address}
|
||||
maxLength={25}
|
||||
onChange={(e) => setAddress(e.target.value)}
|
||||
/>
|
||||
{name ? (
|
||||
<>
|
||||
<small className="charLeft mt-4 fst-italic">
|
||||
{25 - name.length} characters left
|
||||
</small>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}{" "}
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Pincode
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="pincode"
|
||||
value={pincode}
|
||||
maxLength={25}
|
||||
onChange={(e) => setPincode(e.target.value)}
|
||||
/>
|
||||
{name ? (
|
||||
<>
|
||||
<small className="charLeft mt-4 fst-italic">
|
||||
{25 - name.length} characters left
|
||||
</small>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}{" "}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6 col-md-6 col-sm-12 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3 me-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Name as per Bank records
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="nameasbank"
|
||||
value={nameAsBank}
|
||||
onChange={(e) => setNameAsBank(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3 me-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Account Number
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="accountno"
|
||||
value={accountNo}
|
||||
onChange={(e) => setAccountNo(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3 me-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
IFSC Code
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="ifsc"
|
||||
value={ifsc}
|
||||
onChange={(e) => setIfsc(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3 me-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Bank Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="bankname"
|
||||
value={bankName}
|
||||
onChange={(e) => setBankName(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3 me-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Branch Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="branchname"
|
||||
value={branchName}
|
||||
onChange={(e) => setBranchName(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditAffiliate;
|
373
src/views/Affiliate/EditCoupon.jsx
Normal file
373
src/views/Affiliate/EditCoupon.jsx
Normal file
@ -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 (
|
||||
<div className="container">
|
||||
<div
|
||||
className=" page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
flex-direction-row"
|
||||
>
|
||||
<div>
|
||||
<h3>Edit Coupons</h3>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
<div>
|
||||
<Button
|
||||
className="mx-2"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
onClick={handelCreate}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
onClick={handelBack}
|
||||
variant="contained"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
backgroundColor: "red",
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div
|
||||
style={{
|
||||
padding: "2rem",
|
||||
borderRadius: "0.5rem",
|
||||
backgroundColor: "white",
|
||||
marginBottom: "1rem",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
width: "80%",
|
||||
margin: "auto",
|
||||
}}
|
||||
className="border"
|
||||
>
|
||||
<div style={{ width: "100%" }}>
|
||||
<Box>
|
||||
<Typography className="mb-1">Coupon Code</Typography>
|
||||
<TextField
|
||||
className="mb-3"
|
||||
required={true}
|
||||
sx={InputSpace}
|
||||
value={coupon}
|
||||
InputProps={{
|
||||
inputProps: {
|
||||
maxLength: 8,
|
||||
minLength: 8,
|
||||
},
|
||||
}}
|
||||
onChange={(e) => {
|
||||
setCoupon(e.target.value);
|
||||
}}
|
||||
error={couponError}
|
||||
style={{ width: "100%" }}
|
||||
/>
|
||||
{couponError ? (
|
||||
<small style={{ color: "red" }}>8 characters required</small>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
|
||||
<Typography className="mb-1">Discount Amount</Typography>
|
||||
<div className="d-flex align-items-center">
|
||||
<div
|
||||
style={{
|
||||
marginRight: "5px",
|
||||
}}
|
||||
className="d-flex justify-content-center"
|
||||
>
|
||||
<span style={{ fontSize: "1.7rem" }}>₹</span>
|
||||
</div>
|
||||
<TextField
|
||||
className="mb-3"
|
||||
required={true}
|
||||
error={discountError}
|
||||
type="number"
|
||||
value={discount}
|
||||
sx={InputSpace}
|
||||
onChange={handelDiscount}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
</div>
|
||||
<Typography className="mb-1">
|
||||
Affiliate Discount Amount
|
||||
</Typography>
|
||||
<div className="d-flex align-items-center">
|
||||
<div
|
||||
style={{
|
||||
marginRight: "5px",
|
||||
}}
|
||||
className="d-flex justify-content-center"
|
||||
>
|
||||
<span style={{ fontSize: "1.7rem" }}>₹</span>
|
||||
</div>
|
||||
<TextField
|
||||
className="mb-3"
|
||||
required={true}
|
||||
error={discountError}
|
||||
type="number"
|
||||
value={affiliateDiscountAmt}
|
||||
sx={InputSpace}
|
||||
onChange={handelAffilateDiscount}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{affiliateDiscountAmtError ? (
|
||||
<small style={{ color: "red" }}>Max Amount Rs.9999</small>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
|
||||
<Typography className="mb-1">Coupon Valid Till: </Typography>
|
||||
<input
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "50px",
|
||||
outline: validError ? "1px solid red" : "",
|
||||
}}
|
||||
className="mb-2"
|
||||
value={valid}
|
||||
sx={InputSpace}
|
||||
onChange={(e) => {
|
||||
setValid(e.target.value);
|
||||
}}
|
||||
type="date"
|
||||
/>
|
||||
{validError ? (
|
||||
<small style={{ color: "red" }}>
|
||||
Validity Date is Required
|
||||
</small>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
<Typography className="mb-1">Select Affiliate</Typography>
|
||||
<select
|
||||
onChange={(e) => {
|
||||
setAffiliate(e.target.value);
|
||||
}}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "50px",
|
||||
outline: validError ? "1px solid red" : "",
|
||||
}}
|
||||
>
|
||||
<option
|
||||
value={id}
|
||||
>{`${apiData.name} - ${apiData.mobile}`}</option>
|
||||
</select>
|
||||
{affiliateError ? (
|
||||
<small style={{ color: "red" }}>Affiliation is Required</small>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
<br />
|
||||
</Box>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditCoupon;
|
309
src/views/Affiliate/PayAffiliate.jsx
Normal file
309
src/views/Affiliate/PayAffiliate.jsx
Normal file
@ -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 (
|
||||
<>
|
||||
<div className="d-flex justify-content-end">
|
||||
<Link to="/affiliate/affiliates">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
marginBottom: "1rem",
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-6 col-md-6 col-sm-12 my-1">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
className="card"
|
||||
>
|
||||
<div className="card-body p-2">
|
||||
<div
|
||||
style={{
|
||||
padding: "2rem",
|
||||
borderRadius: "0.5rem",
|
||||
backgroundColor: "white",
|
||||
// marginBottom: "1rem",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
className="border"
|
||||
>
|
||||
<div style={{ width: "100%" }}>
|
||||
<Typography className="mb-3">
|
||||
<span style={{ fontWeight: "bold" }}>Affiliate Name: </span>
|
||||
{affiliate}
|
||||
</Typography>
|
||||
<Typography className="mb-3">
|
||||
<span style={{ fontWeight: "bold" }}>Coupon Code: </span>
|
||||
{coupon}
|
||||
</Typography>
|
||||
<Typography className="mb-3">
|
||||
<span style={{ fontWeight: "bold" }}>
|
||||
Per coupon price:{" "}
|
||||
</span>
|
||||
₹{affiliateDiscountAmt}
|
||||
</Typography>
|
||||
<Typography className="mb-3">
|
||||
<span style={{ fontWeight: "bold" }}>
|
||||
No of coupon paying for:{" "}
|
||||
</span>
|
||||
{noOfCoupons} Units
|
||||
</Typography>
|
||||
<Typography className="mb-3">
|
||||
<span style={{ fontWeight: "bold" }}>
|
||||
Amount to be paid:{" "}
|
||||
</span>
|
||||
₹{amountToPay}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6 col-md-6 col-sm-12 my-1">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
className="card"
|
||||
>
|
||||
<div className="card-body p-2">
|
||||
<div
|
||||
style={{
|
||||
padding: "2rem",
|
||||
borderRadius: "0.5rem",
|
||||
backgroundColor: "white",
|
||||
// marginBottom: "1rem",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
className="border"
|
||||
>
|
||||
<div style={{ width: "100%" }}>
|
||||
<Typography className="mb-3">
|
||||
<span style={{ fontWeight: "bold" }}>
|
||||
Name as per Bank records:{" "}
|
||||
</span>
|
||||
{nameAsBank}
|
||||
</Typography>
|
||||
<Typography className="mb-3">
|
||||
<span style={{ fontWeight: "bold" }}>Account Number: </span>
|
||||
{accountNo}
|
||||
</Typography>
|
||||
<Typography className="mb-3">
|
||||
<span style={{ fontWeight: "bold" }}>IFSC Code: </span>
|
||||
{ifsc}
|
||||
</Typography>
|
||||
<Typography className="mb-3">
|
||||
<span style={{ fontWeight: "bold" }}>Bank Name: </span>
|
||||
{bankName}
|
||||
</Typography>
|
||||
<Typography className="mb-3">
|
||||
<span style={{ fontWeight: "bold" }}>Branch Name: </span>
|
||||
{branchName}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12 col-md-12 col-sm-12 my-1">
|
||||
<div className="card">
|
||||
<div className="card-body p-5">
|
||||
<form onSubmit={handlePay}>
|
||||
<div className="d-lg-flex justify-content-center align-items-center">
|
||||
<label htmlFor="title" className="form-label mr-2">
|
||||
Transection ID
|
||||
</label>
|
||||
<input
|
||||
onChange={(e) => 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"
|
||||
/>
|
||||
<label htmlFor="title" className="form-label mr-2">
|
||||
Date
|
||||
</label>
|
||||
<input
|
||||
required="true"
|
||||
type="date"
|
||||
onChange={(e) => setDate(e.target.value)}
|
||||
className="form-control mb-3 col-lg-3 col-md-12 col-sm-12"
|
||||
id="ifsc"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="d-lg-flex align-items-center justify-content-center">
|
||||
<label htmlFor="title" className="form-label mr-2">
|
||||
Time
|
||||
</label>
|
||||
<input
|
||||
required="true"
|
||||
type="time"
|
||||
onChange={(e) => setTime(e.target.value)}
|
||||
className="form-control mb-3 col-lg-3 col-md-12 col-sm-12 mr-5"
|
||||
id="ifsc"
|
||||
/>
|
||||
{/* <label htmlFor="title" className="form-label mr-2">
|
||||
Amount
|
||||
</label> */}
|
||||
<span className="mb-3" style={{ marginRight: "0.5rem" }}>
|
||||
Amount Rs.
|
||||
</span>
|
||||
<input
|
||||
required="true"
|
||||
type="number"
|
||||
className="form-control mb-3 col-lg-3 col-md-12 col-sm-12 mr-4 mb-4"
|
||||
value={amount}
|
||||
onChange={(e) => setAmount(e.target.value)}
|
||||
id="amount"
|
||||
/>
|
||||
|
||||
<Button
|
||||
sx={{ marginTop: "-20px" }}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="success"
|
||||
>
|
||||
Pay
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PayAffiliate;
|
Loading…
Reference in New Issue
Block a user