| Server IP : 13.235.167.51 / Your IP : 216.73.217.116 Web Server : Apache System : Linux machinox-server 6.17.0-1013-aws #13~24.04.1-Ubuntu SMP Fri Apr 24 21:36:58 UTC 2026 aarch64 User : root ( 0) PHP Version : 8.2.29 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/control.machinox.in/src/components/ManageDashboard/ |
Upload File : |
'use client';
import { Col, Row } from "react-bootstrap";
import { useCallback, useEffect, useState } from "react";
import { toast } from "react-toastify";
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
PointElement as Point,
Title,
LineElement,
Legend,
} from "chart.js";
import { Line } from "react-chartjs-2";
import moment from "moment";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import { useDispatch, useSelector } from "react-redux";
import { Logo, profileImages } from "../redux/action";
import "react-datepicker/dist/react-datepicker.css";
import HelperService from "@/Services/HelperService";
import WebService from "@/Services/WebService";
import CompoLoader from "@/Common/ComponentLoader/CompoLoader";
import PageTitle from "@/Common/PageTitle";
import { AiOutlineCustomerService } from "react-icons/ai";
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Legend, Point, LineElement);
const Dashboard: React.FC = (props: any) => {
const EndDate = new Date();
let StartDate = new Date();
StartDate.setMonth(StartDate.getMonth() - 1);
let maxRevenue: any = "";
let suggestedMax: any = "";
const debounce = require("lodash.debounce");
const TimePeriodOptions = [
{ value: 1, label: `${('monthly')}`, type: "MONTHLY" },
{ value: 2, label: `${('daily')}`, type: "DAILY" },
{ value: 3, label: `${('yearly')}`, type: "YEARLY" },
// { value: 4, label: `${('custom')}`, type: "CUSTOM" },
];
const [loader, setLoader] = useState(false);
const [getCustomerLoader, setCustomerLoader] = useState<boolean>(false);
const [getVendorLoader, setVendorLoader] = useState<boolean>(false);
const [getDate, setDates] = useState<any>({
from_date: moment(StartDate).format("YYYY-MM-DD"),
to_date: moment(EndDate).format("YYYY-MM-DD"),
graph_mode: "MONTHLY",
type: "USER"
});
const [getVendorDate, setVendorDates] = useState<any>({
from_date: moment(StartDate).format("YYYY-MM-DD"),
to_date: moment(EndDate).format("YYYY-MM-DD"),
graph_mode: "MONTHLY",
type: "REVENUE"
});
const [totalUser, setTotalUser] = useState(0);
const [totalRevenue, setTotalRevenue] = useState(0);
let dispatch = useDispatch();
useEffect(() => {
getDashboard();
meCallAfterChange();
}, []);
useEffect(() => {
getCustomerGraphInfo();
}, [getDate])
useEffect(() => {
getRevenueGraphInfo();
}, [getVendorDate])
const meCallAfterChange = async () => {
return WebService.getAPI({
action: `admin/Me`,
body: null,
isShowError: true,
}).then((res: any) => {
if (res?.info?.profile_image !== null) {
dispatch(profileImages(res?.info?.profile_image));
}
}).catch((error: any) => {
return error;
});
};
const getDashboard = () => {
setLoader(true)
return WebService.getAPI({
action: `admin/dashboard`,
body: null,
isShowError: false,
})
.then((res: any) => {
setLoader(false);
setTotalRevenue(res.total_revenue);
setTotalUser(res.total_user);
})
.catch((error: any) => {
setLoader(false);
return error;
});
};
const handleCustomerGraphModeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const selectedMode = e.target.value;
setDates((prevState: any) => ({
...prevState,
graph_mode: selectedMode
}));
updateDates(selectedMode, getDate.type);
};
const handleVendorGraphModeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const selectedMode = e.target.value;
setVendorDates((prevState: any) => ({
...prevState,
graph_mode: selectedMode
}));
updateDates(selectedMode, getVendorDate.type);
};
const updateDates = (mode: string, type: string) => {
const today = new Date();
let newStartDate = new Date();
let newEndDate = new Date();
switch (mode) {
case 'DAILY':
newStartDate = new Date();
newEndDate = new Date();
break;
case 'WEEKLY':
newStartDate = new Date(today.setDate(today.getDate() - 7));
newEndDate = new Date();
break;
case 'MONTHLY':
newStartDate = new Date(today.setMonth(today.getMonth() - 1));
newEndDate = new Date();
break;
case 'YEARLY':
newStartDate = new Date(today.setFullYear(today.getFullYear() - 1));
newEndDate = new Date();
break;
default:
newStartDate = getDate.from_date ? new Date(getDate.from_date) : new Date();
newEndDate = getDate.to_date ? new Date(getDate.to_date) : new Date();
break;
}
if (type === "USER") {
setDates((prevState: any) => ({
...prevState,
from_date: moment(newStartDate).format("YYYY-MM-DD"),
to_date: moment(newEndDate).format("YYYY-MM-DD"),
}))
}
if (type === "REVENUE") {
setVendorDates((prevState: any) => ({
...prevState,
from_date: moment(newStartDate).format("YYYY-MM-DD"),
to_date: moment(newEndDate).format("YYYY-MM-DD"),
}));
}
};
const userOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: "top" as const,
labels: {
color: "rgb(255, 99, 132)",
},
},
},
scales: {
y: {
beginAtZero: true,
// suggestedMax: 10,
ticks: {
stepSize: 5,
precision: 0,
callback: (value: number | string) => {
const num = typeof value === "string" ? parseFloat(value) : value;
return Number.isInteger(num) ? num : null;
},
},
},
},
};
const revenueOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: "top" as const,
},
tooltip: {
callbacks: {
label: function (context: any) {
const value = context.raw;
return `Revenue: ${value.toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}`;
},
},
},
},
scales: {
y: {
beginAtZero: true,
suggestedMax: suggestedMax,
ticks: {
stepSize: 10000,
callback: (value: number | string) => {
const num = typeof value === "string" ? parseFloat(value) : value;
return `${num.toLocaleString()}`;
},
},
},
},
};
const [getCustomerChartData, setCustomerChartData] = useState<any>({
labels: [],
datasets: [
{
label: "Total User",
data: [],
backgroundColor: ["#3579F6"],
borderColor: "white",
borderWidth: 5,
barPercentage: 0.5,
borderRadius: 10,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
options: {
responsive: true,
plugins: {
legend: {
position: "top",
display: true,
labels: {
color: "rgb(255, 99, 132)",
},
},
},
scales: {
x: {
stacked: true,
},
y: {
stacked: true,
beginAtZero: true,
ticks: {
stepSize: 1, // show 1,2,3,...
precision: 0, // optional, removes decimal places
callback: (value: number | string) => {
// Chart.js uses string for some values
const num = typeof value === "string" ? parseFloat(value) : value;
return Number.isInteger(num) ? num : null;
},
},
},
},
},
},
],
});
const [getRevenueChartData, setRevenueChartData] = useState<any>({
labels: [],
datasets: [
{
label: "Total Revenue",
data: [],
backgroundColor: ["#3579F6"],
borderColor: "white",
borderWidth: 5,
barPercentage: 0.5,
borderRadius: 10,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
options: {
responsive: true,
plugins: {
legend: {
position: "top",
display: true,
labels: {
color: "rgb(255, 99, 132)",
},
},
},
scales: {
x: {
stacked: true,
},
y: {
stacked: true,
beginAtZero: true,
ticks: {
stepSize: 1, // show 1,2,3,...
precision: 0, // optional, removes decimal places
callback: (value: number | string) => {
// Chart.js uses string for some values
const num = typeof value === "string" ? parseFloat(value) : value;
return Number.isInteger(num) ? num : null;
},
},
},
},
},
},
],
});
const getCustomerGraphInfo = useCallback(
debounce((dates: any) => {
setCustomerLoader(true);
WebService.CommonApi({
method: "GET",
action: `admin/dashboard-stat/user?start_date=${getDate.from_date}&end_date=${getDate.to_date}&graph_mode=${getDate.graph_mode}`,
body: null,
isShowError: true,
})
.then((res: any) => {
setCustomerLoader(false);
if (res !== null) {
const graphData = res?.graph_data || [];
const maxValue = Math.max(...graphData.map((data: any) => data.count));
const suggestedMax = Math.ceil((maxValue + 1) / 5) * 5;
setCustomerChartData({
labels: graphData.map((data: any) => HelperService.toProperCase(data?.date)),
datasets: [
{
label: "Total User",
data: graphData.map((data: any) => data?.count),
backgroundColor: ["#3579F6"],
borderColor: "#3579F6",
borderWidth: 0.5,
barPercentage: 0.5,
barThickness: 20,
maxBarThickness: 8,
borderRadius: 10,
minBarLength: 2,
options: {
responsive: true,
plugins: {
legend: {
position: "top",
display: true,
labels: {
color: "rgb(255, 99, 132)",
},
},
},
scales: {
x: {
stacked: true,
},
y: {
stacked: true,
suggestedMax: suggestedMax,
beginAtZero: true,
ticks: {
stepSize: 1,
precision: 0,
callback: (value: number | string) => {
const num = typeof value === "string" ? parseFloat(value) : value;
return Number.isInteger(num) ? num : null;
},
},
},
},
},
},
],
});
}
})
.catch((error) => {
setCustomerLoader(false);
toast.error(error?.response?.data?.message);
});
}, 300),
[getDate]
);
const getRevenueGraphInfo = useCallback(
debounce((dates: any) => {
setVendorLoader(true);
WebService.CommonApi({
method: "GET",
action: `admin/dashboard-stat/revenue?start_date=${getVendorDate.from_date}&end_date=${getVendorDate.to_date}&graph_mode=${getVendorDate.graph_mode}`,
body: null,
isShowError: true,
})
.then((res: any) => {
setVendorLoader(false);
if (res !== null) {
const graphData = res.graph_data.map((item: any) => ({
...item,
revenue: parseFloat(item.revenue),
}));
const maxRevenue = Math.max(...graphData.map((data: any) => data.revenue));
const suggestedMax = Math.ceil(maxRevenue / 5000) * 5000;
setRevenueChartData({
labels: graphData.map((data: any) => data.date),
datasets: [
{
label: "Total Revenue",
data: graphData.map((data: any) => data.revenue),
backgroundColor: "#3579F6",
borderRadius: 10,
barThickness: 20,
},
],
});
// setRevenueChartData({
// labels: graphData.map((data: any) =>
// HelperService.toProperCase(data?.date)
// ),
// datasets: [
// {
// label: "Total Revenue",
// data: graphData.map((data: any) => data.revenue),
// backgroundColor: ["#3579F6"],
// borderColor: "#3579F6",
// borderWidth: 0.5,
// barPercentage: 0.5,
// barThickness: 20,
// maxBarThickness: 8,
// borderRadius: 10,
// minBarLength: 2,
// options: {
// responsive: true,
// plugins: {
// legend: {
// position: "top",
// display: true,
// labels: {
// color: "rgb(255, 99, 132)",
// },
// },
// },
// scales: {
// x: {
// stacked: true,
// },
// y: {
// stacked: true,
// suggestedMax: suggestedMax,
// beginAtZero: true,
// ticks: {
// stepSize: 1,
// precision: 0,
// callback: (value: number | string) => {
// // Chart.js uses string for some values
// const num = typeof value === "string" ? parseFloat(value) : value;
// return Number.isInteger(num) ? num : null;
// },
// },
// },
// },
// },
// },
// ],
// });
}
})
.catch((error) => {
setVendorLoader(false);
toast.error(error?.response?.data?.message);
});
}, 300),
[getVendorDate]
);
return (
<>
{loader && <CompoLoader />}
<div className="page-vendors pb-5">
<Row className="align-items-center mb-3">
<Col lg={9} xs={12}>
<div className="d-flex gap-3 justify-content-start align-items-center">
<PageTitle title={"Dashboard"} backArrow={false} />
</div>
</Col>
</Row>
<Row>
<Col lg={6} xs={12} sm={4} className="mb-3">
<div className="card" style={{ background: '#fafafa', borderRadius: '5px' }}>
<div className="card-body">
<div className="card-title text-center text-secondary mb-0" >
{/* <div><AiOutlineCustomerService size={50} color="#006FFD" /></div> */}
<h6 className="mb-0 font-bold text-black">{"Total Number of Customers"}</h6>
</div>
<h5 className="card-text text-center">{totalUser}</h5>
</div>
</div>
</Col>
<Col lg={6} xs={12} sm={4} className="mb-3">
<div className="card" style={{ background: '#fafafa', borderRadius: '5px' }}>
<div className="card-body">
<div className="card-title text-center text-secondary mb-0">
{/* <div><IoCarOutline size={50} color="#006FFD" /></div> */}
<h6 className="mb-0 font-bold text-black">{"Total Revenue"} </h6>
</div>
<h5 className="card-text text-center">{totalRevenue}</h5>
</div>
</div>
</Col>
</Row>
{/* user graph */}
<Row className="pt-0">
<Col lg={6} xs={6} md={6} sm={6} className="mb-3">
<div className="card">
<div className="card-header" style={{ backgroundColor: "#FFFFFF" }}>
<div className="row">
<div className="col-12">
<h6 className="card-title font-bold py-2">{"Active User Statistics"}</h6>
</div>
</div>
<div className="row">
<div className="col-4">
<select
className="form-control"
value={getDate?.graph_mode}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => handleCustomerGraphModeChange(e)}
name="graph_mode"
id="graph_mode"
>
{TimePeriodOptions.map((item: any) => (
<option key={item.type} value={item.type}>
{item.label}
</option>
))}
</select>
</div>
{/* <div className="col-4">
<DatePicker
selected={getDate?.from_date}
onChange={(date: any) => {
setDates({
...getDate,
from_date: moment(date).format("YYYY-MM-DD")
});
}}
selectsStart
startDate={getDate?.from_date}
endDate={getDate?.to_date}
/>
</div>
<div className="col-4">
<DatePicker
selected={getDate?.to_date}
onChange={(date: any) => {
setDates({
...getDate,
to_date: moment(date).format("YYYY-MM-DD")
});
}}
selectsEnd
startDate={getDate?.from_date}
endDate={getDate?.to_date}
minDate={getDate?.from_date}
/>
</div> */}
{/* <div className="col-3">
{getDate?.graph_mode === "CUSTOM" && (
<button className="btn btn-primary mx-1" onClick={() => getCustomerGraphInfo(getDate)}>
Apply
</button>
)}
{getDate?.graph_mode !== "MONTHLY" && (
<button className="btn btn-danger" onClick={() => {
setDates({
...getDate,
from_date: new Date(),
to_date: new Date(),
graph_mode: 'MONTHLY',
});
getCustomerGraphInfo(getDate);
}}>
Clear
</button>
)}
</div> */}
</div>
</div>
<div className="card-body" style={{ height: "500px" }}>
{getCustomerLoader ? <CompoLoader /> : <Line options={userOptions} data={getCustomerChartData} />}
</div>
</div>
</Col>
<Col lg={6} xs={6} md={6} sm={6} className="mb-3">
<div className="card">
<div className="card-header" style={{ backgroundColor: "#FFFFFF" }}>
<div className="row">
<div className="col-12">
<h6 className="card-title font-bold py-2">{"Active Revenue Statistics"}</h6>
</div>
</div>
<div className="row">
<div className="col-4">
<select
className="form-control"
value={getVendorDate?.graph_mode}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => handleVendorGraphModeChange(e)}
name="graph_mode"
id="graph_mode"
>
{TimePeriodOptions.map((item: any) => (
<option key={item.type} value={item.type}>
{item.label}
</option>
))}
</select>
</div>
</div>
</div>
<div className="card-body" style={{ height: "500px" }}>
{getVendorLoader ? <CompoLoader /> : <Line options={revenueOptions} data={getRevenueChartData} />}
</div>
</div>
</Col>
</Row>
</div >
</>
);
}
export default Dashboard;