Add ss 00

This commit is contained in:
yznahmad 2025-06-23 14:35:41 +03:00
parent 8d60c5ab9c
commit 8d1c19e5b0

View File

@ -3,17 +3,12 @@ import { useAppSelector } from '@/redux/store';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import Cookies from 'universal-cookie'; import Cookies from 'universal-cookie';
const ReactApexChart = dynamic(() => import('react-apexcharts'), {
ssr: false,
});
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { AppDispatch } from '@/redux/store'; import { AppDispatch } from '@/redux/store';
import { setCurrentMembersGeneralOverviewDuration } from '@/redux/features/statistics-slice' import { setCurrentMembersGeneralOverviewDuration } from '@/redux/features/statistics-slice'
import { Loader2 } from 'lucide-react';
const ReactApexChart = dynamic(() => import('react-apexcharts'), {
ssr: false,
loading: () => <div className="flex items-center justify-center h-full">
<Loader2 className="w-8 h-8 animate-spin" />
</div>
});
export default function MembersOverviewChart() export default function MembersOverviewChart()
{ {
@ -21,7 +16,6 @@ export default function MembersOverviewChart()
const report = useAppSelector((state) => state.statisticsReducer.value.report) const report = useAppSelector((state) => state.statisticsReducer.value.report)
const currentMembersGeneralOverviewDuration = useAppSelector((state) => state.statisticsReducer.value.currentMembersGeneralOverviewDuration) const currentMembersGeneralOverviewDuration = useAppSelector((state) => state.statisticsReducer.value.currentMembersGeneralOverviewDuration)
const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType) const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType)
// declare global variables // declare global variables
const dispatch = useDispatch<AppDispatch>() const dispatch = useDispatch<AppDispatch>()
const cookies = new Cookies(); const cookies = new Cookies();
@ -29,63 +23,95 @@ export default function MembersOverviewChart()
const locale = cookies.get("NEXT_LOCALE") const locale = cookies.get("NEXT_LOCALE")
const isRtl = locale == 'ar' ? true : false const isRtl = locale == 'ar' ? true : false
const isDark = themeType == 'dark' ? true : false const isDark = themeType == 'dark' ? true : false
const [chartSeries, setChartSeries] = useState<{ name: string; data: number[] }[]>([]); const [chartSeries , setChartSeries] = useState<{}[]>([]);
const [labels, setLabels] = useState<string[]>([]) const [labels , setLabels] = useState<string[]>([])
const [isLoading, setIsLoading] = useState(true);
// revenue Chart // revenue Chart
// prepare chart series and handle the transaction between currentMembersGeneralOverviewDuration // prepare chart series and handle the transaction between currentMembersGeneralOverviewDuration
useEffect(() => { useEffect(() => {
if (!report?.membersGeneralOverview) {
setIsLoading(true);
return;
}
setIsLoading(true);
try {
// if chart duration is set to this week // if chart duration is set to this week
if (currentMembersGeneralOverviewDuration == 'thisWeek') { if(currentMembersGeneralOverviewDuration == 'thisWeek')
{
// set the labels // set the labels
setLabels([t('sat'), t('sun'), t('mon'), t('tue'), t('wed'), t('thu'), t('fri')]) setLabels([t('sat') , t('sun') , t('mon') , t('tue') , t('wed') , t('thu') , t('fri')])
// init this weekdata
// Initialize default data structure let data_thisWeek = {
const defaultWeekData = { 'sat': {
sat: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 }, 'totalMembers': 0,
sun: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 }, 'totalActiveSubs': 0,
mon: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 }, 'totalUnActiveSubs': 0,
tue: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 }, 'totalMansMembers': 0,
wed: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 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 } 'sun': {
}; 'totalMembers': 0,
'totalActiveSubs': 0,
// Use data from report if available, otherwise use default data 'totalUnActiveSubs': 0,
const weekData = report?.membersGeneralOverview?.value?.thisWeek?.days || defaultWeekData; '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 // prepare the chart series
setChartSeries([ setChartSeries([
{ {
name: t('totalMembers'), name: t('totalMembers'),
data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalMembers || 0), 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'), name: t('totalActiveSubs'),
data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalActiveSubs || 0), 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'), name: t('totalUnActiveSubs'),
data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalUnActiveSubs || 0), 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'), name: t('totalMansMembers'),
data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalMansMembers || 0), 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'), name: t('totalGirlsMembers'),
data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalGirlsMembers || 0), 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 chart duration is set to this month // if chart duration is set to this month
else if(currentMembersGeneralOverviewDuration == 'thisMonth') else if(currentMembersGeneralOverviewDuration == 'thisMonth')
@ -104,7 +130,7 @@ export default function MembersOverviewChart()
{ {
// if we founded a data for the current month // if we founded a data for the current month
thisMonthTotalSum = report?.membersGeneralOverview?.value.thisMonth.weeks.map((v : any , i : number) : { thisMonthTotalSum = report?.membersGeneralOverview?.value.thisMonth.weeks.map((v : any , i : number) : {
week: number, week : number,
thisWeekSum : { thisWeekSum : {
"totalMembers": number, "totalMembers": number,
"totalActiveSubs": number, "totalActiveSubs": number,
@ -462,137 +488,200 @@ export default function MembersOverviewChart()
]) ])
} }
} }
}, [currentMembersGeneralOverviewDuration])
} catch (error) { // prepare the chart options
console.error('Error preparing chart data:', error); const options : any = {
} finally { series: chartSeries,
setIsLoading(false); options: {
}
}, [report, currentMembersGeneralOverviewDuration, t]);
// Chart options
const chartOptions: ApexCharts.ApexOptions = {
chart: { chart: {
type: 'bar', height: 325,
height: 350, type: 'area',
stacked: true, fontFamily: 'Nunito, sans-serif',
zoom: {
enabled: false,
},
toolbar: { 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, 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: { labels: {
offsetX: isRtl ? 2 : 0,
offsetY: 5,
style: { style: {
colors: isDark ? '#fff' : '#333', colors: isDark ? '#fff' : '#000',
fontSize: '12px',
cssClass: 'apexcharts-xaxis-title',
}, },
}, },
}, },
yaxis: { yaxis: {
tickAmount: 7,
labels: { labels: {
style: { formatter: (value: number) => {
colors: isDark ? '#fff' : '#333', 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: { legend: {
position: 'right', position: 'top',
offsetY: 40, horizontalAlign: 'right',
labels: { fontSize: '16px',
colors: isDark ? '#fff' : '#333', markers: {
width: 10,
height: 10,
offsetX: isRtl ? 5 : -5,
}, },
itemMargin: {
horizontal: 10,
vertical: 5,
}, },
fill: {
opacity: 1,
}, },
tooltip: { tooltip: {
theme: isDark ? 'dark' : 'light', theme: isDark ? 'dark' : 'light',
y: { x: {
formatter: function (val) { show: true,
return val.toString();
}, },
}, },
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,
},
},
}
}],
}, },
}; };
// return the ui
if (isLoading || !report?.membersGeneralOverview) {
return ( return (
<div className="w-full h-full flex items-center justify-center min-h-[400px]"> <>
<Loader2 className="w-8 h-8 animate-spin" /> <div className="flex flex-col gap-5 [&_*]:dark:!text-text-dark p-5 lg:w-2/3 w-full shadow border border-secondary-light bg-primary dark:bg-primary-dark rounded-[5px]">
</div> <h3 className="text-xl font-bold">{t('membersGeneralOverview')}</h3>
); <div className="w-full flex gap-3 justify-end">
} <button disabled={currentMembersGeneralOverviewDuration == 'thisWeek'} onClick={() => {
dispatch(setCurrentMembersGeneralOverviewDuration('thisWeek'))
}} className="disabled:dark:opacity-[0.5] disabled:opacity-[0.5]">
return (
<div className="w-full h-full">
<div className="flex flex-col">
<div className="flex justify-between items-center mb-4">
<h3 className="text-lg font-semibold">{t('membersGeneralOverview')}</h3>
<div className="flex gap-2">
<button
onClick={() => dispatch(setCurrentMembersGeneralOverviewDuration('thisWeek'))}
className={`px-3 py-1 rounded-md text-sm ${currentMembersGeneralOverviewDuration === 'thisWeek' ? 'bg-primary text-white' : 'bg-gray-200 dark:bg-gray-700'}`}
>
{t('thisWeek')} {t('thisWeek')}
</button> </button>
<button <button disabled={currentMembersGeneralOverviewDuration == 'thisMonth'} onClick={() => {
onClick={() => dispatch(setCurrentMembersGeneralOverviewDuration('thisMonth'))} dispatch(setCurrentMembersGeneralOverviewDuration('thisMonth'))
className={`px-3 py-1 rounded-md text-sm ${currentMembersGeneralOverviewDuration === 'thisMonth' ? 'bg-primary text-white' : 'bg-gray-200 dark:bg-gray-700'}`} }} className="disabled:dark:opacity-[0.5] disabled:opacity-[0.5]">
>
{t('thisMonth')} {t('thisMonth')}
</button> </button>
<button <button disabled={currentMembersGeneralOverviewDuration == 'thisYear'} onClick={() => {
onClick={() => dispatch(setCurrentMembersGeneralOverviewDuration('thisYear'))} dispatch(setCurrentMembersGeneralOverviewDuration('thisYear'))
className={`px-3 py-1 rounded-md text-sm ${currentMembersGeneralOverviewDuration === 'thisYear' ? 'bg-primary text-white' : 'bg-gray-200 dark:bg-gray-700'}`} }} className="disabled:dark:opacity-[0.5] disabled:opacity-[0.5]">
>
{t('thisYear')} {t('thisYear')}
</button> </button>
</div> </div>
<ReactApexChart series={options.series} options={options.options} type="area" height={350} width={'100%'} />
</div> </div>
</>
<div className="w-full h-[400px] mt-4">
<ReactApexChart
options={chartOptions}
series={chartSeries}
type="bar"
height="100%"
/>
</div>
</div>
</div>
) )
} }