import React, { useState, useEffect, useContext } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useHistory } from "react-router-dom";
import moment from "moment";
import { notifyError } from "../utils/toast";
import {
Doughnut,
Bar,
} from "react-chartjs-2";
// import Chart from 'chart.js/auto';
import {
Card,
CardBody,
Table,
TableContainer,
TableHeader,
TableBody,
TableRow,
TableCell,
Select,
Button,
} from "@windmill/react-ui";
import { SidebarContext } from "../context/SidebarContext";
import PageTitle from "../components/Typography/PageTitle";
import Loading from "../components/preloader/Loading";
import resetLogo from "../assets/img/reset.png";
import ReportServices from "../services/ReportServices";
import EmployeeServices from "../services/EmployeeServices";
/**
* Returning required redux state data
* @param {Object} state - Redux state
*/
const getReduxData = (state) => {
return {
Loader: state.Loader
};
};
const DashboardReport = () => {
const dispatch = useDispatch();
const navigate = useHistory();
let data = useSelector(getReduxData);
let loading = data?.Loader.loading;
const localData = JSON.parse(localStorage.getItem('adminInfo'));
const [employeeId, setEmployeeId] = useState(localData?.employeeId ? parseInt(localData?.employeeId) : "");
const [latestDesignationSalesPerson, setLatestDesignationSalesPerson] = useState(false);
const [rsm, setRsm] = useState();
const [asm, setAsm] = useState();
const [salesPerson, setSalesPerson] = useState();
const [getEmployeesData, setGetEmployeesData] = useState([]);
const [rsmList, setRsmList] = useState([]);
const [asmList, setAsmList] = useState([]);
const [salesPersonList, setSalesPersonList] = useState([]);
const [mainLoader, setMainLoader] = useState(true);
const {
currentPage,
setCurrentPage,
handleChangePage,
toggleDrawer,
} = useContext(SidebarContext);
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
function returnColorArray(number) {
let colorArray = [];
for (let i = 0; i < number; i++) {
colorArray.push(getRandomColor());
}
return colorArray;
}
const centerTextPlugin = {
id: 'centerText',
beforeDraw(chart) {
const { width, height, ctx } = chart;
const datasets = chart.data.datasets[0];
const total = datasets.data.reduce((sum, value) => sum + value, 0);
ctx.save();
ctx.font = '16px Arial';
ctx.fillStyle = '#000';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Total', width / 2, height / 2.8);
ctx.font = '14px Arial';
ctx.fillText(`${total}`, width / 2, height / 2.4);
ctx.restore();
},
};
// Chart.register(centerTextPlugin);
const chartOptions = {
responsive: true,
plugins: {
legend: {
display: true,
position: "bottom",
onClick: null,
},
},
};
// STATES FOR FETCHING API RESPONSE
const [teamAttendanceReports, setTeamAttendanceReports] = useState();
const [callSummaryReports, setCallSummaryReports] = useState();
const [employeeReports, setEmployeeReports] = useState();
const [catalogReportsForCategory, setCatalogReportsForCategory] = useState();
const [catalogReportsForProduct, setCatalogReportsForProduct] = useState();
// STATES FOR LOADERS
const [teamAttendanceReportsLoader, setTeamAttendanceReportsLoader] = useState(false);
const [callSummaryReportsLoader, setCallSummaryReportsLoader] = useState(false);
const [employeeReportsLoader, setEmployeeReportsLoader] = useState(false);
const [catalogReportsForCategoryLoader, setCatalogReportsForCategoryLoader] = useState(false);
const [catalogReportsForProductLoader, setCatalogReportsForProductLoader] = useState(false);
//DISTRIBUTOR LENGTH
const distributorLimit = 5;
const employeeLimit = 5;
const categoryLimit = 5;
const productLimit = 5;
const characterLength = 12;
const barThickness = 40;
// Ensure colors are generated before JSX
const distributorColors = returnColorArray(distributorLimit);
const employeeColors = returnColorArray(employeeLimit);
const categoryColors = returnColorArray(categoryLimit);
const productColors = returnColorArray(productLimit);
const getEmployees = async (design_id) => {
if (localData?.employeeId) {
await getTeamById(localData?.employeeId, "rsm");
}
else {
await EmployeeServices.getEmployees({
design_id: design_id,
})
.then((res) => {
setGetEmployeesData(res?.data);
setEmployeeId(res?.data[0]?.employeeId);
setRsm(res?.data[0]?.employeeId);
getTeamById(res?.data[0]?.employeeId, "asm");
})
.catch((err) => console.log("ERROR in /getEmployees", err));
}
}
useEffect(async () => {
await getEmployees(3);
}, []);
const getTeamById = async (id, designation) => {
await ReportServices.getTeamById({
employeeId: parseInt(id),
store_id: localData?.store_id ? parseInt(localData?.store_id) : "",
})
.then(res => {
if (designation == "rsm") {
setRsmList(res?.data);
}
else if (designation == "asm") {
setAsmList(res?.data);
}
else if (designation == "salesperson") {
setSalesPersonList(res?.data);
}
else {
alert(`Only have ASM and Sales Person getTeamById query!`);
}
})
.catch(err => console.log("Error in /getTeamById", err));
}
const getTeamAttendanceReports = async () => {
setTeamAttendanceReportsLoader(true);
await ReportServices.getTeamAttendanceReports({
employeeId,
date: new Date().toISOString().split("T")[0],
})
.then(res => setTeamAttendanceReports(res))
.catch(err => console.log("Error in /getTeamAttendanceReports", err));
setTeamAttendanceReportsLoader(false);
};
const getCallSummaryReports = async () => {
setCallSummaryReportsLoader(true);
await ReportServices.getRetailerReports({
customerId: [],
customerType: "None",
employeeId: [
employeeId
],
// startDate: moment().startOf('month').format("YYYY-MM-DD"),
// endDate: moment().endOf('month').format("YYYY-MM-DD"),
startDate: new Date().toISOString().split("T")[0],
endDate: new Date().toISOString().split("T")[0],
frequency: "cumulative",
visitType: "callSummary"
})
.then(res => setCallSummaryReports(res))
.catch(err => console.log("Error in /getCallSummaryReports", err));
setCallSummaryReportsLoader(false);
};
const getEmployeeReports = async () => {
setEmployeeReportsLoader(true);
await ReportServices.getEmployeeReports({
employeeId,
type: "month",
})
.then(res => setEmployeeReports(res))
.catch(err => console.log("Error in /getEmployeeReports", err));
setEmployeeReportsLoader(false);
};
const getCatalogReportsForCategory = async () => {
setCatalogReportsForCategoryLoader(true);
await ReportServices.getCatalogReports({
employeeId,
type: "month",
catalog_type: "category",
})
.then(res => setCatalogReportsForCategory(res))
.catch(err => console.log("Error in /getCatalogReportsForCategory", err));
setCatalogReportsForCategoryLoader(false);
};
const getCatalogReportsForProduct = async () => {
setCatalogReportsForProductLoader(true);
await ReportServices.getCatalogReports({
employeeId,
type: "month",
catalog_type: "product",
})
.then(res => setCatalogReportsForProduct(res))
.catch(err => console.log("Error in /getCatalogReportsForProduct", err));
setCatalogReportsForProductLoader(false);
};
const runAllReportAPIs = () => {
getTeamAttendanceReports();
getCallSummaryReports();
getEmployeeReports();
getCatalogReportsForCategory();
getCatalogReportsForProduct();
}
const reset = () => {
window.location.reload();
}
useEffect(() => {
if (!employeeId) {
// notifyError(`Employee ID is not available!`);
}
runAllReportAPIs();
}, [employeeId]);
const chartDataForTeamAttendanceReports = {
datasets: [
{
data: [
teamAttendanceReports?.present?.count || 0,
teamAttendanceReports?.leaves?.count || 0,
teamAttendanceReports?.defaulters?.count || 0,
],
backgroundColor: ["#00a100", "#8bdce4", "#ff0000"],
label: "Attendance Summary",
total: teamAttendanceReports?.total
},
],
labels: [
`Present (${teamAttendanceReports?.present?.percentage || 0}%)`,
`Leaves (${teamAttendanceReports?.leaves?.percentage || 0}%)`,
`Defaulters (${teamAttendanceReports?.defaulters?.percentage || 0}%)`,
],
};
const chartDataForCovergeCallSummaryReports = {
datasets: [
{
data: [
(callSummaryReports?.data[0]?.coverage_calls && callSummaryReports?.data[0]?.total_customers
? (callSummaryReports?.data[0]?.coverage_calls / callSummaryReports?.data[0]?.total_customers) * 100
: 0) || 0,
(callSummaryReports?.data[0]?.coverage_calls && callSummaryReports?.data[0]?.total_customers
? 100 - (callSummaryReports?.data[0]?.coverage_calls / callSummaryReports?.data[0]?.total_customers) * 100
: 100) || 100,
// 44 || 0,
// 56 || 0,
],
backgroundColor: ["#00a100", "#d5d6d7"],
label: "Call Summary - Visited Calls",
},
],
labels: [
`Visited Calls`,
`Remaining`,
],
};
const chartDataForProductiveCallSummaryReports = {
datasets: [
{
data: [
(callSummaryReports?.data[0]?.productive_customers && callSummaryReports?.data[0]?.total_customers
? (callSummaryReports?.data[0]?.productive_customers / callSummaryReports?.data[0]?.total_customers) * 100
: 0) || 0,
(callSummaryReports?.data[0]?.productive_customers && callSummaryReports?.data[0]?.total_customers
? 100 - (callSummaryReports?.data[0]?.productive_customers / callSummaryReports?.data[0]?.total_customers) * 100
: 100) || 100,
// 8 || 0,
// 92 || 0,
],
backgroundColor: ["#3498db", "#d5d6d7"],
label: "Call Summary - Productive Calls",
},
],
labels: [
`Productive Calls`,
`Remaining`,
],
};
const handleSubmit = () => {
let latestEmployeeId;
setLatestDesignationSalesPerson(false);
// Check which variable exists in the preferred order of precedence (Sales Person > ASM > RSM)
if (salesPerson) {
latestEmployeeId = parseInt(salesPerson);
setLatestDesignationSalesPerson(true);
} else if (asm) {
latestEmployeeId = parseInt(asm);
} else if (rsm) {
latestEmployeeId = parseInt(rsm);
}
if (latestEmployeeId) {
setEmployeeId(latestEmployeeId);
runAllReportAPIs();
}
else {
setEmployeeId(localData?.employeeId ? parseInt(localData?.employeeId) : "");
alert(`Please select an employee from the rsm dropdown first!`);
}
};
return (
<>
Loading Summary Charts...
:
Loading Attendance Summary Chart...
Attendance Summary - Today
Loading Call Summary Chart...
Call Summary - Today
Metric
Value
Total Calls
{/* {callSummaryReports?.data[0]?.total_customers || 0} */}
{(parseFloat(callSummaryReports?.data[0]?.total_customers || 0))?.toLocaleString('en-IN', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}
Visited Calls
{/* {callSummaryReports?.data[0]?.coverage_calls || 0} */}
{(parseFloat(callSummaryReports?.data[0]?.coverage_calls || 0))?.toLocaleString('en-IN', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}
Productive Calls
{/* {callSummaryReports?.data[0]?.productive_customers || 0} */}
{(parseFloat(callSummaryReports?.data[0]?.productive_customers || 0))?.toLocaleString('en-IN', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}
Line Items
{/* {callSummaryReports?.data[0]?.total_items || 0} */}
{(parseFloat(callSummaryReports?.data[0]?.total_items || 0))?.toLocaleString('en-IN', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}
LPC
{callSummaryReports?.data[0]?.avg_items_per_order || "0.00"}
Revenue
{(parseFloat(callSummaryReports?.data[0]?.revenue || 0))?.toLocaleString('en-IN', { style: 'currency', currency: 'INR', minimumFractionDigits: 0, maximumFractionDigits: 0 })}