diff --git a/webapp/src/components/dashboard/home/generalLook.tsx b/webapp/src/components/dashboard/home/generalLook.tsx index ed519cd..7869f56 100644 --- a/webapp/src/components/dashboard/home/generalLook.tsx +++ b/webapp/src/components/dashboard/home/generalLook.tsx @@ -7,116 +7,90 @@ export default function GeneralLook() const t = useTranslations('statistics'); const report = useAppSelector((state) => state.statisticsReducer.value.report) - return ( - <> + if (!report) { + return (
-
-
- - - - - - -

{report?.membersCount.value}

-

{t('totalMembers')}

-
-
-
- - - - - - -

{report?.activeMembersCount.value}

-

{t('totalActiveMembers')}

-
-
-
- - - - - - -

{report?.disActiveMembersCount.value}

-

{t('totalUnActiveMembers')}

-
-
-
-
-
- - - - - - -

{report?.servicesCount.value}

-

{t('totalServices')}

-
-
-
- - - - - - -

{report?.activeServicesCount.value}

-

{t('totalActiveServices')}

-
-
-
- - - - - - -

{report?.disActiveServicesCount.value}

-

{t('totalUnActiveServices')}

-
-
-
-
-
- - - - - - -

{report?.activeSubscriptionsCount.value}

-

{t('totalActiveSubscriptions')}

-
-
-
- - - - - - - -

{report?.expiredSoonSubscriptionsCount.value}

-

{t('expiredSoonSubscriptionsCount')}

-
-
-
- - - - - - -

{report?.expiredSubscriptionsCount.value}

-

{t('totalExpiredSubscriptions')}

-
-
+
+
- + ); + } + + const stats = [ + { + icon: 'members', + value: report?.membersCount?.value ?? 0, + label: t('totalMembers'), + bgColor: 'bg-info' + }, + { + icon: 'activeMembers', + value: report?.activeMembersCount?.value ?? 0, + label: t('totalActiveMembers'), + bgColor: 'bg-success' + }, + { + icon: 'disActiveMembers', + value: report?.disActiveMembersCount?.value ?? 0, + label: t('totalUnActiveMembers'), + bgColor: 'bg-error' + }, + { + icon: 'services', + value: report?.servicesCount?.value ?? 0, + label: t('totalServices'), + bgColor: 'bg-info' + }, + { + icon: 'activeServices', + value: report?.activeServicesCount?.value ?? 0, + label: t('totalActiveServices'), + bgColor: 'bg-success' + }, + { + icon: 'disActiveServices', + value: report?.disActiveServicesCount?.value ?? 0, + label: t('totalUnActiveServices'), + bgColor: 'bg-error' + }, + { + icon: 'activeSubscriptions', + value: report?.activeSubscriptionsCount?.value ?? 0, + label: t('totalActiveSubscriptions'), + bgColor: 'bg-info' + }, + { + icon: 'expiredSoonSubscriptions', + value: report?.expiredSoonSubscriptionsCount?.value ?? 0, + label: t('expiredSoonSubscriptionsCount'), + bgColor: 'bg-warning' + }, + { + icon: 'expiredSubscriptions', + value: report?.expiredSubscriptionsCount?.value ?? 0, + label: t('totalExpiredSubscriptions'), + bgColor: 'bg-error' + } + ]; + + return ( +
+ {stats.map((stat, index) => ( +
+
+ + + + + + +

{stat.value}

+

{stat.label}

+
+
+
+ ))} +
) } \ No newline at end of file diff --git a/webapp/src/components/dashboard/home/membersOverviewChart.tsx b/webapp/src/components/dashboard/home/membersOverviewChart.tsx index ed9b358..d0ef347 100644 --- a/webapp/src/components/dashboard/home/membersOverviewChart.tsx +++ b/webapp/src/components/dashboard/home/membersOverviewChart.tsx @@ -3,12 +3,17 @@ import { useAppSelector } from '@/redux/store'; import { useTranslations } from 'next-intl'; import dynamic from 'next/dynamic'; import Cookies from 'universal-cookie'; -const ReactApexChart = dynamic(() => import('react-apexcharts'), { - ssr: false, -}); 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() { @@ -16,6 +21,7 @@ export default function MembersOverviewChart() 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(); @@ -23,113 +29,68 @@ export default function MembersOverviewChart() const locale = cookies.get("NEXT_LOCALE") const isRtl = locale == 'ar' ? true : false const isDark = themeType == 'dark' ? true : false - const [chartSeries , setChartSeries] = useState<{}[]>([]); - const [labels , setLabels] = useState([]) + 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 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')]) - // init this weekdata - let data_thisWeek = { - '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, - } - } - // if there is a data from the backend we overwrite the currentData - if(report?.membersGeneralOverview?.value.thisWeek.days) { - data_thisWeek = report?.membersGeneralOverview?.value.thisWeek.days; - } - // prepare the chart series - setChartSeries([ - { - name: t('totalMembers'), - data: [data_thisWeek['sat']['totalMembers'], data_thisWeek['sun']['totalMembers'], data_thisWeek['mon']['totalMembers'], data_thisWeek['tue']['totalMembers'], data_thisWeek['wed']['totalMembers'], data_thisWeek['thu']['totalMembers'], data_thisWeek['fri']['totalMembers']], - }, - { - name: t('totalActiveSubs'), - data: [data_thisWeek['sat']['totalActiveSubs'], data_thisWeek['sun']['totalActiveSubs'], data_thisWeek['mon']['totalActiveSubs'], data_thisWeek['tue']['totalActiveSubs'], data_thisWeek['wed']['totalActiveSubs'], data_thisWeek['thu']['totalActiveSubs'], data_thisWeek['fri']['totalActiveSubs']], - }, - { - name: t('totalUnActiveSubs'), - data: [data_thisWeek['sat']['totalUnActiveSubs'], data_thisWeek['sun']['totalUnActiveSubs'], data_thisWeek['mon']['totalUnActiveSubs'], data_thisWeek['tue']['totalUnActiveSubs'], data_thisWeek['wed']['totalUnActiveSubs'], data_thisWeek['thu']['totalUnActiveSubs'], data_thisWeek['fri']['totalUnActiveSubs']], - }, - { - name: t('totalMansMembers'), - data: [data_thisWeek['sat']['totalMansMembers'], data_thisWeek['sun']['totalMansMembers'], data_thisWeek['mon']['totalMansMembers'], data_thisWeek['tue']['totalMansMembers'], data_thisWeek['wed']['totalMansMembers'], data_thisWeek['thu']['totalMansMembers'], data_thisWeek['fri']['totalMansMembers']], - }, - { - name: t('totalGirlsMembers'), - data: [data_thisWeek['sat']['totalGirlsMembers'], data_thisWeek['sun']['totalGirlsMembers'], data_thisWeek['mon']['totalGirlsMembers'], data_thisWeek['tue']['totalGirlsMembers'], data_thisWeek['wed']['totalGirlsMembers'], data_thisWeek['thu']['totalGirlsMembers'], data_thisWeek['fri']['totalGirlsMembers']], - }, - ]) + if (!report?.membersGeneralOverview) { + setIsLoading(true); + return; } - // 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) + + 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') { - // if we founded a data for the current month - thisMonthTotalSum = report?.membersGeneralOverview?.value.thisMonth.weeks.map((v : any , i : number) : { + let thisMonthTotalSum : { week : number, thisWeekSum : { "totalMembers": number, @@ -138,184 +99,30 @@ export default function MembersOverviewChart() "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 : { + }[]; + 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: { + 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 init the this week sum + let thisWeekSum = { + "totalMembers": 0, + "totalActiveSubs": 0, + "totalUnActiveSubs": 0, + "totalMansMembers": 0, + "totalGirlsMembers": 0 + } // we map through this month weeks - let weekSum = w.days.map((d : { + v.days.map((w : { 'sat': { 'totalMembers': number, 'totalActiveSubs': number, @@ -366,352 +173,426 @@ export default function MembersOverviewChart() '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) { + Object.keys(w).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 + 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 thisWeekSum }) + // each week we return there sum data return { - week: w.week, - weekSum: weekSum + week: v.week, + thisWeekSum: thisWeekSum } }) - - 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 + let labels : [] = []; + thisMonthTotalSum.forEach(function(v , i) { + labels.push(t('week')+ ' ' +thisMonthTotalSum[i]["week"]) }) - - 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: { + // 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 } - },i2 : number) => { - let index : 'totalMembers' | 'totalActiveSubs' | 'totalUnActiveSubs' | 'totalMansMembers' | 'totalGirlsMembers' = v; - return v2.thisMonthWeeksSum[index]; + }[] = ['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 + }; }) - // 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], - } - ]) - } - } - }, [currentMembersGeneralOverviewDuration]) - // prepare the chart options - const options : any = { - series: chartSeries, - options: { - chart: { - height: 325, - type: 'area', - fontFamily: 'Nunito, sans-serif', - zoom: { - enabled: false, - }, - toolbar: { - show: false, - }, - }, - data_thisWeekLabels: { - enabled: false, - }, - stroke: { - show: true, - curve: 'smooth', - width: 2, - lineCap: 'square', - }, - dropShadow: { - enabled: true, - opacity: 0.2, - blur: 10, - left: -7, - top: 22, - }, - colors: ['#38C172', '#38C172' , '#E3342F' , '#0263FF', '#FF30F7'], - markers: { - //discrete: [ - // { - // seriesIndex: 0, - // data_thisWeekPointIndex: 1, - // fillColor: '#38C172', - // strokeColor: 'transparent', - // size: 7, - // }, - // { - // seriesIndex: 1, - // data_thisWeekPointIndex: 1, - // fillColor: '#E3342F', - // strokeColor: 'transparent', - // size: 7, - // }, - //], - }, - labels: labels, - xaxis: { - axisBorder: { - show: false, - }, - axisTicks: { - show: false, - }, - crosshairs: { - show: true, - }, - labels: { - offsetX: isRtl ? 2 : 0, - offsetY: 5, - style: { - colors: isDark ? '#fff' : '#000', - fontSize: '12px', - cssClass: 'apexcharts-xaxis-title', - }, - }, - }, - yaxis: { - tickAmount: 7, - labels: { - formatter: (value: number) => { - if(value > 1000) - { - return parseInt(value.toFixed(0)) + t('k') - } - else { - return parseInt(value.toFixed(0)) - } - }, - offsetX: isRtl ? -30 : -10, - offsetY: 0, - style: { - colors: isDark ? '#fff' : '#000', - fontSize: '12px', - cssClass: 'apexcharts-yaxis-title', - }, - }, - }, - grid: { - borderColor: isDark ? '#191E3A' : '#E0E6ED', - strokeDashArray: 5, - xaxis: { - lines: { - show: false, - }, - }, - yaxis: { - lines: { - show: true, - }, - }, - padding: { - top: 0, - right: 0, - bottom: 0, - left: 0, - }, - }, - legend: { - position: 'top', - horizontalAlign: 'right', - fontSize: '16px', - markers: { - width: 10, - height: 10, - offsetX: isRtl ? 5 : -5, - }, - itemMargin: { - horizontal: 10, - vertical: 5, - }, - }, - tooltip: { - theme: isDark ? 'dark' : 'light', - x: { - show: true, - }, - }, - fill: { - type: 'gradient', - gradient: { - shadeIntensity: 1, - inverseColors: !1, - opacityFrom: isDark ? 0.19 : 0.28, - opacityTo: 0.05, - stops: isDark ? [100, 100] : [45, 100], - }, - }, - responsive: [{ - breakpoint: 420, - options: { - yaxis: { - show: false, - showAlways: false, - }, - legend: { - offsetY: 10, - height: 60, - position: 'bottom', - horizontalAlign: 'center', - fontSize: '12px', - markers: { - width: 10, - height: 10, - offsetX: isRtl ? 5 : -5, - }, - itemMargin: { - horizontal: 10, - vertical: 5, - }, - }, + 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(); + }, + }, }, }; - // return the ui - return ( - <> -
-

{t('membersGeneralOverview')}

-
- - - -
- {!chartSeries || chartSeries.length === 0 ? ( -
-
-
- ) : ( - - )} + + + if (isLoading || !report?.membersGeneralOverview) { + return ( +
+
- + ); + } + + + return ( +
+
+
+

{t('membersGeneralOverview')}

+
+ + + +
+
+ +
+ +
+
+
) } \ No newline at end of file