diff --git a/webapp/src/components/dashboard/home/servicesSubscriptions.tsx b/webapp/src/components/dashboard/home/servicesSubscriptions.tsx
index 41f9eeb..b4b3dac 100644
--- a/webapp/src/components/dashboard/home/servicesSubscriptions.tsx
+++ b/webapp/src/components/dashboard/home/servicesSubscriptions.tsx
@@ -2,6 +2,7 @@ import { useAppSelector } from '@/redux/store';
import { useTranslations } from 'next-intl';
import dynamic from 'next/dynamic';
import Cookies from 'universal-cookie';
+import { useState, useEffect } from 'react';
const ReactApexChart = dynamic(() => import('react-apexcharts'), {
ssr: false,
});
@@ -9,34 +10,56 @@ const ReactApexChart = dynamic(() => import('react-apexcharts'), {
export default function ServicesSubscriptions()
{
// get redux needed state
- const report = useAppSelector((state) => state.statisticsReducer.value.report)
- const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType)
+ const report = useAppSelector((state) => state.statisticsReducer.value.report);
+ const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType);
+ const [isClient, setIsClient] = useState(false);
+
// declare global variables
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
- // if loading show load screen
- if(!report) return
- // setup chart data
- let data = report?.servicesNameAndSubscribers.value.map((v : {
- _id: string,
- name: string,
- totalSubscribers: number,
- } , i : number) => {
- return v?.totalSubscribers;
- })
- // setup chart labels
- let labels = report?.servicesNameAndSubscribers.value.map((v : {
- _id: string,
- name: string,
- totalSubscribers: number,
- } , i : number) => {
- return v?.name;
- })
+ const locale = cookies.get("NEXT_LOCALE");
+ const isRtl = locale === 'ar';
+ const isDark = themeType === 'dark';
+
+ // Set isClient to true after component mounts
+ useEffect(() => {
+ setIsClient(true);
+ }, []);
+
+ // if loading or no report, show loading spinner
+ if (!report || !isClient) {
+ return (
+
+ );
+ }
+
+ // setup chart data with null checks
+ const data = report?.servicesNameAndSubscribers?.value?.map((v: {
+ _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 (
+
+
{t('noDataAvailable')}
+
+ );
+ }
+
// setup chart options
- var options = {
+ const options = {
series: [{
name: t('subscription'),
data: data
diff --git a/webapp/src/components/dashboard/home/workersJobTypes.tsx b/webapp/src/components/dashboard/home/workersJobTypes.tsx
index e810a8d..e1710b1 100644
--- a/webapp/src/components/dashboard/home/workersJobTypes.tsx
+++ b/webapp/src/components/dashboard/home/workersJobTypes.tsx
@@ -2,6 +2,7 @@ import { useAppSelector } from '@/redux/store';
import { useTranslations } from 'next-intl';
import dynamic from 'next/dynamic';
import Cookies from 'universal-cookie';
+import { useState, useEffect } from 'react';
const ReactApexChart = dynamic(() => import('react-apexcharts'), {
ssr: false,
});
@@ -9,34 +10,56 @@ const ReactApexChart = dynamic(() => import('react-apexcharts'), {
export default function WorkersJobTypes()
{
// get needed redux state
- const report = useAppSelector((state) => state.statisticsReducer.value.report)
- const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType)
+ const report = useAppSelector((state) => state.statisticsReducer.value.report);
+ const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType);
+ const [isClient, setIsClient] = useState(false);
+
// declare global variables
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
- // if loading show load screen
- if(!report) return
- // prepare chart data
- let data = report?.workersNameAndJobType.value.map((v : {
- _id: string,
- jobType: string,
- count: number,
- } , i : number) => {
- return v?.count;
- })
- // prepare chart labels
- let labels = report?.workersNameAndJobType.value.map((v : {
- _id: string,
- jobType: string,
- count: number,
- } , i : number) => {
- return v?.jobType;
- })
+ const locale = cookies.get("NEXT_LOCALE");
+ const isRtl = locale === 'ar';
+ const isDark = themeType === 'dark';
+
+ // Set isClient to true after component mounts
+ useEffect(() => {
+ setIsClient(true);
+ }, []);
+
+ // if loading or no report, show loading spinner
+ if (!report || !isClient) {
+ return (
+
+ );
+ }
+
+ // prepare chart data with null checks
+ const data = report?.workersNameAndJobType?.value?.map((v: {
+ _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 (
+
+
{t('noDataAvailable')}
+
+ );
+ }
+
// prepare chart options
- var options = {
+ const options = {
series: [{
name: t('worker'),
data: data