Android_Retail/src/Pages/DashBoard/RetailDashboard.jsx

2557 lines
90 KiB
JavaScript

import React, { useCallback, useEffect, useRef, useState } from 'react';
import '../../Styles/DashBoard/RetailDashBoard.scss';
import GraphChart from './Chart/GraphChart';
import { DatePicker, Space, Tooltip } from 'antd';
import dayjs from 'dayjs';
import { IoMdRefresh } from 'react-icons/io';
import { CiShop } from 'react-icons/ci';
import { FiMenu } from 'react-icons/fi';
import PozoMind from '../../Images/pozologowhite.svg';
import { useNavigate, useOutletContext } from 'react-router-dom';
import CalendarDropdown from '../../Components/CalendarDropdown';
import { MdKeyboardArrowDown } from 'react-icons/md';
import { IoMdNotificationsOutline } from 'react-icons/io';
import {
getdashboard,
getdashboarddate,
getpreOrderDashBoard,
getSalesHdr,
getTopSellingCustomers,
} from '../../Features/RetailDashboard/Dashboard.js';
import { FaTimesCircle } from 'react-icons/fa';
import sandClock from '../../Images/sandClock.png';
import {
FeatureAddon,
getTemplate,
GlobalPricingAppPricingName,
StoredSessionData,
} from '../../Features/ThemeChange/ThemeChange.js';
import {
getAllCustomerPendingBalance,
getAppSubscriptionDate,
getPreferenceData,
} from '../../Features/BookingScreen/BookingData/BookingData.js';
import {
clearSession,
dateFormatChange,
encryptedValuesUrlFun,
ExtractDateFormate,
getSession,
} from '../../Services/Others';
import { shallowEqual, useDispatch } from 'react-redux';
import { useSelector } from 'react-redux';
import {
getAllprodIds,
getExpireProductsList,
getLowStockAlertProductsList,
getTopSellingProduct,
} from '../../Features/ProductPage/ProductPage.js';
import {
ApplicationPreferences,
checkSession,
GenerateLogout,
getCompBranchData,
getEmpAccesData,
GLobalSadminUserData,
GlobalSelectedBranchId,
PostLoginSuser,
PUTLoginuser,
} from '../../Features/BrachLogin/BranchLogin.js';
import { getPurchasedAppDetails } from '../../Features/BookingScreen/Pricing/Pricing.js';
import Add from '../../Images/dashboard/Add.png';
import AddPurchase from '../../Images/dashboard/AddPurchase.png';
import invoice from '../../Images/dashboard/invoice.png';
import user from '../../Images/dashboard/user.jpg';
import report from '../../Images/dashboard/report.png';
import Calendar from '../../Components/Calendar/Calendar';
import { PiSignOut } from 'react-icons/pi';
import BSNavBarUserInfo from '../BookingScreen/Components/BSNavbar/BSNavBarUserInfo';
import { DefaultModal } from '../../Components/Modal/DefaultModal';
import { RadioGrpButton } from '../../Components/Forms/RadioGroup.jsx';
import { DropDowns } from '../../Components/Forms/DropDown.jsx';
import {
ChangeRedirectStatus,
getEmpAccess,
GlobalRedirectStatus,
} from '../../Features/AppPage/CenterPage.js';
import { UserDataBasedOnBranchId } from '../../Features/Reports/Reports.js';
import { gettableData } from '../../Features/PreferenceMaster/PreferenceMaster.js';
import Loader from '../../Components/Loader/Loader.jsx';
import { getUserProfile } from '../../Features/UserAccount/userData.js';
import TopSellingProductsChart from './TopSellingProductsChart.jsx';
import { Messages } from '../../Components/Notifications/Messages.jsx';
const commonUrl = import.meta.env.ENV_COMMON_BASE_URL;
const subDirectory = import.meta.env.ENV_BASE_URL;
const RetailDashboard = () => {
const today = new Date();
const year = today.getFullYear();
const month = today.getMonth();
const formatDate = (date) =>
`${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
const intialFromDate = `${year}-${String(month + 1).padStart(2, '0')}-01`;
const intialToDate = formatDate(today);
const navigate = useNavigate();
const dispatch = useDispatch();
const { RangePicker } = DatePicker;
const [selectedTab, setSelectedTab] = useState('dashboard');
const tabs = [
{ value: 'dashboard', label: 'Dashboard' },
{ value: 'top-selling-products', label: 'Top Selling Products' },
];
const { setCollapse } = useOutletContext();
const SessionData = useSelector(StoredSessionData, shallowEqual);
const PricingAppPricingName = useSelector(
GlobalPricingAppPricingName,
shallowEqual
);
const [topSellingProducts, setTopSellingProducts] = useState([]);
const [initialDate, setInitialDate] = useState(true);
const [dates, setDates] = useState([
dayjs(intialFromDate),
dayjs(intialToDate),
]);
const [ismounted, setIsmounted] = useState(true);
const [customerPendingBalance, setcustomerPendingBalance] = useState([]);
console.log(PricingAppPricingName, 'PricingAppPricingName');
// const {
// AppId: appId,
// CompId: compId,
// BranchId: branchId,
// } = SessionData || {};
// console.log(appId, compId, branchId, 'SessionData');
const [range1, setRange1] = useState('today');
const [range2, setRange2] = useState('today');
const [range3, setRange3] = useState('today');
const [userprofile, setUserprofile] = useState(false);
const userProfileRef = useRef(null);
const CompId = getSession('CompId');
const BranchId = getSession('BranchId');
const AppId = getSession('AppId');
const UserId = getSession('UserId');
const UserType = getSession('UserType');
const sessionId = getSession('SessionId');
const BrLength = getSession('BranchLength');
const [selection, setSelection] = useState('dashboard');
const [page, setPage] = useState(1);
const [totalPages, setTotalPages] = useState(0);
const [loading, setLoading] = useState(false);
const [products, setProducts] = useState([]);
console.log(selection, 'selection');
const [CompBranchData, setCompBranchData] = useState();
const [EmpAcces, setEmpAccess] = useState();
const [seletedBranchData, setseletedBranchData] = useState(BranchId);
const [branchName, setBranchName] = useState('Guest');
const [selectedBranchForFilter, setSelectedBranchForFilter] = useState(
BrLength == 1 ? null : 'all'
);
const [ApiData, setApiData] = useState([]);
console.log(CompBranchData, 'CompBranchData');
const [Zero, SetZero] = useState(false);
const [ResponseData, setResponseData] = useState();
const [DateApiData, setDateApiData] = useState([]);
const [piedat, setPiedat] = useState([]);
const inputRefs = useRef([]);
const [pin, setPin] = useState(['', '', '', '']);
const [expiredList, setExpiredList] = useState([]);
const [lowStockList, setLowStock] = useState([]);
const [AllProdIds, setAllProdIds] = useState([]);
const [AppDetails, setAppDetails] = useState([]);
const [preorderData, setpreorderData] = useState([]);
const [TopSellingCus, setTopsellingCus] = useState([]);
const [SalesHdr, setSalesHdr] = useState([]);
const [modal, setModal] = useState(false);
const [SelectType, setSelectType] = useState('O');
const [SelectTypeName, setSelectTypeName] = useState('OTP');
const [pinInput, setpinInput] = useState(false);
const [otp, setOtp] = useState();
const [FirstTimeOtp, setFirstTimeOtp] = useState(false);
const [FirstTimePin, setFirstTimePin] = useState(false);
const [seconds, setSeconds] = useState(0);
const [disabled, setDisabled] = useState(false);
const clicked = useRef(false);
const [selectedUserData, setSelectedUserData] = useState(null);
const [userDropDown, setuserDropDown] = useState([]);
const [ExpiryDate, setExpiryDate] = useState();
const [EmpData, setEmpData] = useState();
const [messageType, setMessageType] = useState(null);
const [messageData, setMessageData] = useState(null);
console.log(EmpData, 'EmpDataEmpData');
// Loading states to prevent duplicate API calls
const [isLoadingBranchData, setIsLoadingBranchData] = useState(false);
const [isLoadingDashboard, setIsLoadingDashboard] = useState(false);
const [isLoadingBranchFilter, setIsLoadingBranchFilter] = useState(false);
const [isInitialLoad, setIsInitialLoad] = useState(true);
const [initialFetchCompleted, setInitialFetchCompleted] = useState(false);
// Ref to track if component is mounted
const isMountedRef = useRef(true);
const RedirectStatus = useSelector(GlobalRedirectStatus);
const globalbranchid = useSelector(GlobalSelectedBranchId);
const SAdminUserData = useSelector(GLobalSadminUserData);
const appPreferences = useSelector(ApplicationPreferences);
const isCheckSportsApp = appPreferences
?.find((preference) => preference?.PreferredCatName === 'Common Module')
?.PreferenceCatDetails?.some(
(e) =>
e?.PreferredSubCatName === 'SportsApp' && e?.PreferredStatus === 'Y'
);
const bookingTypePreference = appPreferences?.find(
(preference) => preference?.PreferredCatName === 'Booking Type'
)?.PreferenceCatDetails;
const dinePreference = bookingTypePreference?.find(
(type) =>
type?.PreferredSubCatName?.toLowerCase() === 'dine in' &&
type?.PreferredStatus === 'Y'
);
const takeAwayPreference = bookingTypePreference?.find(
(type) =>
type?.PreferredSubCatName?.toLowerCase() === 'take away' &&
type?.PreferredStatus === 'Y'
);
const timerDuration = 30;
let EndDate = AppDetails?.[0]?.ValidityEnd;
const isoDate = EndDate; // <-- July 24
const date = new Date(isoDate);
const options = { year: 'numeric', month: 'long', day: 'numeric' };
const formatted = date.toLocaleDateString('en-US', options);
// "July 24, 2025"
console.log(expiredList, lowStockList, 'lowStockList');
console.log(TopSellingCus, preorderData, 'preorderData');
let DineInData =
ApiData?.[0]?.ChartDtl?.map((item) => {
return {
label: '',
value:
item?.OverAllDineInAmount || 0 - item?.OverAllDineInOfferAmount || 0,
date: item?.SalesDate,
};
}) || [];
let TakeAway =
ApiData?.[0]?.ChartDtl?.map((item) => {
return {
label: '',
value:
item?.OverAllTakeAwayAmount ||
0 - item?.OverAllTakeAwayOfferAmount ||
0,
date: item?.SalesDate,
};
}) || [];
let selfbooking =
ApiData?.[0]?.ChartDtl?.map((item) => {
return {
label: '',
value: 0,
date: item?.SalesDate,
};
}) || [];
console.log(DineInData, 'DineInData');
useEffect(() => {
dispatch(getUserProfile({ UserId: UserId, ActiveStatus: 'A' })).unwrap();
}, [UserId]);
useEffect(() => {
if (isInitialLoad && CompId && AppId && selection === 'dashboard') {
// debugger
if (dates && dates?.[0] && dates?.[1] && !initialDate) {
onRangeChange(dates, [
dates?.[0]?.format('DD-MM-YYYY'),
dates?.[1]?.format('DD-MM-YYYY'),
]);
} else {
setIsInitialLoad(false);
initializeData();
getInitialdataForPendingBills();
}
}
}, [CompId, AppId, isInitialLoad, selection, BranchId]);
const getInitialdataForPendingBills = async () => {
let data = {
CompId: CompId,
...(!selectedBranchForFilter ? { BranchId: BranchId } : {}),
AppId: AppId,
};
console.log(data, 'getSalesHdrFn');
dispatch(getSalesHdr(data))
.unwrap()
.then((response) => {
if (response?.data?.statusCode === 1) {
setSalesHdr(response?.data?.data);
} else {
setSalesHdr([]);
console.error('Failed to fetch pre-order dashboard data');
}
})
.catch((error) => {
console.error('Error fetching pre-order dashboard:', error);
});
};
// Initialize all data in proper sequence
const initializeData = async () => {
try {
// First fetch branch data as other calls depend on it
await fetchBranchData();
// Then fetch other data that doesn't depend on branch selection
await Promise.all([
fetchData(),
getAllProdId(),
topSellingProductsFn(),
CustPendingBalance(),
getExpdate(),
fetchApi(),
]);
setInitialFetchCompleted(true);
// Dashboard-specific data will be loaded by SingleBranchFlow or Dashboardshow
} catch (error) {
console.error('Error initializing dashboard data:', error);
}
};
// Cleanup effect to handle component unmounting
useEffect(() => {
return () => {
isMountedRef.current = false;
};
}, []);
useEffect(() => {
if (
BranchId != null &&
BranchId != undefined &&
CompBranchData?.length > 0 &&
!isLoadingBranchData
) {
// Set branch name if we have branch data
const currentBranch = CompBranchData?.filter(
(item) => item?.BrId == BranchId
)?.[0];
if (currentBranch) {
setBranchName(currentBranch.BrName);
}
// Handle single branch flow only if we have exactly one branch
if (CompBranchData?.length == 1) {
if (UserType != 'Super Admin User') {
SingleBranchFlow();
} else {
const checkData = SAdminUserData?.filter(
(item) =>
item?.AppId == AppId &&
item?.CompId == CompId &&
item?.BranchId == BranchId
);
if (
UserType == 'Super Admin User' &&
(checkData?.length == 0 || checkData?.[0]?.Status !== 'Y')
) {
userDropData();
setModal(true);
} else {
SingleBranchFlow();
}
}
}
}
}, [
BranchId,
CompBranchData,
isLoadingBranchData,
UserType,
AppId,
CompId,
SAdminUserData,
]);
useEffect(() => {
if (
AppId &&
CompId &&
BranchId &&
dates &&
selection === 'top-selling-products'
) {
const data = {
AppId,
CompId,
BranchId,
pageNumber: 1,
FromDate: dates[0]?.format('YYYY-MM-DD') || intialFromDate,
ToDate: dates[1]?.format('YYYY-MM-DD') || intialToDate,
};
setPage(1);
fetchProducts(data);
setIsInitialLoad(true);
}
}, [selection]);
const userDropData = async () => {
const gettinguserDropDown = await dispatch(
UserDataBasedOnBranchId(seletedBranchData ? seletedBranchData : BranchId)
).unwrap();
if (gettinguserDropDown?.data?.statusCode === 1) {
let finaluserDropDown = gettinguserDropDown?.data?.data?.filter(
(value) => value.ActiveStatus === 'A'
);
setuserDropDown(finaluserDropDown);
}
};
const onComplete = useCallback(() => {
setMessageData(null);
setMessageType(null);
}, []);
const fetchApi = async () => {
let data = {
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
EmpId: UserId,
};
let response = await dispatch(getEmpAccess(data)).unwrap();
let datas = response?.data?.data?.[0]?.EmpAccessDetails?.filter((item) =>
['Add Product', 'Product Receipt', 'Daily Sales', 'Sales'].includes(
item.ConfigName
)
);
console.log(datas, 'ffsasasf');
setEmpData(datas);
};
const getExpdate = async () => {
let data = {
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
};
let res = await dispatch(getAppSubscriptionDate(data)).unwrap();
if (res?.data?.statusCode === 1 && res?.data?.data?.length > 0) {
const remaining = res?.data?.data?.[0];
// let RemainingDays = expData?.RemainingDays;
// let RemainingHours=expData?.RemainingHours;
// let RemainingMinutes=expData?.RemainingMinutes;
// let RemainingSeconds=expData?.RemainingSeconds
const now = new Date();
const totalMs =
remaining.RemainingDays * 24 * 60 * 60 * 1000 +
remaining.RemainingHours * 60 * 60 * 1000 +
remaining.RemainingMinutes * 60 * 1000 +
remaining.RemainingSeconds * 1000;
const futureDate = new Date(now.getTime() + totalMs);
const formatted = ExtractDateFormate(
futureDate.toISOString().split('T')[0]
);
// futureDate.toLocaleString();
setExpiryDate(formatted);
}
};
const getSalesHdrFn = (FromDate, ToDate) => {
let today = new Date().toISOString().split('T')[0].split('-');
let data = {
CompId: CompId,
...(!selectedBranchForFilter ? { BranchId: BranchId } : {}),
AppId: AppId,
FromDate: FromDate ? FromDate : `${today[0]}-${today[1]}-${today[2]}`,
ToDate: ToDate ? ToDate : `${today[0]}-${today[1]}-${today[2]}`,
};
console.log(data, 'getSalesHdrFn');
dispatch(getSalesHdr(data))
.unwrap()
.then((response) => {
if (response?.data?.statusCode === 1) {
setSalesHdr(response?.data?.data);
} else {
setSalesHdr([]);
console.error('Failed to fetch pre-order dashboard data');
}
})
.catch((error) => {
console.error('Error fetching pre-order dashboard:', error);
});
};
const getTopBuyingCustomers = (FromDate, ToDate) => {
let today = new Date().toISOString().split('T')[0].split('-');
let data = {
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
FromDate: FromDate ? FromDate : `${today[2]}-${today[1]}-${today[0]}`,
ToDate: ToDate ? ToDate : `${today[2]}-${today[1]}-${today[0]}`,
};
dispatch(getTopSellingCustomers(data))
.unwrap()
.then((response) => {
if (response?.data?.statusCode === 1) {
setTopsellingCus(response?.data?.data);
} else {
console.error('Failed to fetch pre-order dashboard data');
}
})
.catch((error) => {
console.error('Error fetching pre-order dashboard:', error);
});
};
const getpreOrderDashBoardFn = (FromDate, ToDate) => {
let today = new Date().toISOString().split('T')[0].split('-');
let data = {
CompId: CompId,
...(!selectedBranchForFilter ? { BranchId: BranchId } : {}),
AppId: AppId,
FromDate: FromDate ? FromDate : `${today[0]}-${today[1]}-${today[2]}`,
ToDate: ToDate ? ToDate : `${today[0]}-${today[1]}-${today[2]}`,
};
dispatch(getpreOrderDashBoard(data))
.unwrap()
.then((response) => {
if (response?.data?.statusCode === 1) {
setpreorderData(response?.data?.data);
} else {
console.error('Failed to fetch pre-order dashboard data');
}
})
.catch((error) => {
console.error('Error fetching pre-order dashboard:', error);
});
};
const fetchBranchData = async () => {
// Prevent duplicate calls
if (isLoadingBranchData) {
return;
}
setIsLoadingBranchData(true);
try {
let data = {
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
UserId: UserId,
};
if (UserType === 'Super Admin' || UserType === 'Super Admin User') {
const response = await dispatch(
getCompBranchData({ CompId: CompId, AppId: AppId })
).unwrap();
if (response?.data?.statusCode === 1 && isMountedRef.current) {
setBranchName(
response?.data?.data?.filter((item) => item?.BrId == BranchId)?.[0]
?.BrName
);
setCompBranchData(response?.data?.data);
setIsmounted(false);
}
} else if (
UserType === 'Admin' ||
UserType === 'Admin User' ||
UserType == 'Employee'
) {
if (UserType == 'Employee') {
const EmpAcessRepsonse = await dispatch(
getEmpAccesData(data)
).unwrap();
setEmpAccess(EmpAcessRepsonse?.data?.data);
}
const response = await dispatch(
getCompBranchData({ AppId: AppId, UserId: UserId, CompId: CompId })
).unwrap();
if (response?.data?.statusCode === 1 && isMountedRef.current) {
setBranchName(
response?.data?.data?.filter((item) => item?.BrId == BranchId)?.[0]
?.BrName
);
setCompBranchData(response?.data?.data);
if (response?.data?.data?.length > 1) {
setIsmounted(false);
}
}
console.log('Branch data fetched successfully:', response?.data?.data);
}
let AppDetails = await dispatch(
getPurchasedAppDetails({ AppId, UserId })
).unwrap();
//;
if (AppDetails?.data?.statusCode === 1 && isMountedRef.current) {
setAppDetails(AppDetails?.data?.data);
}
} catch (error) {
console.error('Error fetching branch data:', error);
} finally {
setIsLoadingBranchData(false);
}
};
let topSellingProductsFn = async () => {
const today = new Date();
const year = today.getFullYear();
const month = today.getMonth(); // 0-based: Jan = 0
// Last day of the current month
const lastDay = new Date(year, month + 1, 0); // 0 = last day of previous month
const formatDate = (date) =>
`${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
const data = {
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
FromDate: `${year}-${String(month + 1).padStart(2, '0')}-01`, // First day
ToDate: formatDate(lastDay), // e.g. 2025-07-31
};
dispatch(getTopSellingProduct(data))
.unwrap()
.then((response) => {
if (response?.data?.statusCode === 1) {
setTopSellingProducts(response?.data?.data);
} else {
console.error('Failed to fetch top selling products');
}
})
.catch((error) => {
console.error('Error fetching top selling products:', error);
});
};
const CustPendingBalance = () => {
dispatch(
getAllCustomerPendingBalance({
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
})
)
.unwrap()
.then((response) => {
if (response?.data?.statusCode === 1) {
setcustomerPendingBalance(response?.data?.data);
} else {
console.error('Failed to fetch top selling products');
}
})
.catch((error) => {
console.error('Error fetching top selling products:', error);
});
};
const getAllProdId = async (branchId) => {
let data = {
CompId: CompId,
...(selectedBranchForFilter !== 'all'
? { BranchId: branchId || BranchId }
: {}),
AppId: AppId,
};
let response = await dispatch(getAllprodIds(data)).unwrap();
if ((response.data.statusCode = 1)) {
setAllProdIds(response.data.data);
} else {
setAllProdIds([]);
}
};
useEffect(() => {
if (selectedBranchForFilter && initialFetchCompleted) {
getAllProdId(selectedBranchForFilter);
}
}, [selectedBranchForFilter]);
const fetchData = async () => {
try {
const [expireRes, lowStockRes] = await Promise.all([
dispatch(
getExpireProductsList({
compId: CompId,
...(!selectedBranchForFilter ? { branchId: BranchId } : {}),
appId: AppId,
})
)?.unwrap(),
dispatch(
getLowStockAlertProductsList({
compId: CompId,
...(!selectedBranchForFilter ? { branchId: BranchId } : {}),
appId: AppId,
})
)?.unwrap(),
]);
if (expireRes?.data?.statusCode === 1) {
setExpiredList(expireRes?.data?.data);
}
if (lowStockRes?.data?.statusCode === 1) {
setLowStock(lowStockRes?.data?.data);
}
} catch (err) {
// setMessage({ type: 'error', data: 'API failed' });
}
};
const datasets = [
dinePreference && {
name: 'Dine In',
color: '#978FED',
data: DineInData,
},
{
name: takeAwayPreference ? 'Takeaway' : 'Sales',
color: '#EE89DF',
data: TakeAway,
},
{
name: 'Self booking',
color: '#F6CF7D',
data: selfbooking,
},
].filter(Boolean);
const UserDropDownChange = async (e) => {
setSelectedUserData(e);
};
const handlePageChange = async () => {
if (CompBranchData?.length === 1) {
const commonUrl = import.meta.env.ENV_COMMON_BASE_URL;
const MobileNo = encryptedValuesUrlFun(getSession('MobileNo'));
const userName = encryptedValuesUrlFun(getSession('userName'));
const UserId = encryptedValuesUrlFun(getSession('UserId'));
const UserType = encryptedValuesUrlFun(getSession('UserType'));
const CompId = encryptedValuesUrlFun(getSession('CompId'));
const CompName = encryptedValuesUrlFun(getSession('CompName'));
const SessionId = encryptedValuesUrlFun(getSession('SessionId'));
if (sessionStorage.getItem('BranchId') !== null) {
clearSession('BranchId');
}
if (sessionStorage.getItem('AppId') !== null) {
clearSession('AppId');
}
const param = {
MN: MobileNo,
UN: userName,
UD: UserId,
UT: UserType,
CD: CompId,
CN: CompName,
SD: SessionId,
};
const queryParams = new URLSearchParams(param).toString();
window.location.replace(
`${commonUrl}/home/landing-page/home?${queryParams}`
);
} else {
setseletedBranchData();
if (sessionStorage.getItem('BranchId') !== null) {
clearSession('BranchId');
}
navigate(`${subDirectory}app-page/branch-login`);
}
if (sessionStorage.getItem('hasRefreshed') !== null) {
sessionStorage.removeItem('hasRefreshed');
}
setModal(false);
};
const handleUserProfile = () => {
setUserprofile((prev) => !prev);
};
const handleChange = (index, event) => {
const value = event.target.value;
if (/^\d$/.test(value)) {
const newPin = [...pin];
newPin[index] = value;
setPin(newPin);
if (index < inputRefs?.current?.length - 1) {
inputRefs?.current[index + 1]?.focus(); // Move to next input
}
if (newPin.every((num) => num !== '')) {
handleSubmit(newPin.join('')); // Call function when all 4 digits are entered
} // Call function when all 4 digits are entered
} else {
event.target.value = '';
const newPin = [...pin];
newPin[index] = value;
setPin(newPin); // Clear input if more than one digit is entered
}
};
const handleKeyDown = (index, event) => {
if (event.key === 'Backspace' && index > 0 && !event.target.value) {
inputRefs?.current[index - 1]?.focus(); // Move to previous input on backspace
}
};
const handleSubmit = async (enteredPin) => {
if (otp == Number(enteredPin)) {
let data = {
CompId: CompId,
BranchId:
seletedBranchData != null && seletedBranchData != undefined
? seletedBranchData
: BranchId,
AppId: AppId,
UserId: UserId,
SignInType: SelectTypeName,
SecurityCode: Number(enteredPin),
UpdatedBy: UserId,
SessionId: sessionId,
EmpId: selectedUserData,
};
let response = await dispatch(PUTLoginuser(data)).unwrap();
if (response?.data?.statusCode == 1) {
await dispatch(checkSession({ UserId, sessionId })).unwrap();
setModal(false);
inputRefs?.current.forEach((ref) => {
if (ref) {
ref.value = '';
}
});
setPin(['', '', '', '']);
SingleBranchFlow();
}
} else {
alert(`Invalid ${SelectType == 'O' ? 'OTP' : 'Pin'}`);
}
};
const ChangeMethod = (e) => {
setSelectType(e);
setSelectTypeName(e === 'O' ? 'OTP' : 'PIN');
};
const sentpinfn = async () => {
let data = {
CompId: CompId,
BranchId:
seletedBranchData != null && seletedBranchData != undefined
? seletedBranchData
: BranchId,
AppId: AppId,
UserId: UserId,
SignInType: SelectTypeName,
CreatedBy: UserId,
EmpId: selectedUserData,
};
let response = await dispatch(PostLoginSuser(data)).unwrap();
if (response?.data?.statusCode == 1) {
setOtp(response?.data?.OTP || response?.data?.PIN);
setpinInput(true); // Show PIN/OTP input fields
setSeconds(timerDuration); // Start the countdown timer
setDisabled(true); // Disable the button temporarily
if (SelectTypeName === 'OTP') {
setFirstTimeOtp(true); // Set OTP as sent
} else {
setFirstTimePin(true); // Set PIN as sent
}
}
};
const handleClick = async () => {
if (selectedUserData) {
if (clicked.current) return;
clicked.current = true;
if (seconds === 0) {
// Disable the button temporarily
sentpinfn(); // Resend PIN/OTP after 30 seconds
}
inputRefs?.current.forEach((ref) => {
if (ref) {
ref.value = ''; // Reset the value of each input
}
});
setPin(['', '', '', '']);
} else {
alert('Please select user');
}
};
const SingleBranchFlow = async () => {
try {
let data = {
CompId: CompId,
BranchId: BranchId ? BranchId : globalbranchid,
AppId: AppId,
};
let res = await dispatch(getPreferenceData(data)).unwrap();
setIsmounted(false);
const filteredDatas = res?.data?.data?.[0]?.SettingDtlDetails?.filter(
(item) =>
item.SettingIdName?.toLowerCase() === 'dashboard' &&
item.SettingValue === 'N'
);
if (!RedirectStatus && filteredDatas?.length > 0) {
if (
res?.data?.data?.[0]?.SettingDtlDetails.find(
(item) => item.SettingIdName === 'Dashboard'
)?.SettingValue === 'N'
) {
if (UserType !== 'Employee') {
dispatch(ChangeRedirectStatus(true));
// await dispatch(getTemplate({ CompId, BranchId, AppId })).unwrap();
navigate(`${subDirectory}sales`);
} else if (
EmpAcces?.length > 0 &&
EmpAcces?.[0]?.EmpAccessDetails?.find(
(item) => item?.ConfigName === 'Sales'
)?.ReadAccess === 'Y'
) {
dispatch(ChangeRedirectStatus(true));
// await dispatch(getTemplate({ CompId, BranchId, AppId })).unwrap();
navigate(`${subDirectory}sales`);
} else {
// Only call Dashboardshow if not already loading
if (!isLoadingDashboard) {
Dashboardshow();
}
}
} else {
// Only call Dashboardshow if not already loading
if (!isLoadingDashboard) {
Dashboardshow();
}
}
} else {
// Only call Dashboardshow if not already loading
if (!isLoadingDashboard) {
Dashboardshow();
}
}
} catch (error) {
console.error('Error in SingleBranchFlow:', error);
}
};
useEffect(() => {
if (SessionData && CompId && BranchId && AppId && !isInitialLoad) {
Dashboardshow();
}
}, [SessionData, CompId, BranchId, AppId, isInitialLoad]);
const Dashboardshow = async () => {
// Prevent duplicate calls and only call Dashboardshow if not already loading
if (isLoadingDashboard) {
return;
}
setIsLoadingDashboard(true);
try {
let data;
if (UserType === 'Employee') {
data = {
CompId: CompId,
...(!selectedBranchForFilter ? { BranchId: BranchId } : {}),
AppId: AppId,
UserId: UserId,
};
} else {
data = {
CompId: CompId,
...(!selectedBranchForFilter ? { BranchId: BranchId } : {}),
AppId: AppId,
};
}
console.log(data, 'data');
let response = await dispatch(getdashboard(data)).unwrap();
if (isMountedRef.current) {
setApiData(response?.data?.data);
setPiedat(response?.data?.data);
setResponseData(response?.data?.statusCode);
}
} catch (error) {
console.error('Error fetching dashboard data:', error);
} finally {
setIsLoadingDashboard(false);
}
};
const dateFormat = 'DD-MM-YYYY';
const onChangeBranchFilter = async (branchId) => {
if (isLoadingBranchFilter) {
return;
}
setIsLoadingBranchFilter(true);
setSelectedBranchForFilter(branchId);
try {
if (branchId === 'all') {
await fetchAllBranchesData();
} else {
await fetchSingleBranchData(branchId);
}
} catch (error) {
console.error('Error changing branch filter:', error);
} finally {
setIsLoadingBranchFilter(false);
}
};
const fetchAllBranchesData = async () => {
try {
if (!CompBranchData || CompBranchData.length === 0) return;
let data;
if (UserType === 'Employee') {
data = {
CompId: CompId,
AppId: AppId,
UserId: UserId,
};
} else {
data = { CompId: CompId, AppId: AppId };
}
let response = await dispatch(getdashboard(data)).unwrap();
if (response?.data?.statusCode === 1) {
setApiData(response?.data?.data);
setPiedat(response?.data?.data);
}
setApiData(response?.data?.data);
setPiedat(response?.data?.data);
} catch (error) {
console.error('Error fetching all branches data:', error);
}
// Also refresh other data for all branches
getpreOrderDashBoardFnAllBranches();
getTopBuyingCustomersAllBranches();
getSalesHdrFnAllBranches();
};
const fetchSingleBranchData = async (branchId) => {
let data;
if (UserType === 'Employee') {
data = {
CompId: CompId,
BranchId: branchId,
AppId: AppId,
UserId: UserId,
};
} else {
data = { CompId: CompId, BranchId: branchId, AppId: AppId };
}
let response = await dispatch(getdashboard(data)).unwrap();
setApiData(response?.data?.data);
setPiedat(response?.data?.data);
// Also refresh other data
getpreOrderDashBoardFn();
getTopBuyingCustomers();
getSalesHdrFn();
};
// Function to aggregate data from multiple branches
const aggregateBranchData = (branchDataArray) => {
const aggregated = {
DineInOrderCount: 0,
TakeAwayOrderCount: 0,
SelfTakeAwayOrderCount: 0,
OverAllSalesAmt: 0,
OverAllDineInAmount: 0,
OverAllTakeAwayAmount: 0,
ChartDtl: [],
};
branchDataArray.forEach((branchData) => {
if (branchData) {
aggregated.DineInOrderCount += branchData.DineInOrderCount || 0;
aggregated.TakeAwayOrderCount += branchData.TakeAwayOrderCount || 0;
aggregated.SelfTakeAwayOrderCount +=
branchData.SelfTakeAwayOrderCount || 0;
aggregated.OverAllSalesAmt += branchData.OverAllSalesAmt || 0;
aggregated.OverAllDineInAmount += branchData.OverAllDineInAmount || 0;
aggregated.OverAllTakeAwayAmount +=
branchData.OverAllTakeAwayAmount || 0;
// Merge chart data (you might want to customize this based on your needs)
if (branchData.ChartDtl && branchData.ChartDtl.length > 0) {
aggregated.ChartDtl = aggregated.ChartDtl.concat(branchData.ChartDtl);
}
}
});
return aggregated;
};
// Helper functions for fetching data from all branches
const getpreOrderDashBoardFnAllBranches = async (FromDate, ToDate) => {
if (!CompBranchData || CompBranchData.length === 0) return;
try {
let today = new Date().toISOString().split('T')[0].split('-');
let data = {
CompId: CompId,
...(!selectedBranchForFilter ? { BranchId: BranchId } : {}),
AppId: AppId,
FromDate: FromDate ? FromDate : `${today[0]}-${today[1]}-${today[2]}`,
ToDate: ToDate ? ToDate : `${today[0]}-${today[1]}-${today[2]}`,
};
const response = await dispatch(getpreOrderDashBoard(data)).unwrap();
if (response?.data?.statusCode === 1) {
setpreorderData(response?.data?.data);
} else {
setpreorderData([]);
console.error('Failed to fetch pre-order dashboard data');
}
} catch (error) {
console.error('Error fetching preorder data for all branches:', error);
}
};
const getTopBuyingCustomersAllBranches = async (FromDate, ToDate) => {
if (!CompBranchData || CompBranchData.length === 0) return;
try {
const allBranchPromises = CompBranchData.map(async (branch) => {
let today = new Date().toISOString().split('T')[0].split('-');
let data = {
CompId: CompId,
BranchId: branch.BrId,
AppId: AppId,
FromDate: FromDate ? FromDate : `${today[2]}-${today[1]}-${today[0]}`,
ToDate: ToDate ? ToDate : `${today[2]}-${today[1]}-${today[0]}`,
};
const response = await dispatch(getTopSellingCustomers(data)).unwrap();
return response?.data?.data || [];
});
const allBranchData = await Promise.all(allBranchPromises);
// Flatten and merge customer data from all branches
const allCustomers = allBranchData.flat();
// Group by customer and sum amounts
const customerMap = {};
allCustomers.forEach((customer) => {
if (customer.CustName) {
if (customerMap[customer.CustName]) {
customerMap[customer.CustName].TotalSalesAmount +=
customer.TotalSalesAmount || 0;
} else {
customerMap[customer.CustName] = { ...customer };
}
}
});
// Convert back to array and sort by total sales
const aggregatedCustomers = Object.values(customerMap)
.sort((a, b) => (b.TotalSalesAmount || 0) - (a.TotalSalesAmount || 0))
.slice(0, 10); // Top 10 customers
setTopsellingCus(aggregatedCustomers);
} catch (error) {
console.error('Error fetching top customers for all branches:', error);
}
};
const getSalesHdrFnAllBranches = async (FromDate, ToDate) => {
if (!CompBranchData || CompBranchData.length === 0) return;
try {
let today = new Date().toISOString().split('T')[0].split('-');
let data = {
CompId: CompId,
...(!selectedBranchForFilter ? { BranchId: BranchId } : {}),
AppId: AppId,
FromDate: FromDate ? FromDate : `${today[0]}-${today[1]}-${today[2]}`,
ToDate: ToDate ? ToDate : `${today[0]}-${today[1]}-${today[2]}`,
};
const response = await dispatch(getSalesHdr(data)).unwrap();
setSalesHdr(response?.data?.data);
} catch (error) {
console.error('Error fetching sales header for all branches:', error);
}
};
const onRangeChange = async (dates, dateStrings) => {
SetZero(true);
let fromDateVal = dateStrings[0]?.split('-');
let toDateVal = dateStrings[1]?.split('-');
setDates(dates);
setInitialDate(false);
if (dates && selection === 'dashboard') {
const fromDate =
fromDateVal[2] + '-' + fromDateVal[1] + '-' + fromDateVal[0];
const toDate = toDateVal[2] + '-' + toDateVal[1] + '-' + toDateVal[0];
if (selectedBranchForFilter === 'all') {
// Fetch data for all branches with date range
await fetchAllBranchesDataWithDateRange(fromDate, toDate);
} else {
// Fetch data for specific branch with date range
await fetchSingleBranchDataWithDateRange(
selectedBranchForFilter ? selectedBranchForFilter : BranchId,
fromDate,
toDate
);
}
getpreOrderDashBoardFn();
} else if (selection === 'top-selling-products') {
const FromDate = dates?.[0]?.format('YYYY-MM-DD') || intialFromDate;
const ToDate = dates?.[1]?.format('YYYY-MM-DD') || intialToDate;
await fetchProducts({
AppId,
CompId,
BranchId,
FromDate,
ToDate,
pageNumber: 1,
});
setPage(1);
}
};
const fetchProducts = async (data) => {
setLoading(true);
try {
const res = await dispatch(getTopSellingProduct(data))?.unwrap();
if (res?.data?.statusCode === 1 && res?.data?.data?.length > 0) {
setProducts(res?.data?.data);
setTotalPages(Math.ceil(res?.data?.data?.[0]?.TotalCount / 10));
} else {
setProducts([]);
setTotalPages(0);
}
} catch (error) {
console.error('Error fetching products:', error);
}
setLoading(false);
};
const fetchAllBranchesDataWithDateRange = async (fromDate, toDate) => {
try {
let data;
if (UserType === 'Employee') {
data = {
CompId: CompId,
...(!selectedBranchForFilter ? { BranchId: BranchId } : {}),
AppId: AppId,
FromDate: fromDate,
ToDate: toDate,
UserId: UserId,
};
} else {
data = {
CompId: CompId,
...(!selectedBranchForFilter ? { BranchId: BranchId } : {}),
AppId: AppId,
FromDate: fromDate,
ToDate: toDate,
};
}
const response = await dispatch(getdashboarddate(data)).unwrap();
if (response?.data?.statusCode === 1) {
setDateApiData(response?.data?.data);
setApiData(response?.data?.data);
} else {
setDateApiData([]);
setApiData([]);
}
// const allBranchData = await Promise.all(allBranchPromises);
// // Aggregate the data from all branches
// const aggregatedData = aggregateBranchData(allBranchData);
// setDateApiData([aggregatedData]);
// setApiData([aggregatedData]);
// setPiedat([aggregatedData]);
// Also refresh other data for all branches with date range
getpreOrderDashBoardFnAllBranches(fromDate, toDate);
getTopBuyingCustomersAllBranches(fromDate, toDate);
getSalesHdrFnAllBranches(fromDate, toDate);
getSalesHdrFn(fromDate, toDate);
} catch (error) {
console.error('Error fetching all branches data with date range:', error);
setDateApiData([]);
setApiData([]);
setPiedat([]);
setpreorderData([]);
setTopsellingCus([]);
setSalesHdr([]);
}
};
// Function to fetch data for single branch with date range
const fetchSingleBranchDataWithDateRange = async (
branchId,
fromDate,
toDate
) => {
try {
const targetBranchId = branchId === 'all' ? BranchId : branchId;
let data;
if (UserType === 'Employee') {
data = {
CompId: CompId,
BranchId: targetBranchId,
AppId: AppId,
FromDate: fromDate,
ToDate: toDate,
UserId: UserId,
};
} else {
data = {
CompId: CompId,
BranchId: targetBranchId,
AppId: AppId,
FromDate: fromDate,
ToDate: toDate,
};
}
let response = await dispatch(getdashboarddate(data)).unwrap();
if (response?.data?.statusCode === 1) {
setDateApiData(response?.data?.data);
setApiData(response?.data?.data);
setPiedat(response?.data?.data);
getpreOrderDashBoardFn(fromDate, toDate);
getTopBuyingCustomers(fromDate, toDate);
getSalesHdrFn(fromDate, toDate);
} else {
setDateApiData([]);
setApiData([]);
setPiedat([]);
setpreorderData([]);
setTopsellingCus([]);
setSalesHdr([]);
}
} catch (error) {
console.error(
'Error fetching single branch data with date range:',
error
);
setDateApiData([]);
setApiData([]);
setPiedat([]);
setpreorderData([]);
setTopsellingCus([]);
setSalesHdr([]);
}
};
const disabledDate = (current) => {
const today = dayjs().endOf('day');
const firstSalesDate = ApiData?.[0]?.Firstsalesdate;
// If firstSalesDate exists and is valid, use it as minimum date
if (firstSalesDate) {
const minDate = dayjs(firstSalesDate).startOf('day');
return current && (current < minDate || current > today);
}
// If no firstSalesDate, disable future dates only
return current && current > today;
};
useEffect(() => {
const handleResize = () => {
setCollapse(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
useEffect(() => {
const handleClickOutside = (event) => {
if (
userProfileRef.current &&
!userProfileRef.current.contains(event.target)
) {
setUserprofile(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [userProfileRef]);
const Logout = async () => {
const status = 'N'; // replace with your actual status
const res = await dispatch(GenerateLogout({ UserId, status })).unwrap();
if (res?.data?.statusCode === 1) {
sessionStorage.clear();
window.location.replace(`${commonUrl}`);
}
};
if (ismounted)
return (
<div
style={{
position: 'fixed',
top: '0',
left: '0',
right: '0',
bottom: '0',
height: '100vh',
width: '100vw',
backgroundColor: '#fff',
}}
>
<Loader />
</div>
);
const handleSelectChange = (value) => {
setSelection(value);
};
return (
<div className="RetailDashboard-Master">
<div className="dashboardHeader">
<Messages
messageType={messageType}
messageData={messageData}
onComplete={onComplete}
/>
<div className="shopName">
<div>{branchName}</div>
</div>
<div className="dashboareduser">
<div>
{(() => {
if (!ExpiryDate) return null;
const today = new Date();
const expiryDate = new Date(ExpiryDate);
const timeDiff = expiryDate.getTime() - today.getTime();
const daysDiff = Math.ceil(timeDiff / (1000 * 3600 * 24));
if (daysDiff <= 7 && daysDiff >= 0) {
return (
<div>
<img src={sandClock} alt="" width={25} />
{PricingAppPricingName?.[0]?.PricingName && (
<div className="infoplan">
Current Plan:{' '}
{PricingAppPricingName?.[0]?.PricingName +
' / ' +
PricingAppPricingName?.[0]?.Type}
</div>
)}
<div className="infoplan">Plan Expiry on {ExpiryDate}</div>
</div>
);
}
return null;
})()}
</div>
<div className="userShortName" onClick={handleUserProfile}>
{(AppDetails?.[0]?.UserName || 'Guest')
?.substring(0, 2)
?.toUpperCase()}
</div>
{userprofile && (
<BSNavBarUserInfo
isOpen={userprofile}
divRef={userProfileRef}
userProfileData={{
UserImage: user,
UserName: AppDetails?.[0]?.UserName,
MobileNo: AppDetails?.[0]?.MobileNo,
}}
Logout={Logout}
/>
)}
</div>
</div>
<div
className={`dashboardHeader2${selection === 'top-selling-products' ? ' top' : ''}`}
>
{/* <div style={{ fontSize: '18px', fontWeight: '500' }}>Dashboard</div> */}
{/* public Login dashboard*/}
<div className="tab-switcher">
{tabs?.map((tab) => (
<button
key={tab.value}
className={`tab-button ${selection === tab?.value ? 'active' : ''}`}
onClick={() => handleSelectChange(tab?.value)}
>
{tab.label}
</button>
))}
</div>
{/* Branch Filter Dropdown */}
{CompBranchData?.length > 1 && selection !== 'top-selling-products' && (
<div className="branch-filter-dropdown">
<DropDowns
options={[
{ value: 'all', label: 'All Branches' },
...CompBranchData?.map((option) => ({
value: option.BrId,
label: option.BrName,
})),
]}
className="branch-filter-select"
onChangeFunction={onChangeBranchFilter}
valueData={selectedBranchForFilter}
defaultValue="all"
placeholder="All Branches"
/>
</div>
)}
<div className="FilterAndRefresh">
<RangePicker
presets={[]}
onChange={onRangeChange}
format={dateFormat}
disabledDate={disabledDate}
className="datepickerDashboardrange"
inputReadOnly={true}
/>
{/* <div className="refershdashboard">
<div>
{' '}
<IoMdRefresh />
Refresh
</div>
<span>10sec auto refresh</span>
</div> */}
</div>
</div>
{selection === 'dashboard' ? (
<>
<div className="dashboardMainGrid">
<div className="TotalRevenue">
<div className="tlxHeader"></div>
<div className="TotalRevenue-Graph">
<GraphChart datasets={datasets} />
</div>
</div>
<div className="dashboardMainCenter">
<div className="todaySnapshotRow">
<p
style={{
fontSize: '13px',
marginBottom: '0.2rem',
fontWeight: '500',
fontFamily: 'Inter',
}}
>
Today's Snapshot
</p>
{selectedBranchForFilter === 'all' ? (
<div className="todaySnapFlex">
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{ApiData?.[0]?.BranchDtl?.map((item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>{item.BrName || 'N/A'}</strong>
<br />
Orders:{' '}
{(item.DineInOrderCount || 0) +
(item.TakeAwayOrderCount || 0)}
<br />
Revenue: ₹{item.OverAllSalesAmt || 0}
</div>
))}
</div>
}
placement="bottom"
>
<div className="todaySnapshotBox orders">
{ApiData?.[0]?.DineInOrderCount +
ApiData?.[0]?.TakeAwayOrderCount +
ApiData?.[0]?.DineIn_TakeAwayOrderCount || 0}{' '}
<div>Orders</div>
</div>
</Tooltip>
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{ApiData?.[0]?.BranchDtl?.map((item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>{item.BrName || 'N/A'}</strong>
<br />
Orders:{' '}
{(item.DineInOrderCount || 0) +
(item.TakeAwayOrderCount || 0)}
<br />
Revenue: ₹{item.OverAllSalesAmt || 0}
</div>
))}
</div>
}
placement="bottom"
>
{!isCheckSportsApp && (
<div className="todaySnapshotBox revenue">
{ApiData?.[0]?.OverAllSalesAmt -
ApiData?.[0]?.OverAllOfferAmount || 0}{' '}
<div>Revenue</div>
</div>
)}
</Tooltip>
<Tooltip
title={`Total New Customers across all branches: ${SalesHdr?.[0]?.NewCustomers || 0}`}
placement="bottom"
>
<div className="todaySnapshotBox customers">
{SalesHdr?.[0]?.NewCustomers || 0}{' '}
<div>New Customers</div>
</div>
</Tooltip>
{!isCheckSportsApp && (
<Tooltip
title={`Total Pending Bills across all branches: ${SalesHdr?.[0]?.PendingBill || 0}`}
placement="bottom"
>
<div className="todaySnapshotBox pending">
{SalesHdr?.[0]?.PendingBill || 0}{' '}
<div>Pending Bills</div>
</div>
</Tooltip>
)}
</div>
) : (
<div>
<div className="todaySnapshotBox orders">
{ApiData?.[0]?.DineInOrderCount +
ApiData?.[0]?.TakeAwayOrderCount +
ApiData?.[0]?.DineIn_TakeAwayOrderCount || 0}{' '}
<div>Orders</div>
</div>
{!isCheckSportsApp && (
<div className="todaySnapshotBox revenue">
{(
(ApiData?.[0]?.OverAllSalesAmt || 0) -
(ApiData?.[0]?.OverAllOfferAmount || 0)
).toFixed(2)}{' '}
<div>Revenue </div>
</div>
)}
<div className="todaySnapshotBox customers">
{SalesHdr?.[0]?.NewCustomers || 0}{' '}
<div>New Customers</div>
</div>
{!isCheckSportsApp && (
<div className="todaySnapshotBox pending">
{SalesHdr?.[0]?.PendingBill || 0}{' '}
<div>Pending Bills</div>
</div>
)}
</div>
)}
</div>
<div className="quickActionsRow">
<div
onClick={() => {
const hasEmpAccess = EmpData?.find(
(item) =>
item.ConfigName === 'Add Product' &&
item.ReadAccess === 'Y'
);
if (!hasEmpAccess && UserType === 'Employee') {
setMessageData('Please contact your admin to get access');
setMessageType('error');
}
if (isCheckSportsApp) {
navigate(`${subDirectory}setting/products-master/new`);
}
if (
(UserType === 'Employee' && hasEmpAccess) ||
UserType === 'Admin' ||
UserType === 'Super Admin' ||
UserType === 'Super Admin User'
) {
navigate(`${subDirectory}setting/product-master/new`);
}
// setting/product-master/new
}}
className="quickActionBox"
>
<img src={Add} alt="" />
{!isCheckSportsApp ? (
<div>Add Product</div>
) : (
<div>Add Slot</div>
)}
</div>
{!isCheckSportsApp && (
<div
onClick={() => {
const hasEmpAccess = EmpData?.find(
(item) =>
item.ConfigName === 'Product Receipt' &&
item.ReadAccess === 'Y'
);
if (!hasEmpAccess && UserType === 'Employee') {
setMessageData(
'Please contact your admin to get access'
);
setMessageType('error');
}
if (
(UserType === 'Employee' && hasEmpAccess) ||
UserType === 'Admin' ||
UserType === 'Super Admin' ||
UserType === 'Super Admin User'
) {
navigate(`${subDirectory}setting/purchase-entry/new`);
}
}}
className="quickActionBox"
>
<img src={AddPurchase} alt="" />
<div>Add Purchase</div>
</div>
)}
<div
onClick={() => {
const hasEmpAccess = EmpData?.find(
(item) =>
item.ConfigName === 'Daily Sales' &&
item.ReadAccess === 'Y'
);
if (!hasEmpAccess && UserType === 'Employee') {
setMessageData('Please contact your admin to get access');
setMessageType('error');
}
if (
(UserType === 'Employee' && hasEmpAccess) ||
UserType === 'Admin' ||
UserType === 'Super Admin' ||
UserType === 'Super Admin User'
) {
navigate(`${subDirectory}report/datewisereport`);
}
}}
className="quickActionBox"
>
<img src={report} alt="" width="45px" />
<div>Report</div>
</div>
<div
className="quickActionBox"
onClick={() => {
const hasEmpAccess = EmpData?.find(
(item) =>
item.ConfigName === 'Sales' && item.ReadAccess === 'Y'
);
if (!hasEmpAccess && UserType === 'Employee') {
setMessageData('Please contact your admin to get access');
setMessageType('error');
}
if (
(UserType === 'Employee' && hasEmpAccess) ||
UserType === 'Admin' ||
UserType === 'Super Admin' ||
UserType === 'Super Admin User'
) {
navigate(`${subDirectory}sales`);
}
}}
>
<img src={invoice} alt="" />
<div>New Bill</div>
</div>
</div>
{/* ------------------------Dont Delete----------------------------- */}
{/* <div className="expensesSalesRow">
<div className="expenseBox">Electricity<div>₹1,500</div></div>
<div className="expenseBox">Purchases<div>₹12,150</div></div>
<div className="expenseBox">Salaries<div className="red">₹7,500</div></div>
</div> */}
{/* <div className="salesBreakdownRow">
<div className="salesBreakdownBox">
DineIn <div>{ApiData?.[0]?.DineInOrderCount}</div>
</div>
<div className="salesBreakdownBox">
Takeaway<div>{ApiData?.[0]?.TakeAwayOrderCount}</div>
</div>
<div className="salesBreakdownBox">
Delivery<div>{ApiData?.[0]?.SelfTakeAwayOrderCount}</div>
</div>
</div> */}
<div className="salesBreakdownRow">
{dinePreference &&
(ApiData?.[0]?.BranchDtl?.length > 1 ? (
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden',
}}
>
{ApiData[0].BranchDtl.map((item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>{item.BrName || 'N/A'}</strong>
<br />
Orders: {item.DineInOrderCount || 0}
<br />
</div>
))}
</div>
}
placement="bottom"
>
<div className="salesBreakdownBox">
DineIn <div>{ApiData?.[0]?.DineInOrderCount || 0}</div>
</div>
</Tooltip>
) : (
<div className="salesBreakdownBox">
DineIn <div>{ApiData?.[0]?.DineInOrderCount || 0}</div>
</div>
))}
<div className="salesBreakdownBox">
{takeAwayPreference ? 'Takeaway' : 'Sales'}
{ApiData?.[0]?.BranchDtl?.length > 1 ? (
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{ApiData[0].BranchDtl.map((item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>{item.BrName || 'N/A'}</strong>
<br />
Orders: {item.TakeAwayOrderCount || 0}
<br />
</div>
))}
</div>
}
placement="bottom"
>
<div>{ApiData?.[0]?.TakeAwayOrderCount || 0}</div>
</Tooltip>
) : (
<div>{ApiData?.[0]?.TakeAwayOrderCount || 0}</div>
)}
</div>
{dinePreference && takeAwayPreference && (
<div className="salesBreakdownBox">
{'DineIn + Takeaway'}
{ApiData?.[0]?.BranchDtl?.length > 1 ? (
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{ApiData[0].BranchDtl.map((item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>{item.BrName || 'N/A'}</strong>
<br />
Orders: {item.DineIn_TakeAwayOrderCount || 0}
<br />
</div>
))}
</div>
}
placement="bottom"
>
<div>
{ApiData?.[0]?.DineIn_TakeAwayOrderCount || 0}
</div>
</Tooltip>
) : (
<div>{ApiData?.[0]?.DineIn_TakeAwayOrderCount || 0}</div>
)}
</div>
)}
{!isCheckSportsApp && (
<div className="salesBreakdownBox">
{ApiData?.[0]?.BranchDtl?.length > 1 ? (
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{ApiData[0].BranchDtl.map((item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>{item.BrName || 'N/A'}</strong>
<br />
Delivery: {item.SelfTakeAwayOrderCount || 0}
<br />
</div>
))}
</div>
}
placement="bottom"
>
Delivery
<div>{ApiData?.[0]?.SelfTakeAwayOrderCount || 0}</div>
</Tooltip>
) : (
<>
Delivery
<div>{ApiData?.[0]?.SelfTakeAwayOrderCount || 0}</div>
</>
)}
</div>
)}
</div>
</div>
{!isCheckSportsApp && (
<div className="dashboardMainRight">
<div className="productSummaryTitle">Product Summary</div>
<div className="productSummaryCard">
<div className="productSummaryRow">
<div className="productSummaryBox total">
{AllProdIds?.[0]?.BranchDtl?.length > 1 ? (
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{AllProdIds[0].BranchDtl.map((item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>{item?.BranchName || 'N/A'}</strong>
<br />
TOTAL PRODUCTS: {item?.ProductCount || 0}
<br />
</div>
))}
</div>
}
placement="bottom"
>
<div>
<p>{AllProdIds?.[0]?.TotalProductCount}</p>
<div>TOTAL PRODUCTS</div>
</div>
</Tooltip>
) : (
<div>
<p>
{AllProdIds?.[0]?.TotalProductCount ||
AllProdIds?.length}
</p>
<div>TOTAL PRODUCTS</div>
</div>
)}
</div>
<div className="productSummaryBox live">
{expiredList?.[0]?.Branchdtl?.length > 1 ? (
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{expiredList[0].Branchdtl.map((item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>{item.BranchName || 'N/A'}</strong>
<br />
Expiry Stock: {item.ProductsDtl?.length || 0}
<br />
</div>
))}
</div>
}
placement="bottom"
>
<div>
<p> {expiredList?.length}</p>
<div>EXPIRY STOCK</div>
</div>
</Tooltip>
) : (
<div>
<p> {expiredList?.length}</p>
<div>EXPIRY STOCK</div>
</div>
)}
</div>
<div className="productSummaryBox low">
{lowStockList?.[0]?.BranchDtl?.length > 1 ? (
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{lowStockList[0].BranchDtl.map((item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>{item.BranchName || 'N/A'}</strong>
<br />
LOW STOCK: {item.lowStockList?.length || 0}
<br />
</div>
))}
</div>
}
placement="bottom"
>
<div>
<p>{lowStockList?.length}</p>
<div>LOW STOCK</div>
</div>
</Tooltip>
) : (
<div>
<p> {lowStockList?.length}</p>
<div>LOW STOCK</div>
</div>
)}
</div>
<div className="productSummaryBox nostock">
{SalesHdr?.[0]?.BranchDetails?.length > 1 ? (
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{SalesHdr[0].BranchDetails.map((item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>{item.BranchName || 'N/A'}</strong>
<br />
NO STOCK: {item.NoStockProduct || 0}
<br />
</div>
))}
</div>
}
placement="bottom"
>
<div>
<p>{SalesHdr?.[0]?.NoStockProduct || 0}</p>
<div>NO STOCK</div>
</div>
</Tooltip>
) : (
<div>
<p> {SalesHdr?.[0]?.NoStockProduct || 0}</p>
<div>NO STOCK</div>
</div>
)}
</div>
</div>
</div>
<div className="notificationCenterTitle">
Notification Center
</div>
<div className="notificationCenterCard">
{expiredList?.length > 0 && (
<div className="notificationStock">
{expiredList.length} Products expiry today!
</div>
)}
{lowStockList?.length > 0 && (
<div className="notificationStock">
Low Stock count {lowStockList.length}
</div>
)}
{!expiredList?.length && !lowStockList?.length && (
<div
style={{
fontSize: '12px',
width: '100%',
textAlign: 'center',
}}
>
Notification Empty
</div>
)}
</div>
</div>
)}
</div>
{!isCheckSportsApp && (
<div className="dashboardSecondaryGrid">
<div className="topSellingProductCard">
<div className="topSellingHeader">
<div>Top Selling Product</div>
<div className="topSellingMonth">This Month</div>
</div>
{topSellingProducts.map((product, idx) => (
<div className="TopSellingProduct-list" key={idx}>
<img src={product.ProdLogo} alt={product.name} />
<div>
{product.ProdName} - {product.TotalSoldQty}{' '}
</div>
</div>
))}
</div>
<div className="preOrderSummaryCardMain">
<div className="preOrderSummaryCard">
<div className="preOrderSummaryTitle">Pre Order Summary</div>
<div className="preOrderSummaryRow">
<div className="preOrderSummaryBox total">
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{preorderData?.[0]?.BranchDtl
? preorderData?.[0]?.BranchDtl?.map(
(item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>
{item.BranchName || 'N/A'}
</strong>
<br />
Total Orders: {item.TotalOrders || 0}
<br />
</div>
)
)
: 'No Data'}
</div>
}
placement="bottom"
>
{preorderData?.[0]?.TotalOrders || 0}
<div>Total Orders</div>
</Tooltip>
</div>
<div className="preOrderSummaryBox pending">
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{preorderData?.[0]?.BranchDtl
? preorderData?.[0]?.BranchDtl?.map(
(item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>
{item.BranchName || 'N/A'}
</strong>
<br />
Total Orders: {item.PendingOrders || 0}
<br />
</div>
)
)
: 'No Data'}
</div>
}
placement="bottom"
>
{preorderData?.[0]?.PendingOrders || 0}
<div>Pending</div>
</Tooltip>
</div>
<div className="preOrderSummaryBox completed">
<Tooltip
title={
<div
className="tooltip-scrollable"
style={{
maxHeight: 300,
overflowY: 'auto',
overflowX: 'hidden', // Moves scrollbar to far right edge of tooltip
}}
>
{preorderData?.[0]?.BranchDtl
? preorderData?.[0]?.BranchDtl?.map(
(item, index) => (
<div
key={index}
style={{
marginBottom: 8,
paddingBottom: 8,
borderBottom: '1px solid #f0f0f0',
}}
>
<strong>
{item.BranchName || 'N/A'}
</strong>
<br />
Total Orders: {item.CompletedOrders || 0}
<br />
</div>
)
)
: 'No Data'}
</div>
}
placement="bottom"
>
{preorderData?.[0]?.CompletedOrders || 0}
<div>Completed</div>
</Tooltip>
</div>
</div>
</div>
<div className="creditListCardMain">
<div className="creditListTitle">Credit List</div>
<div className="creditListCard">
<div className="creditListHeader">
<div>Customer</div>
<div>Amount</div>
</div>
{customerPendingBalance?.length > 0 ? (
customerPendingBalance.map((customer, idx) => (
<div className="creditListRow" key={idx}>
<div className="">
{customer?.CustName || customer.CustMobile}
</div>
<div>₹{customer.creditBal.toFixed(2)}</div>
</div>
))
) : (
<div className="creditListRow">
<div>No Pending Balance</div>
<div>₹0.00</div>
</div>
)}
{/* <div className="creditListViewAll">View All</div> */}
</div>
</div>
<div className="stockAlertsCard">
<div className="stockAlertsTitle">Stock Alerts</div>
<div className="stockAlertsTable">
<div className="stockAlertsHeaderRow">
<div className="stockAlertsCol slno">Sl.No</div>
<div className="stockAlertsCol product">Product</div>
<div className="stockAlertsCol count">Stock Count</div>
</div>
{lowStockList?.length > 0 ? (
lowStockList?.map((item, index) => (
<div className="stockAlertsRow" key={index}>
<div className="stockAlertsCol slno">{index + 1}</div>
<div className="stockAlertsCol product">
<div className="stockAlertsProductLink">
{item?.ProdName || item?.ProdId}
</div>
</div>
<div className="stockAlertsCol count">
{item?.BalanceQty}
</div>
</div>
))
) : (
<div style={{ textAlign: 'center', fontSize: '12px' }}>
No Low Stock Product
</div>
)}
{/* <div className="stockAlertsRow">
<div className="stockAlertsCol slno">2</div>
<div className="stockAlertsCol product">
<div className="stockAlertsProductLink">
Cotton Blend Mandarin Collar Self One Design Kurta
</div>
</div>
<div className="stockAlertsCol count">4</div>
</div>
<div className="stockAlertsRow">
<div className="stockAlertsCol slno">3</div>
<div className="stockAlertsCol product">
<div className="stockAlertsProductLink">
Cotton Blend Mandarin Collar Self One Design Kurta
</div>
</div>
<div className="stockAlertsCol count">1</div>
</div> */}
{/* <div className="stockAlertsViewAll">
<a href="#">View All</a>
</div> */}
</div>
</div>
</div>
</div>
)}
</>
) : (
<>
<TopSellingProductsChart
dates={dates}
products={products}
loading={loading}
totalPages={totalPages}
page={page}
setPage={setPage}
fetchProducts={fetchProducts}
initialDate={initialDate}
/>
</>
)}
<DefaultModal
open={modal}
title="Authentication"
width={500}
footer={false}
handleCancel={handlePageChange}
children={
<>
<div className="modalContentsadminuser">
<DropDowns
options={userDropDown?.map((option) => ({
value: option?.UserId,
label: option?.UserName,
}))}
label={<label class="required">User Name</label>}
className="field-DropDown"
onChangeFunction={(e) => UserDropDownChange(e)}
isOnchanges={selectedUserData ? true : false}
valueData={selectedUserData}
disabled={disabled}
/>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<div className="RadioButton">
<RadioGrpButton
content={[
{ value: 'O', label: 'OTP' },
{ value: 'P', label: 'PIN' },
]}
fieldState={true}
defaultSelect={SelectType}
onSelectFuntion={(e) => ChangeMethod(e)}
/>
</div>
</div>
{pinInput && (
<div className="otpInputsadminuser">
{[0, 1, 2, 3].map((i) => (
<input
key={i}
ref={(el) => (inputRefs.current[i] = el)}
className="inputNumber"
type="text"
inputMode="numeric"
pattern="[0-9]"
maxLength={1}
onChange={(e) => handleChange(i, e)}
onKeyDown={(e) => handleKeyDown(i, e)}
style={{
textAlign: 'center',
width: '40px',
fontSize: '20px',
}}
/>
))}
</div>
)}
<div
style={{
width: '100%',
display: 'flex',
justifyContent: 'flex-end',
}}
>
<button
className="size-save-button-retail"
onClick={handleClick}
disabled={disabled}
>
{SelectTypeName === 'OTP'
? !FirstTimeOtp
? `send ${SelectTypeName.toLocaleLowerCase()}`
: `resend ${SelectTypeName.toLocaleLowerCase()}${
seconds > 0 ? ` in ${seconds}s` : ''
}`
: !FirstTimePin
? `send ${SelectTypeName.toLocaleLowerCase()}`
: `resend ${SelectTypeName.toLocaleLowerCase()}${
seconds > 0 ? ` in ${seconds}s` : ''
}`}
</button>
</div>
</div>
</>
}
/>
</div>
);
};
export default RetailDashboard;