import { useEffect, useState } from 'react' import { useAppSelector } from '@/redux/store'; import { useTranslations } from 'next-intl'; import dynamic from 'next/dynamic'; import Cookies from 'universal-cookie'; import { useDispatch } from 'react-redux'; import { AppDispatch } from '@/redux/store'; import { setCurrentMembersGeneralOverviewDuration } from '@/redux/features/statistics-slice' import { Loader2 } from 'lucide-react'; const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false, loading: () =>
}); export default function MembersOverviewChart() { // get needed redux state const report = useAppSelector((state) => state.statisticsReducer.value.report) const currentMembersGeneralOverviewDuration = useAppSelector((state) => state.statisticsReducer.value.currentMembersGeneralOverviewDuration) const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType) // declare global variables const dispatch = useDispatch() const cookies = new Cookies(); const t = useTranslations('statistics'); const locale = cookies.get("NEXT_LOCALE") const isRtl = locale == 'ar' ? true : false const isDark = themeType == 'dark' ? true : false const [chartSeries, setChartSeries] = useState<{ name: string; data: number[] }[]>([]); const [labels, setLabels] = useState([]) const [isLoading, setIsLoading] = useState(true); // revenue Chart // prepare chart series and handle the transaction between currentMembersGeneralOverviewDuration useEffect(() => { if (!report?.membersGeneralOverview) { setIsLoading(true); return; } setIsLoading(true); try { // if chart duration is set to this week if (currentMembersGeneralOverviewDuration == 'thisWeek') { // set the labels setLabels([t('sat'), t('sun'), t('mon'), t('tue'), t('wed'), t('thu'), t('fri')]) // Initialize default data structure const defaultWeekData = { sat: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 }, sun: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 }, mon: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 }, tue: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 }, wed: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 }, thu: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 }, fri: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 } }; // Use data from report if available, otherwise use default data const weekData = report?.membersGeneralOverview?.value?.thisWeek?.days || defaultWeekData; // prepare the chart series setChartSeries([ { name: t('totalMembers'), data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalMembers || 0), }, { name: t('totalActiveSubs'), data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalActiveSubs || 0), }, { name: t('totalUnActiveSubs'), data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalUnActiveSubs || 0), }, { name: t('totalMansMembers'), data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalMansMembers || 0), }, { name: t('totalGirlsMembers'), data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalGirlsMembers || 0), }, ]); } // if chart duration is set to this month else if(currentMembersGeneralOverviewDuration == 'thisMonth') { let thisMonthTotalSum : { week : number, thisWeekSum : { "totalMembers": number, "totalActiveSubs": number, "totalUnActiveSubs": number, "totalMansMembers": number, "totalGirlsMembers": number } }[]; if(report?.membersGeneralOverview?.value.thisMonth) { // if we founded a data for the current month thisMonthTotalSum = report?.membersGeneralOverview?.value.thisMonth.weeks.map((v : any , i : number) : { week: number, thisWeekSum : { "totalMembers": number, "totalActiveSubs": number, "totalUnActiveSubs": number, "totalMansMembers": number, "totalGirlsMembers": number } } => { // we init the this week sum let thisWeekSum = { "totalMembers": 0, "totalActiveSubs": 0, "totalUnActiveSubs": 0, "totalMansMembers": 0, "totalGirlsMembers": 0 } // we map through this month weeks v.days.map((w : { 'sat': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'sun': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'mon': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'tue': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'wed': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'thu': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'fri': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, } } , i : number) => { // we loop through week days and we sum there data Object.keys(w).forEach(function(key : "sat" | "sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "_id" , index : number) { if(key == '_id') return thisWeekSum.totalMembers = thisWeekSum.totalMembers + w[key].totalMembers thisWeekSum.totalActiveSubs = thisWeekSum.totalActiveSubs + w[key].totalActiveSubs thisWeekSum.totalUnActiveSubs = thisWeekSum.totalUnActiveSubs + w[key].totalUnActiveSubs thisWeekSum.totalMansMembers = thisWeekSum.totalMansMembers + w[key].totalMansMembers thisWeekSum.totalGirlsMembers = thisWeekSum.totalGirlsMembers + w[key].totalGirlsMembers }) }) // each week we return there sum data return { week: v.week, thisWeekSum: thisWeekSum } }) let labels : [] = []; thisMonthTotalSum.forEach(function(v , i) { labels.push(t('week')+ ' ' +thisMonthTotalSum[i]["week"]) }) // set the labels setLabels(labels) // we setup chart_series ( chart data ) let a : { name: string, data: { "totalMembers": number, "totalActiveSubs": number, "totalUnActiveSubs": number, "totalMansMembers": number, "totalGirlsMembers": number } }[] = ['totalMembers' , 'totalActiveSubs' , 'totalUnActiveSubs' , 'totalMansMembers' , 'totalGirlsMembers'].map((v : string , i : number) : { name: string, data: { "totalMembers": number, "totalActiveSubs": number, "totalUnActiveSubs": number, "totalMansMembers": number, "totalGirlsMembers": number } } => { let data = thisMonthTotalSum.map((v2 : { week: number, thisWeekSum: { "totalMembers": number, "totalActiveSubs": number, "totalUnActiveSubs": number, "totalMansMembers": number, "totalGirlsMembers": number } },i2 : number) => { let index : 'totalMembers' | 'totalActiveSubs' | 'totalUnActiveSubs' | 'totalMansMembers' | 'totalGirlsMembers' = v; return v2.thisWeekSum[index]; }) // return the line data return { name: t(v), data: data }; }) setChartSeries(a) } // if there was no data we use default return else { setChartSeries([ { name: '1'+t('week'), data: [0,0,0,0,0], }, { name: '2'+t('week'), data: [0,0,0,0,0], }, { name: '3'+t('week'), data: [0,0,0,0,0], }, { name: '4'+t('week'), data: [0,0,0,0,0], } ]) } } // if chart duration is set to this month else if(currentMembersGeneralOverviewDuration == 'thisYear') { // set the labels setLabels([t('1month'), t('2month'), t('3month'), t('4month'), t('5month'), t('6month'), t('7month'), t('8month'), t('9month'), t('10month'), t('11month')]) // check if there is current month report let thisYearTotalSum : { month: number, thisMonthWeeksSum: { "totalMembers": number, "totalActiveSubs": number, "totalUnActiveSubs": number, "totalMansMembers": number, "totalGirlsMembers": number } }[] if(report?.membersGeneralOverview?.value.thisYear) { // if we founded a data for the current month thisYearTotalSum = report?.membersGeneralOverview?.value.thisYear.months.map((v : any , i : number) : { month : number, thisMonthWeeksSum : { "totalMembers": number, "totalActiveSubs": number, "totalUnActiveSubs": number, "totalMansMembers": number, "totalGirlsMembers": number } } => { let summedWeeks = v.weeks.map((w : any , i : number) => { // we map through this month weeks let weekSum = w.days.map((d : { 'sat': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'sun': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'mon': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'tue': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'wed': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'thu': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, }, 'fri': { 'totalMembers': number, 'totalActiveSubs': number, 'totalUnActiveSubs': number, 'totalMansMembers': number, 'totalGirlsMembers': number, } } , i : number) => { // we init the this week sum let thisWeekSum = { "totalMembers": 0, "totalActiveSubs": 0, "totalUnActiveSubs": 0, "totalMansMembers": 0, "totalGirlsMembers": 0 } // we loop through week days and we sum there data Object.keys(d).forEach(function(key : "sat" | "sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "_id" , index : number) { if(key == '_id') return thisWeekSum.totalMembers = thisWeekSum.totalMembers + d[key].totalMembers thisWeekSum.totalActiveSubs = thisWeekSum.totalActiveSubs + d[key].totalActiveSubs thisWeekSum.totalUnActiveSubs = thisWeekSum.totalUnActiveSubs + d[key].totalUnActiveSubs thisWeekSum.totalMansMembers = thisWeekSum.totalMansMembers + d[key].totalMansMembers thisWeekSum.totalGirlsMembers = thisWeekSum.totalGirlsMembers + d[key].totalGirlsMembers }) // each week we return there sum data return thisWeekSum }) return { week: w.week, weekSum: weekSum } }) let thisMonthWeeksSum = { "totalMembers": 0, "totalActiveSubs": 0, "totalUnActiveSubs": 0, "totalMansMembers": 0, "totalGirlsMembers": 0 } summedWeeks.map((v : {week: number, weekSum: { "totalMembers": number, "totalActiveSubs": number, "totalUnActiveSubs": number, "totalMansMembers": number, "totalGirlsMembers": number }[]},i : number) => { thisMonthWeeksSum.totalMembers += v.weekSum[0].totalMembers thisMonthWeeksSum.totalActiveSubs += v.weekSum[0].totalActiveSubs thisMonthWeeksSum.totalUnActiveSubs += v.weekSum[0].totalUnActiveSubs thisMonthWeeksSum.totalMansMembers += v.weekSum[0].totalMansMembers thisMonthWeeksSum.totalGirlsMembers += v.weekSum[0].totalGirlsMembers }) return { month: v.month, thisMonthWeeksSum: thisMonthWeeksSum } }) // prepare the labels let labels : [] = []; thisYearTotalSum.forEach(function(v , i) { labels.push(t(thisYearTotalSum[i]["month"]+"month")) }) setLabels(labels) // we setup chart_series ( chart data ) let a : { name: string, data: { "totalMembers": number, "totalActiveSubs": number, "totalUnActiveSubs": number, "totalMansMembers": number, "totalGirlsMembers": number } }[] = ['totalMembers' , 'totalActiveSubs' , 'totalUnActiveSubs' , 'totalMansMembers' , 'totalGirlsMembers'].map((v : string , i : number) : { name: string, data: { "totalMembers": number, "totalActiveSubs": number, "totalUnActiveSubs": number, "totalMansMembers": number, "totalGirlsMembers": number } } => { let data = thisYearTotalSum.map((v2 : { month: number, thisMonthWeeksSum: { "totalMembers": number, "totalActiveSubs": number, "totalUnActiveSubs": number, "totalMansMembers": number, "totalGirlsMembers": number } },i2 : number) => { let index : 'totalMembers' | 'totalActiveSubs' | 'totalUnActiveSubs' | 'totalMansMembers' | 'totalGirlsMembers' = v; return v2.thisMonthWeeksSum[index]; }) // return the line data return { name: t(v), data: data }; }) setChartSeries(a) } // if there was no data we use default return else { setChartSeries([ { name: '1'+t('week'), data: [0,0,0,0,0], }, { name: '2'+t('week'), data: [0,0,0,0,0], }, { name: '3'+t('week'), data: [0,0,0,0,0], }, { name: '4'+t('week'), data: [0,0,0,0,0], } ]) } } } catch (error) { console.error('Error preparing chart data:', error); } finally { setIsLoading(false); } }, [report, currentMembersGeneralOverviewDuration, t]); // Chart options const chartOptions: ApexCharts.ApexOptions = { chart: { type: 'bar', height: 350, stacked: true, toolbar: { show: true, }, zoom: { enabled: true, }, foreColor: isDark ? '#fff' : '#333', fontFamily: isRtl ? 'Tajawal, sans-serif' : 'Inter, sans-serif', }, responsive: [ { breakpoint: 480, options: { legend: { position: 'bottom', offsetY: 10, }, }, }, ], plotOptions: { bar: { horizontal: false, borderRadius: 5, dataLabels: { total: { enabled: true, style: { fontSize: '13px', fontWeight: 900, }, }, }, }, }, xaxis: { type: 'category', categories: labels, labels: { style: { colors: isDark ? '#fff' : '#333', }, }, }, yaxis: { labels: { style: { colors: isDark ? '#fff' : '#333', }, }, }, legend: { position: 'right', offsetY: 40, labels: { colors: isDark ? '#fff' : '#333', }, }, fill: { opacity: 1, }, tooltip: { theme: isDark ? 'dark' : 'light', y: { formatter: function (val) { return val.toString(); }, }, }, }; if (isLoading || !report?.membersGeneralOverview) { return (
); } return (

{t('membersGeneralOverview')}

) }