Compare commits
2 Commits
df46525ccf
...
c8828e7e5f
| Author | SHA1 | Date | |
|---|---|---|---|
| c8828e7e5f | |||
| 489474e9d7 |
@ -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 currencySymbol = useAppSelector((state) => state.settingsReducer.value.appGeneralSettings.currencySymbol || '$');
|
const settings = useAppSelector((state) => state.settingsReducer.value);
|
||||||
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, don't render the chart
|
// if loading or no report or settings not loaded, show loading spinner
|
||||||
if (!report || !isClient) {
|
if (!report || !isClient || !settings?.appGeneralSettings) {
|
||||||
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,6 +36,9 @@ 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
|
||||||
|
|||||||
@ -2,6 +2,7 @@ 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,
|
||||||
});
|
});
|
||||||
@ -9,34 +10,56 @@ 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' ? true : false
|
const isRtl = locale === 'ar';
|
||||||
const isDark = themeType == 'dark' ? true : false
|
const isDark = themeType === 'dark';
|
||||||
// if loading show load screen
|
|
||||||
if(!report) return
|
// Set isClient to true after component mounts
|
||||||
// setup chart data
|
useEffect(() => {
|
||||||
let data = report?.servicesNameAndSubscribers.value.map((v : {
|
setIsClient(true);
|
||||||
_id: string,
|
}, []);
|
||||||
name: string,
|
|
||||||
totalSubscribers: number,
|
// if loading or no report, show loading spinner
|
||||||
} , i : number) => {
|
if (!report || !isClient) {
|
||||||
return v?.totalSubscribers;
|
return (
|
||||||
})
|
<div className="w-full h-[350px] flex items-center justify-center">
|
||||||
// setup chart labels
|
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-gray-900 dark:border-gray-100"></div>
|
||||||
let labels = report?.servicesNameAndSubscribers.value.map((v : {
|
</div>
|
||||||
_id: string,
|
);
|
||||||
name: string,
|
}
|
||||||
totalSubscribers: number,
|
|
||||||
} , i : number) => {
|
// setup chart data with null checks
|
||||||
return v?.name;
|
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 (
|
||||||
|
<div className="w-full h-[350px] flex items-center justify-center">
|
||||||
|
<p>{t('noDataAvailable')}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// setup chart options
|
// setup chart options
|
||||||
var options = {
|
const options = {
|
||||||
series: [{
|
series: [{
|
||||||
name: t('subscription'),
|
name: t('subscription'),
|
||||||
data: data
|
data: data
|
||||||
|
|||||||
@ -2,6 +2,7 @@ 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,
|
||||||
});
|
});
|
||||||
@ -9,34 +10,56 @@ 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' ? true : false
|
const isRtl = locale === 'ar';
|
||||||
const isDark = themeType == 'dark' ? true : false
|
const isDark = themeType === 'dark';
|
||||||
// if loading show load screen
|
|
||||||
if(!report) return
|
// Set isClient to true after component mounts
|
||||||
// prepare chart data
|
useEffect(() => {
|
||||||
let data = report?.workersNameAndJobType.value.map((v : {
|
setIsClient(true);
|
||||||
_id: string,
|
}, []);
|
||||||
jobType: string,
|
|
||||||
count: number,
|
// if loading or no report, show loading spinner
|
||||||
} , i : number) => {
|
if (!report || !isClient) {
|
||||||
return v?.count;
|
return (
|
||||||
})
|
<div className="w-full h-[350px] flex items-center justify-center">
|
||||||
// prepare chart labels
|
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-gray-900 dark:border-gray-100"></div>
|
||||||
let labels = report?.workersNameAndJobType.value.map((v : {
|
</div>
|
||||||
_id: string,
|
);
|
||||||
jobType: string,
|
}
|
||||||
count: number,
|
|
||||||
} , i : number) => {
|
// prepare chart data with null checks
|
||||||
return v?.jobType;
|
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 (
|
||||||
|
<div className="w-full h-[350px] flex items-center justify-center">
|
||||||
|
<p>{t('noDataAvailable')}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// prepare chart options
|
// prepare chart options
|
||||||
var options = {
|
const options = {
|
||||||
series: [{
|
series: [{
|
||||||
name: t('worker'),
|
name: t('worker'),
|
||||||
data: data
|
data: data
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user