Compare commits

..

No commits in common. "c8828e7e5f14bd5e2da53a3b514a5b9a74c3e2c6" and "df46525ccf9f2c4b1690aff54d4c254be8b144ae" have entirely different histories.

3 changed files with 51 additions and 100 deletions

View File

@ -11,7 +11,7 @@ export default function IncomeOutcome()
{ {
// get needed redux state // get needed redux state
const report = useAppSelector((state) => state.statisticsReducer.value.report); const report = useAppSelector((state) => state.statisticsReducer.value.report);
const settings = useAppSelector((state) => state.settingsReducer.value); const currencySymbol = useAppSelector((state) => state.settingsReducer.value.appGeneralSettings.currencySymbol || '$');
const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType); const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType);
const [isClient, setIsClient] = useState(false); const [isClient, setIsClient] = useState(false);
@ -27,8 +27,8 @@ export default function IncomeOutcome()
setIsClient(true); setIsClient(true);
}, []); }, []);
// if loading or no report or settings not loaded, show loading spinner // if loading or no report, don't render the chart
if (!report || !isClient || !settings?.appGeneralSettings) { if (!report || !isClient) {
return ( return (
<div className="w-full h-[350px] flex items-center justify-center"> <div className="w-full h-[350px] flex items-center justify-center">
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-gray-900 dark:border-gray-100"></div> <div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-gray-900 dark:border-gray-100"></div>
@ -36,9 +36,6 @@ export default function IncomeOutcome()
); );
} }
// Get currency symbol with fallback to '$' if not available
const currencySymbol = settings.appGeneralSettings.currencySymbol || '$';
// prepare chart data // prepare chart data
const data = [report?.totalIncome || 0, report?.totalOutcome || 0]; const data = [report?.totalIncome || 0, report?.totalOutcome || 0];
// prepare chart labels // prepare chart labels

View File

@ -2,7 +2,6 @@ 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';
import { useState, useEffect } from 'react';
const ReactApexChart = dynamic(() => import('react-apexcharts'), { const ReactApexChart = dynamic(() => import('react-apexcharts'), {
ssr: false, ssr: false,
}); });
@ -10,56 +9,34 @@ const ReactApexChart = dynamic(() => import('react-apexcharts'), {
export default function ServicesSubscriptions() export default function ServicesSubscriptions()
{ {
// get redux needed state // get redux needed state
const report = useAppSelector((state) => state.statisticsReducer.value.report); const report = useAppSelector((state) => state.statisticsReducer.value.report)
const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType); const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType)
const [isClient, setIsClient] = useState(false);
// declare global variables // declare global variables
const cookies = new Cookies(); const cookies = new Cookies();
const t = useTranslations('statistics'); const t = useTranslations('statistics');
const locale = cookies.get("NEXT_LOCALE"); const locale = cookies.get("NEXT_LOCALE")
const isRtl = locale === 'ar'; const isRtl = locale == 'ar' ? true : false
const isDark = themeType === 'dark'; const isDark = themeType == 'dark' ? true : false
// if loading show load screen
// Set isClient to true after component mounts if(!report) return
useEffect(() => { // setup chart data
setIsClient(true); let data = report?.servicesNameAndSubscribers.value.map((v : {
}, []); _id: string,
name: string,
// if loading or no report, show loading spinner totalSubscribers: number,
if (!report || !isClient) { } , i : number) => {
return ( return v?.totalSubscribers;
<div className="w-full h-[350px] flex items-center justify-center"> })
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-gray-900 dark:border-gray-100"></div> // setup chart labels
</div> let labels = report?.servicesNameAndSubscribers.value.map((v : {
); _id: string,
} name: string,
totalSubscribers: number,
// setup chart data with null checks } , i : number) => {
const data = report?.servicesNameAndSubscribers?.value?.map((v: { return v?.name;
_id: string; })
name: string;
totalSubscribers: number;
}) => v?.totalSubscribers) || [];
// setup chart labels with null checks
const labels = report?.servicesNameAndSubscribers?.value?.map((v: {
_id: string;
name: string;
totalSubscribers: number;
}) => v?.name) || [];
// Return empty state if no data
if (data.length === 0 || labels.length === 0) {
return (
<div className="w-full h-[350px] flex items-center justify-center">
<p>{t('noDataAvailable')}</p>
</div>
);
}
// setup chart options // setup chart options
const options = { var options = {
series: [{ series: [{
name: t('subscription'), name: t('subscription'),
data: data data: data

View File

@ -2,7 +2,6 @@ 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';
import { useState, useEffect } from 'react';
const ReactApexChart = dynamic(() => import('react-apexcharts'), { const ReactApexChart = dynamic(() => import('react-apexcharts'), {
ssr: false, ssr: false,
}); });
@ -10,56 +9,34 @@ const ReactApexChart = dynamic(() => import('react-apexcharts'), {
export default function WorkersJobTypes() export default function WorkersJobTypes()
{ {
// get needed redux state // get needed redux state
const report = useAppSelector((state) => state.statisticsReducer.value.report); const report = useAppSelector((state) => state.statisticsReducer.value.report)
const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType); const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType)
const [isClient, setIsClient] = useState(false);
// declare global variables // declare global variables
const cookies = new Cookies(); const cookies = new Cookies();
const t = useTranslations('statistics'); const t = useTranslations('statistics');
const locale = cookies.get("NEXT_LOCALE"); const locale = cookies.get("NEXT_LOCALE")
const isRtl = locale === 'ar'; const isRtl = locale == 'ar' ? true : false
const isDark = themeType === 'dark'; const isDark = themeType == 'dark' ? true : false
// if loading show load screen
// Set isClient to true after component mounts if(!report) return
useEffect(() => { // prepare chart data
setIsClient(true); let data = report?.workersNameAndJobType.value.map((v : {
}, []); _id: string,
jobType: string,
// if loading or no report, show loading spinner count: number,
if (!report || !isClient) { } , i : number) => {
return ( return v?.count;
<div className="w-full h-[350px] flex items-center justify-center"> })
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-gray-900 dark:border-gray-100"></div> // prepare chart labels
</div> let labels = report?.workersNameAndJobType.value.map((v : {
); _id: string,
} jobType: string,
count: number,
// prepare chart data with null checks } , i : number) => {
const data = report?.workersNameAndJobType?.value?.map((v: { return v?.jobType;
_id: string; })
jobType: string;
count: number;
}) => v?.count) || [];
// prepare chart labels with null checks
const labels = report?.workersNameAndJobType?.value?.map((v: {
_id: string;
jobType: string;
count: number;
}) => v?.jobType) || [];
// Return empty state if no data
if (data.length === 0 || labels.length === 0) {
return (
<div className="w-full h-[350px] flex items-center justify-center">
<p>{t('noDataAvailable')}</p>
</div>
);
}
// prepare chart options // prepare chart options
const options = { var options = {
series: [{ series: [{
name: t('worker'), name: t('worker'),
data: data data: data