diff --git a/webapp/src/components/dashboard/home/incomeOutcome.tsx b/webapp/src/components/dashboard/home/incomeOutcome.tsx
index 05c86f0..c5fcd9b 100644
--- a/webapp/src/components/dashboard/home/incomeOutcome.tsx
+++ b/webapp/src/components/dashboard/home/incomeOutcome.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 { useEffect, useState } from 'react';
const ReactApexChart = dynamic(() => import('react-apexcharts'), {
ssr: false,
});
@@ -9,44 +10,63 @@ const ReactApexChart = dynamic(() => import('react-apexcharts'), {
export default function IncomeOutcome()
{
// get needed redux state
- const report = useAppSelector((state) => state.statisticsReducer.value.report)
- const currencySymbol = useAppSelector((state) => state.settingsReducer.value.appGeneralSettings.currencySymbol)
- const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType)
+ const report = useAppSelector((state) => state.statisticsReducer.value.report);
+ const currencySymbol = useAppSelector((state) => state.settingsReducer.value.appGeneralSettings.currencySymbol || '$');
+ 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
+ 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, don't render the chart
+ if (!report || !isClient) {
+ return (
+
+ );
+ }
+
// prepare chart data
- let data = [report?.totalIncome , report?.totalOutcome]
+ const data = [report?.totalIncome || 0, report?.totalOutcome || 0];
// prepare chart labels
- let labels = [t('income') , t('outcome')]
+ const labels = [t('income'), t('outcome')];
+
// prepare chart options
- var options = {
- series: [{
+ const options = {
+ series: [{
name: currencySymbol,
data: data
}],
- annotations: {
+ annotations: {
points: [{
- x: t('incomes'),
- seriesIndex: 0,
- label: {
- borderColor: '#775DD0',
- offsetY: 0,
- style: {
- color: '#fff',
- background: '#775DD0',
- },
- }
+ x: t('incomes'),
+ seriesIndex: 0,
+ label: {
+ borderColor: '#775DD0',
+ offsetY: 0,
+ style: {
+ color: '#fff',
+ background: '#775DD0',
+ },
+ }
}]
},
chart: {
height: 350,
type: 'bar',
+ toolbar: {
+ show: false
+ }
},
plotOptions: {
bar: {
@@ -69,6 +89,7 @@ export default function IncomeOutcome()
horizontal: 10,
vertical: 5,
},
+ show: false
},
fill: {
type: isDark ? '' : 'gradient',
@@ -80,7 +101,7 @@ export default function IncomeOutcome()
stops: isDark ? [100, 100] : [45, 100],
},
},
- colors: ['#0263FF' , '#E3342F'],
+ colors: ['#0263FF', '#E3342F'],
dataLabels: {
enabled: false
},
@@ -90,7 +111,7 @@ export default function IncomeOutcome()
},
grid: {
row: {
- colors: [isDark ? '#333' : '#fff', '#f2f2f2'] // Adjust the grid row color for dark mode
+ colors: [isDark ? '#333' : '#fff', '#f2f2f2']
},
},
xaxis: {
@@ -100,39 +121,68 @@ export default function IncomeOutcome()
offsetY: 5,
style: {
colors: isDark ? '#fff' : '#000',
- fontSize: '12px',
- cssClass: 'apexcharts-xaxis-title',
},
+ formatter: function(value: string) {
+ return value;
+ }
},
categories: labels,
- tickPlacement: 'on'
+ axisBorder: {
+ show: false
+ },
+ axisTicks: {
+ show: false
+ },
},
yaxis: {
- tickAmount: 7,
labels: {
- offsetX: isRtl ? -30 : -10,
- offsetY: 0,
style: {
colors: isDark ? '#fff' : '#000',
- fontSize: '12px',
- cssClass: 'apexcharts-yaxis-title',
- },
- },
+ }
+ }
},
tooltip: {
theme: isDark ? 'dark' : 'light',
- x: {
- show: true,
- },
+ y: {
+ formatter: function(val: number) {
+ return `${currencySymbol} ${val}`;
+ }
+ }
},
+ responsive: [{
+ breakpoint: 480,
+ options: {
+ legend: {
+ position: 'bottom',
+ offsetY: 10,
+ horizontalAlign: 'center',
+ fontSize: '12px',
+ markers: {
+ width: 10,
+ height: 10,
+ offsetX: isRtl ? 5 : -5,
+ },
+ itemMargin: {
+ horizontal: 10,
+ vertical: 5,
+ },
+ },
+ }
+ }]
};
- // return the ui
+
return (
- <>
-
-
{t('incomeOutcomeGeneralOverview')}
-
+
+
{t('incomeOutcomeGeneralOverview')}
+
+
- >
- )
+
+ );
}
\ No newline at end of file