From f5af09cc508c9e2a2b283f9753884d8e40df2927 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Sat, 4 Nov 2023 15:20:22 +0330 Subject: [PATCH 01/17] LFFE-10 create base folder and page of reports --- public/locales/fa/app.json | 4 ++++ src/components/dashboard/reports/index.jsx | 5 +++++ src/core/data/sidebarMenu.jsx | 12 ++++++++++- src/pages/dashboard/reports/index.jsx | 25 ++++++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/components/dashboard/reports/index.jsx create mode 100644 src/pages/dashboard/reports/index.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 2a47ea5..adbf89a 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -34,6 +34,7 @@ }, "sidebar": { "dashboard": "داشبورد", + "reports": "گزارشات", "passenger-office-chief": "اداره مسافر", "machinery-expert": "ماشین آلات", "passenger-boss": "رئیس مسافر ", @@ -93,6 +94,7 @@ }, "Dashboard": { "dashboard_page": "داشبورد", + "reports": "گزارشات", "passenger_boss_page": "رئیس مسافر", "transportation_assistance": "معاونت حمل و نقل", "change_password": "تغییر رمز عبور", @@ -467,5 +469,7 @@ "navgan_id": "کد ناوگان", "button-cancel": "انصراف", "button-add": "ثبت" + }, + "reports": { } } diff --git a/src/components/dashboard/reports/index.jsx b/src/components/dashboard/reports/index.jsx new file mode 100644 index 0000000..3b9665d --- /dev/null +++ b/src/components/dashboard/reports/index.jsx @@ -0,0 +1,5 @@ +const DashboardReportsComponent = (props) => ( + <>hiiiiii +); + +export default DashboardReportsComponent; \ No newline at end of file diff --git a/src/core/data/sidebarMenu.jsx b/src/core/data/sidebarMenu.jsx index db8e0b8..5d0386c 100644 --- a/src/core/data/sidebarMenu.jsx +++ b/src/core/data/sidebarMenu.jsx @@ -13,6 +13,7 @@ import PaidIcon from '@mui/icons-material/Paid'; import ManageAccountsIcon from '@mui/icons-material/ManageAccounts'; import PersonIcon from '@mui/icons-material/Person'; import AccessibilityIcon from '@mui/icons-material/Accessibility'; +import AssessmentIcon from '@mui/icons-material/Assessment'; const sidebarMenu = [ [ @@ -24,6 +25,15 @@ const sidebarMenu = [ selected: false, permission: "all", }, + { + key: "sidebar.reports", + name: "reports", + type: "page", + route: "/dashboard/reports", + icon: , + selected: false, + permission: "all", + }, { key: "sidebar.passenger-office-chief", secondary: "secondary.passenger-office", @@ -146,7 +156,7 @@ const sidebarMenu = [ route: "/dashboard/expert-management", icon: , selected: false, - permission: "manage_navgan_loan", + permission: "manage_experts", }, { key: "sidebar.user-management", diff --git a/src/pages/dashboard/reports/index.jsx b/src/pages/dashboard/reports/index.jsx new file mode 100644 index 0000000..4590184 --- /dev/null +++ b/src/pages/dashboard/reports/index.jsx @@ -0,0 +1,25 @@ +import WithAuthMiddleware from "@/middlewares/WithAuth"; +import {parse} from "next-useragent"; +import DashboardReportsComponent from "@/components/dashboard/reports"; + +// const requiredPermissions = ["reports"]; +export default function Reports() { + return ( + + {/**/} + + {/**/} + + ); +} + +export async function getServerSideProps({req, locale}) { + const {isBot} = parse(req.headers["user-agent"]); + return { + props: { + messages: (await import(`&/locales/${locale}/app.json`)).default, + title: "Dashboard.reports", + isBot, + }, + }; +} From 7c24b55eb385ed093ad9405cae0f7a1dc290d066 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Sat, 4 Nov 2023 17:16:27 +0330 Subject: [PATCH 02/17] LFFE-10 bring two chart (polar/bar) --- src/components/dashboard/reports/BarChart.jsx | 40 +++++++++++++++++ .../dashboard/reports/PolarChart.jsx | 39 +++++++++++++++++ src/components/dashboard/reports/index.jsx | 43 +++++++++++++++++-- .../dashboard/expert-management/index.jsx | 2 +- src/pages/dashboard/reports/index.jsx | 11 ++--- 5 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 src/components/dashboard/reports/BarChart.jsx create mode 100644 src/components/dashboard/reports/PolarChart.jsx diff --git a/src/components/dashboard/reports/BarChart.jsx b/src/components/dashboard/reports/BarChart.jsx new file mode 100644 index 0000000..461b01f --- /dev/null +++ b/src/components/dashboard/reports/BarChart.jsx @@ -0,0 +1,40 @@ +import {Grid} from "@mui/material"; +import Chart from "@/core/components/Chart"; + +const DashboardReportsComponent = (props) => { + const specialOption = { + title: { + text: "مامامیا ماماسیتا", + align: "center" + }, + plotOptions: { + bar: { + borderRadius: 1, + horizontal: false, + } + }, + dataLabels: { + enabled: true + }, + }; + const series = [{ + name: 'اطلاعی ندارم', + data: [ + {x: 'قم', y: 300}, + {x: 'شیراز', y: 240}, + {x: 'اصفهان', y: 190}, + {x: 'تهران', y: 150}, + {x: 'کرج', y: 120}, + {x: 'زنجان', y: 250}, + {x: 'سیستان بلوچستان', y: 180}, + {x: 'هرمزگان', y: 260} + ] + }] + return ( + + + + ) +}; + +export default DashboardReportsComponent; \ No newline at end of file diff --git a/src/components/dashboard/reports/PolarChart.jsx b/src/components/dashboard/reports/PolarChart.jsx new file mode 100644 index 0000000..4af549a --- /dev/null +++ b/src/components/dashboard/reports/PolarChart.jsx @@ -0,0 +1,39 @@ +import {Grid} from "@mui/material"; +import Chart from "@/core/components/Chart"; + +const DashboardReportsComponent = (props) => { + const specialOption = { + title: { + text: "مامامیا ماماسیتا", + align: "center" + }, + stroke: { + colors: ['#fff'] + }, + responsive: [{ + breakpoint: 480, + options: { + chart: { + width: 200 + }, + legend: { + position: 'bottom' + } + } + }], + dataLabels: { + enabled: true + }, + }; + const series = [{ + name: 'اطلاعی ندارم', + data: [14, 23, 21, 17, 15, 10, 12, 17, 21] + }] + return ( + + + + ) +}; + +export default DashboardReportsComponent; \ No newline at end of file diff --git a/src/components/dashboard/reports/index.jsx b/src/components/dashboard/reports/index.jsx index 3b9665d..681b1ca 100644 --- a/src/components/dashboard/reports/index.jsx +++ b/src/components/dashboard/reports/index.jsx @@ -1,5 +1,42 @@ -const DashboardReportsComponent = (props) => ( - <>hiiiiii -); +import {Grid} from "@mui/material"; +import BarChart from "@/components/dashboard/reports/BarChart"; +import PolarChart from "@/components/dashboard/reports/PolarChart"; + +const DashboardReportsComponent = (props) => { + const specialOption = { + title: { + text: "مامامیا ماماسیتا", + align: "center" + }, + plotOptions: { + bar: { + borderRadius: 1, + horizontal: false, + } + }, + dataLabels: { + enabled: true + }, + }; + const series = [{ + name: 'اطلاعی ندارم', + data: [ + {x: 'قم', y: 300}, + {x: 'شیراز', y: 240}, + {x: 'اصفهان', y: 190}, + {x: 'تهران', y: 150}, + {x: 'کرج', y: 120}, + {x: 'زنجان', y: 250}, + {x: 'سیستان بلوچستان', y: 180}, + {x: 'هرمزگان', y: 260} + ] + }] + return ( + + + + + ) +}; export default DashboardReportsComponent; \ No newline at end of file diff --git a/src/pages/dashboard/expert-management/index.jsx b/src/pages/dashboard/expert-management/index.jsx index eab73fc..2db2389 100644 --- a/src/pages/dashboard/expert-management/index.jsx +++ b/src/pages/dashboard/expert-management/index.jsx @@ -14,7 +14,7 @@ export async function getServerSideProps({req, locale}) { messages: (await import(`&/locales/${locale}/app.json`)).default, title: "Dashboard.expert_management", isBot, - layout: {name: 'DashboardLayout', props: {permissions: ["manage_transportation_navgan"]}} + layout: {name: 'DashboardLayout', props: {permissions: ["manage_experts"]}} }, }; } diff --git a/src/pages/dashboard/reports/index.jsx b/src/pages/dashboard/reports/index.jsx index 4590184..9dba421 100644 --- a/src/pages/dashboard/reports/index.jsx +++ b/src/pages/dashboard/reports/index.jsx @@ -1,15 +1,9 @@ -import WithAuthMiddleware from "@/middlewares/WithAuth"; -import {parse} from "next-useragent"; import DashboardReportsComponent from "@/components/dashboard/reports"; +import {parse} from "next-useragent"; -// const requiredPermissions = ["reports"]; export default function Reports() { return ( - - {/**/} - - {/**/} - + ); } @@ -20,6 +14,7 @@ export async function getServerSideProps({req, locale}) { messages: (await import(`&/locales/${locale}/app.json`)).default, title: "Dashboard.reports", isBot, + layout: {name: 'DashboardLayout'} }, }; } From 5c22941bd2fa13af47bbed1cc2732117ce4e7900 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Sun, 5 Nov 2023 14:31:24 +0330 Subject: [PATCH 03/17] LFFE-10 bring bar chart / make diffrent component for each chart / gradiant colorize for charts (compelete structural) --- src/components/dashboard/reports/BarChart.jsx | 89 +++++++++++++++---- .../dashboard/reports/PolarChart.jsx | 30 ++----- src/components/dashboard/reports/index.jsx | 74 ++++++++------- src/lib/app/contexts/chart.jsx | 0 src/lib/app/contexts/language.jsx | 2 +- src/lib/app/hooks/useChart.jsx | 0 6 files changed, 118 insertions(+), 77 deletions(-) create mode 100644 src/lib/app/contexts/chart.jsx create mode 100644 src/lib/app/hooks/useChart.jsx diff --git a/src/components/dashboard/reports/BarChart.jsx b/src/components/dashboard/reports/BarChart.jsx index 461b01f..9065dea 100644 --- a/src/components/dashboard/reports/BarChart.jsx +++ b/src/components/dashboard/reports/BarChart.jsx @@ -1,40 +1,91 @@ -import {Grid} from "@mui/material"; import Chart from "@/core/components/Chart"; -const DashboardReportsComponent = (props) => { +function calculateGradientColor(percentage) { + let colorStops = [ + {percent: 0, color: [199, 18, 5]}, // 0%: #3D0C11 + {percent: 33, color: [240, 59, 47]}, // 33%: #D80032 + {percent: 34, color: [237, 204, 101]}, // 34%: #F2F7A1 + {percent: 66, color: [240, 184, 7]}, // 66%: #E9B824 + {percent: 67, color: [167, 211, 151]}, // 67%: #B0D9B1 + {percent: 100, color: [0, 91, 65]} // 100%: #005B41 + ]; + + let segment; + for (let i = 0; i < colorStops.length - 1; i++) { + if (percentage >= colorStops[i].percent && percentage <= colorStops[i + 1].percent) { + segment = i; + break; + } + } + + let color1 = colorStops[segment].color; + let color2 = colorStops[segment + 1].color; + let ratio = (percentage - colorStops[segment].percent) / (colorStops[segment + 1].percent - colorStops[segment].percent); + + let color = [ + Math.round(color1[0] + ratio * (color2[0] - color1[0])), + Math.round(color1[1] + ratio * (color2[1] - color1[1])), + Math.round(color1[2] + ratio * (color2[2] - color1[2])) + ]; + + return `rgb(${color[0]}, ${color[1]}, ${color[2]})`; + +} + +const BarChart = ({data}) => { + const usableArray = data.map(({name, data, ...rest}) => ({ + x: name, + y: data, + ...rest + })); + let colorArray = data.map(obj => calculateGradientColor(obj.data)); const specialOption = { title: { - text: "مامامیا ماماسیتا", - align: "center" + text: "درصد پیشرفت تسویه وام", + align: "center", + style: { + color: "#7e7e7e", + fontWeight: 500 + } }, + plotOptions: { bar: { - borderRadius: 1, + distributed: true, horizontal: false, + }, + }, + legend: { + show: false, + }, + colors: colorArray, + xaxis: { + labels: { + rotate: 45, + rotateAlways: false, + trim: false, + style: { + fontWeight: 600, + fontSize: "11px", + colors: '#7e7e7e' + } } }, + yaxis: { + min: 0, + max: 100 + }, dataLabels: { enabled: true }, }; const series = [{ name: 'اطلاعی ندارم', - data: [ - {x: 'قم', y: 300}, - {x: 'شیراز', y: 240}, - {x: 'اصفهان', y: 190}, - {x: 'تهران', y: 150}, - {x: 'کرج', y: 120}, - {x: 'زنجان', y: 250}, - {x: 'سیستان بلوچستان', y: 180}, - {x: 'هرمزگان', y: 260} - ] + data: usableArray }] return ( - - - + ) }; -export default DashboardReportsComponent; \ No newline at end of file +export default BarChart; \ No newline at end of file diff --git a/src/components/dashboard/reports/PolarChart.jsx b/src/components/dashboard/reports/PolarChart.jsx index 4af549a..c7b0289 100644 --- a/src/components/dashboard/reports/PolarChart.jsx +++ b/src/components/dashboard/reports/PolarChart.jsx @@ -1,39 +1,21 @@ -import {Grid} from "@mui/material"; import Chart from "@/core/components/Chart"; -const DashboardReportsComponent = (props) => { +const PolarChart = ({data}) => { const specialOption = { title: { text: "مامامیا ماماسیتا", align: "center" }, - stroke: { - colors: ['#fff'] - }, - responsive: [{ - breakpoint: 480, - options: { - chart: { - width: 200 - }, - legend: { - position: 'bottom' - } - } - }], + labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'], + colors: ['red', 'blue', 'green', 'yellow', 'pink'], dataLabels: { enabled: true }, }; - const series = [{ - name: 'اطلاعی ندارم', - data: [14, 23, 21, 17, 15, 10, 12, 17, 21] - }] + const series = [14, 23, 21, 17, 15] return ( - - - + ) }; -export default DashboardReportsComponent; \ No newline at end of file +export default PolarChart; \ No newline at end of file diff --git a/src/components/dashboard/reports/index.jsx b/src/components/dashboard/reports/index.jsx index 681b1ca..24ce45f 100644 --- a/src/components/dashboard/reports/index.jsx +++ b/src/components/dashboard/reports/index.jsx @@ -1,41 +1,49 @@ -import {Grid} from "@mui/material"; +import {Grid, Paper} from "@mui/material"; import BarChart from "@/components/dashboard/reports/BarChart"; import PolarChart from "@/components/dashboard/reports/PolarChart"; +const fakeData = [ + {name: "قم", data: 0}, + {name: "اراک", data: 33}, + {name: "شیراز", data: 90}, + {name: "اصفهان", data: 30}, + {name: "تبریز", data: 70}, + {name: "مشهد", data: 32}, + {name: "تهران", data: 12}, + {name: "اراک", data: 44}, + {name: "شیراز", data: 95}, + {name: "اصفهان", data: 30}, + {name: "تبریز", data: 70}, + {name: "مشهد", data: 10}, + {name: "تهران", data: 28}, + {name: "شیراز", data: 85}, + {name: "اصفهان", data: 30}, + {name: "تبریز", data: 70}, + {name: "مشهد", data: 10}, + {name: "تهران", data: 12}, + {name: "اراک", data: 40}, + {name: " asdراز", data: 85}, + {name: "اصفهان", data: 30}, + {name: "تبریز", data: 67}, + {name: "مشهد", data: 100} +]; + const DashboardReportsComponent = (props) => { - const specialOption = { - title: { - text: "مامامیا ماماسیتا", - align: "center" - }, - plotOptions: { - bar: { - borderRadius: 1, - horizontal: false, - } - }, - dataLabels: { - enabled: true - }, - }; - const series = [{ - name: 'اطلاعی ندارم', - data: [ - {x: 'قم', y: 300}, - {x: 'شیراز', y: 240}, - {x: 'اصفهان', y: 190}, - {x: 'تهران', y: 150}, - {x: 'کرج', y: 120}, - {x: 'زنجان', y: 250}, - {x: 'سیستان بلوچستان', y: 180}, - {x: 'هرمزگان', y: 260} - ] - }] return ( - - - - + <> + + + + + + + + + + + + + ) }; diff --git a/src/lib/app/contexts/chart.jsx b/src/lib/app/contexts/chart.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/app/contexts/language.jsx b/src/lib/app/contexts/language.jsx index a6df674..a31ffd9 100644 --- a/src/lib/app/contexts/language.jsx +++ b/src/lib/app/contexts/language.jsx @@ -13,7 +13,7 @@ export const LanguageProvider = ({children}) => { key: "fa", dir: "rtl", name: "فارسی", - fontFamily: `IRANSans, sans-serif`, + fontFamily: `IRANSansFaNum, sans-serif`, tableLocalization: FA_DATATABLE_LOCALIZATION, chartLocalization: FA_CHART_LOCALIZATION } diff --git a/src/lib/app/hooks/useChart.jsx b/src/lib/app/hooks/useChart.jsx new file mode 100644 index 0000000..e69de29 From 46371dc3ecbb4830bb244adc1ff5e5c8860c4f1d Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Sun, 5 Nov 2023 17:37:56 +0330 Subject: [PATCH 04/17] LFFE-10 bring pie chart and work on polararea --- src/components/dashboard/reports/BarChart.jsx | 3 +- src/components/dashboard/reports/PieChart.jsx | 37 ++++++++++ .../dashboard/reports/PolarChart.jsx | 20 +++++- src/components/dashboard/reports/index.jsx | 67 +++++++++++-------- src/core/components/Chart.jsx | 16 ++++- 5 files changed, 110 insertions(+), 33 deletions(-) create mode 100644 src/components/dashboard/reports/PieChart.jsx diff --git a/src/components/dashboard/reports/BarChart.jsx b/src/components/dashboard/reports/BarChart.jsx index 9065dea..c6dde22 100644 --- a/src/components/dashboard/reports/BarChart.jsx +++ b/src/components/dashboard/reports/BarChart.jsx @@ -48,7 +48,6 @@ const BarChart = ({data}) => { fontWeight: 500 } }, - plotOptions: { bar: { distributed: true, @@ -84,7 +83,7 @@ const BarChart = ({data}) => { data: usableArray }] return ( - + ) }; diff --git a/src/components/dashboard/reports/PieChart.jsx b/src/components/dashboard/reports/PieChart.jsx new file mode 100644 index 0000000..123c2f6 --- /dev/null +++ b/src/components/dashboard/reports/PieChart.jsx @@ -0,0 +1,37 @@ +import Chart from "@/core/components/Chart"; + +const Pie = ({data}) => { + const specialOption = { + title: { + text: "کشوری", + align: "center", + style: { + color: "#7e7e7e", + fontWeight: 500 + } + }, + // plotOptions: { + // pie: { + // rings: { + // strokeWidth: 3, + // strokeColor: '#fff', + // }, + // spokes: { + // strokeWidth: 3, + // connectorColors: '#fff', + // } + // }, + // }, + labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'], + colors: ['red', 'blue', 'green', 'yellow', 'pink'], + dataLabels: { + enabled: true + }, + }; + const series = [14, 23, 21, 17, 15] + return ( + + ) +}; + +export default Pie; \ No newline at end of file diff --git a/src/components/dashboard/reports/PolarChart.jsx b/src/components/dashboard/reports/PolarChart.jsx index c7b0289..db1e533 100644 --- a/src/components/dashboard/reports/PolarChart.jsx +++ b/src/components/dashboard/reports/PolarChart.jsx @@ -3,8 +3,24 @@ import Chart from "@/core/components/Chart"; const PolarChart = ({data}) => { const specialOption = { title: { - text: "مامامیا ماماسیتا", - align: "center" + text: "کشوری", + align: "center", + style: { + color: "#7e7e7e", + fontWeight: 500 + } + }, + plotOptions: { + polarArea: { + rings: { + strokeWidth: 3, + strokeColor: '#fff', + }, + spokes: { + strokeWidth: 3, + connectorColors: '#fff', + } + }, }, labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'], colors: ['red', 'blue', 'green', 'yellow', 'pink'], diff --git a/src/components/dashboard/reports/index.jsx b/src/components/dashboard/reports/index.jsx index 24ce45f..9611b78 100644 --- a/src/components/dashboard/reports/index.jsx +++ b/src/components/dashboard/reports/index.jsx @@ -1,46 +1,59 @@ -import {Grid, Paper} from "@mui/material"; +import {Chip, Divider, Grid, Paper} from "@mui/material"; import BarChart from "@/components/dashboard/reports/BarChart"; import PolarChart from "@/components/dashboard/reports/PolarChart"; +import Pie from "@/components/dashboard/reports/PieChart"; const fakeData = [ - {name: "قم", data: 0}, - {name: "اراک", data: 33}, - {name: "شیراز", data: 90}, + {name: "آذربایجان شرقی", data: 0}, + {name: "آذربایجان غربی", data: 33}, + {name: "اردبیل", data: 90}, {name: "اصفهان", data: 30}, - {name: "تبریز", data: 70}, - {name: "مشهد", data: 32}, - {name: "تهران", data: 12}, - {name: "اراک", data: 44}, - {name: "شیراز", data: 95}, - {name: "اصفهان", data: 30}, - {name: "تبریز", data: 70}, - {name: "مشهد", data: 10}, - {name: "تهران", data: 28}, - {name: "شیراز", data: 85}, - {name: "اصفهان", data: 30}, - {name: "تبریز", data: 70}, - {name: "مشهد", data: 10}, - {name: "تهران", data: 12}, - {name: "اراک", data: 40}, - {name: " asdراز", data: 85}, - {name: "اصفهان", data: 30}, - {name: "تبریز", data: 67}, - {name: "مشهد", data: 100} + {name: "البرز", data: 70}, + {name: "ایلام", data: 32}, + {name: "بوشهر", data: 12}, + {name: "تهران", data: 44}, + {name: "چهارمحال و بختیاری", data: 95}, + {name: "خراسان جنوبی", data: 30}, + {name: "خراسان رضوی", data: 70}, + {name: "خراسان شمالی", data: 10}, + {name: "خوزستان", data: 28}, + {name: "زنجان", data: 85}, + {name: "سمنان", data: 30}, + {name: "سیستان و بلوچستان", data: 70}, + {name: "فارس", data: 10}, + {name: "قزوین", data: 12}, + {name: "قم", data: 40}, + {name: "کردستان", data: 85}, + {name: "کرمان", data: 30}, + {name: "کرمانشاه", data: 67}, + {name: "کهگیلویه و بویراحمد", data: 100}, + {name: "گلستان", data: 97}, + {name: "گیلان", data: 5}, + {name: "لرستان", data: 27}, + {name: "مازندران", data: 31}, + {name: "مرکزی", data: 37}, + {name: "هرمزگان", data: 46}, + {name: "همدان", data: 52}, + {name: "یزد", data: 60} ]; const DashboardReportsComponent = (props) => { return ( <> - + - + - - + + + + + + diff --git a/src/core/components/Chart.jsx b/src/core/components/Chart.jsx index d0796ab..86e5d85 100644 --- a/src/core/components/Chart.jsx +++ b/src/core/components/Chart.jsx @@ -1,16 +1,28 @@ import dynamic from "next/dynamic"; import useLanguage from "@/lib/app/hooks/useLanguage"; +import ReactDOMServer from 'react-dom/server'; +import WidgetsIcon from '@mui/icons-material/Widgets'; + +const widgetIconSvgString = ReactDOMServer.renderToString(); const ApexChart = dynamic(() => import("react-apexcharts"), {ssr: false}); -const Chart = ({type, series, specialOption}) => { +const Chart = ({chartId, type, series, specialOption}) => { const {languageApp, languageList} = useLanguage(); const chartLang = languageList.find((item) => item.key == languageApp).chartLocalization const options = { chart: { + id: chartId, locales: [chartLang], defaultLocale: languageApp, - fontFamily: languageList[0].fontFamily + fontFamily: languageList[0].fontFamily, + toolbar: { + tools: { + zoomIn: false, + zoomOut: false, + download: widgetIconSvgString, + } + } }, ...(specialOption ? specialOption : {}) } From 1de7036f4b1dfb4f9d17d7bde146e1e94860dbd0 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Mon, 6 Nov 2023 17:26:21 +0330 Subject: [PATCH 05/17] LFFE-10 work on filter and specialize components of chart types --- .../dashboard/reports/Filter/index.jsx | 137 ++++++++++++++++++ .../reports/LoanDistribution/PieChart.jsx | 37 +++++ .../reports/LoanDistribution/PolarChart.jsx | 37 +++++ .../reports/LoanDistribution/index.jsx | 57 ++++++++ .../reports/{ => LoanProgress}/BarChart.jsx | 22 +-- .../dashboard/reports/LoanProgress/index.jsx | 52 +++++++ src/components/dashboard/reports/PieChart.jsx | 37 ----- .../dashboard/reports/PolarChart.jsx | 37 ----- src/components/dashboard/reports/index.jsx | 58 +------- 9 files changed, 337 insertions(+), 137 deletions(-) create mode 100644 src/components/dashboard/reports/Filter/index.jsx create mode 100644 src/components/dashboard/reports/LoanDistribution/PieChart.jsx create mode 100644 src/components/dashboard/reports/LoanDistribution/PolarChart.jsx create mode 100644 src/components/dashboard/reports/LoanDistribution/index.jsx rename src/components/dashboard/reports/{ => LoanProgress}/BarChart.jsx (85%) create mode 100644 src/components/dashboard/reports/LoanProgress/index.jsx delete mode 100644 src/components/dashboard/reports/PieChart.jsx delete mode 100644 src/components/dashboard/reports/PolarChart.jsx diff --git a/src/components/dashboard/reports/Filter/index.jsx b/src/components/dashboard/reports/Filter/index.jsx new file mode 100644 index 0000000..3c8ec43 --- /dev/null +++ b/src/components/dashboard/reports/Filter/index.jsx @@ -0,0 +1,137 @@ +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + Button, + Chip, + FormControl, + InputLabel, + MenuItem, + OutlinedInput, + Select, + Stack, + Typography +} from "@mui/material"; +import {useFormik} from "formik"; +import {useState} from "react"; +import QueryStatsIcon from '@mui/icons-material/QueryStats'; + +const provinceList = [ + 'قزوین', + 'تبریز', + 'مشهد', +]; +const yearList = [ + '1401', + '1402', + '1403', +] + +const Filter = ({title}) => { + const [province, setProvince] = useState([]); + const [year, setYear] = useState([]); + const provinceChange = (event) => { + const { + target: {value}, + } = event; + setProvince(typeof value === 'string' ? value.split(',') : value); + }; + const yearChange = (event) => { + const { + target: {value}, + } = event; + setYear(typeof value === 'string' ? value.split(',') : value); + }; + const formik = useFormik({ + initialValues: { + date: "", + province_id: "", + }, onSubmit: (values, {setSubmitting}) => { + const formData = new FormData(); + formData.append("date", values.date); + formData.append("province_id", values.province_id); + + }, + }); + + return ( + + + + {title} + + + + + + + + + انتخاب استان + + + + انتخاب سال + + + + + + ) +}; + +export default Filter; \ No newline at end of file diff --git a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx new file mode 100644 index 0000000..4dcc225 --- /dev/null +++ b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx @@ -0,0 +1,37 @@ +import Chart from "@/core/components/Chart"; + +const Pie = ({data}) => { + const specialOption = { + title: { + text: undefined, + }, + plotOptions: { + pie: { + rings: { + strokeWidth: 3, + strokeColor: '#fff', + }, + fill: { + colors: ['red', 'blue', 'green', 'yellow', 'pink'] + } + }, + }, + fill: { + opacity: 0.9, + }, + labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'], + dataLabels: { + enabled: true, + style: { + fontSize: '14px', + fontWeight: 300, + }, + }, + }; + const series = [14, 23, 21, 17, 15] + return ( + + ) +}; + +export default Pie; \ No newline at end of file diff --git a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx new file mode 100644 index 0000000..97599c3 --- /dev/null +++ b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx @@ -0,0 +1,37 @@ +import Chart from "@/core/components/Chart"; + +const PolarChart = ({data}) => { + const specialOption = { + title: { + text: undefined, + }, + plotOptions: { + polarArea: { + rings: { + strokeWidth: 2, + strokeColor: '#e3e3e3', + }, + fill: { + colors: ['red', 'blue', 'green', 'yellow', 'pink'] + } + }, + }, + fill: { + opacity: 0.9, + }, + labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'], + dataLabels: { + enabled: true, + style: { + fontSize: '14px', + fontWeight: 400, + }, + }, + }; + const series = [14, 23, 21, 17, 15] + return ( + + ) +}; + +export default PolarChart; \ No newline at end of file diff --git a/src/components/dashboard/reports/LoanDistribution/index.jsx b/src/components/dashboard/reports/LoanDistribution/index.jsx new file mode 100644 index 0000000..f90529a --- /dev/null +++ b/src/components/dashboard/reports/LoanDistribution/index.jsx @@ -0,0 +1,57 @@ +import {Chip, Divider, Grid, Paper} from "@mui/material"; +import PolarChart from "./PolarChart"; +import Pie from "./PieChart"; + +const fakeData = [ + {name: "آذربایجان شرقی", data: 0}, + {name: "آذربایجان غربی", data: 33}, + {name: "اردبیل", data: 90}, + {name: "اصفهان", data: 30}, + {name: "البرز", data: 70}, + {name: "ایلام", data: 32}, + {name: "بوشهر", data: 12}, + {name: "تهران", data: 44}, + {name: "چهارمحال و بختیاری", data: 95}, + {name: "خراسان جنوبی", data: 30}, + {name: "خراسان رضوی", data: 70}, + {name: "خراسان شمالی", data: 10}, + {name: "خوزستان", data: 28}, + {name: "زنجان", data: 85}, + {name: "سمنان", data: 30}, + {name: "سیستان و بلوچستان", data: 70}, + {name: "فارس", data: 10}, + {name: "قزوین", data: 12}, + {name: "قم", data: 40}, + {name: "کردستان", data: 85}, + {name: "کرمان", data: 30}, + {name: "کرمانشاه", data: 67}, + {name: "کهگیلویه و بویراحمد", data: 100}, + {name: "گلستان", data: 97}, + {name: "گیلان", data: 5}, + {name: "لرستان", data: 27}, + {name: "مازندران", data: 31}, + {name: "مرکزی", data: 37}, + {name: "هرمزگان", data: 46}, + {name: "همدان", data: 52}, + {name: "یزد", data: 60} +]; + +const LoanDistribution = (props) => { + return ( + + + + + + + + + + + + + + ) +}; + +export default LoanDistribution; \ No newline at end of file diff --git a/src/components/dashboard/reports/BarChart.jsx b/src/components/dashboard/reports/LoanProgress/BarChart.jsx similarity index 85% rename from src/components/dashboard/reports/BarChart.jsx rename to src/components/dashboard/reports/LoanProgress/BarChart.jsx index c6dde22..37e85a8 100644 --- a/src/components/dashboard/reports/BarChart.jsx +++ b/src/components/dashboard/reports/LoanProgress/BarChart.jsx @@ -41,12 +41,7 @@ const BarChart = ({data}) => { let colorArray = data.map(obj => calculateGradientColor(obj.data)); const specialOption = { title: { - text: "درصد پیشرفت تسویه وام", - align: "center", - style: { - color: "#7e7e7e", - fontWeight: 500 - } + text: undefined, }, plotOptions: { bar: { @@ -72,10 +67,19 @@ const BarChart = ({data}) => { }, yaxis: { min: 0, - max: 100 + max: 100, + labels: { + formatter: function (val) { + return val + '%' + } + } }, dataLabels: { - enabled: true + enabled: true, + style: { + fontSize: '14px', + fontWeight: 400, + }, }, }; const series = [{ @@ -83,7 +87,7 @@ const BarChart = ({data}) => { data: usableArray }] return ( - + ) }; diff --git a/src/components/dashboard/reports/LoanProgress/index.jsx b/src/components/dashboard/reports/LoanProgress/index.jsx new file mode 100644 index 0000000..54db36d --- /dev/null +++ b/src/components/dashboard/reports/LoanProgress/index.jsx @@ -0,0 +1,52 @@ +import {Grid, Paper} from "@mui/material"; +import BarChart from "./BarChart"; +import Filter from "../Filter"; + +const fakeData = [ + {name: "آذربایجان شرقی", data: 0}, + {name: "آذربایجان غربی", data: 33}, + {name: "اردبیل", data: 90}, + {name: "اصفهان", data: 30}, + {name: "البرز", data: 70}, + {name: "ایلام", data: 32}, + {name: "بوشهر", data: 12}, + {name: "تهران", data: 44}, + {name: "چهارمحال و بختیاری", data: 95}, + {name: "خراسان جنوبی", data: 30}, + {name: "خراسان رضوی", data: 70}, + {name: "خراسان شمالی", data: 10}, + {name: "خوزستان", data: 28}, + {name: "زنجان", data: 85}, + {name: "سمنان", data: 30}, + {name: "سیستان و بلوچستان", data: 70}, + {name: "فارس", data: 10}, + {name: "قزوین", data: 12}, + {name: "قم", data: 40}, + {name: "کردستان", data: 85}, + {name: "کرمان", data: 30}, + {name: "کرمانشاه", data: 67}, + {name: "کهگیلویه و بویراحمد", data: 100}, + {name: "گلستان", data: 97}, + {name: "گیلان", data: 5}, + {name: "لرستان", data: 27}, + {name: "مازندران", data: 31}, + {name: "مرکزی", data: 37}, + {name: "هرمزگان", data: 46}, + {name: "همدان", data: 52}, + {name: "یزد", data: 60} +]; + +const LoanProgress = (props) => { + return ( + + + + + + + + + ) +}; + +export default LoanProgress; \ No newline at end of file diff --git a/src/components/dashboard/reports/PieChart.jsx b/src/components/dashboard/reports/PieChart.jsx deleted file mode 100644 index 123c2f6..0000000 --- a/src/components/dashboard/reports/PieChart.jsx +++ /dev/null @@ -1,37 +0,0 @@ -import Chart from "@/core/components/Chart"; - -const Pie = ({data}) => { - const specialOption = { - title: { - text: "کشوری", - align: "center", - style: { - color: "#7e7e7e", - fontWeight: 500 - } - }, - // plotOptions: { - // pie: { - // rings: { - // strokeWidth: 3, - // strokeColor: '#fff', - // }, - // spokes: { - // strokeWidth: 3, - // connectorColors: '#fff', - // } - // }, - // }, - labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'], - colors: ['red', 'blue', 'green', 'yellow', 'pink'], - dataLabels: { - enabled: true - }, - }; - const series = [14, 23, 21, 17, 15] - return ( - - ) -}; - -export default Pie; \ No newline at end of file diff --git a/src/components/dashboard/reports/PolarChart.jsx b/src/components/dashboard/reports/PolarChart.jsx deleted file mode 100644 index db1e533..0000000 --- a/src/components/dashboard/reports/PolarChart.jsx +++ /dev/null @@ -1,37 +0,0 @@ -import Chart from "@/core/components/Chart"; - -const PolarChart = ({data}) => { - const specialOption = { - title: { - text: "کشوری", - align: "center", - style: { - color: "#7e7e7e", - fontWeight: 500 - } - }, - plotOptions: { - polarArea: { - rings: { - strokeWidth: 3, - strokeColor: '#fff', - }, - spokes: { - strokeWidth: 3, - connectorColors: '#fff', - } - }, - }, - labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'], - colors: ['red', 'blue', 'green', 'yellow', 'pink'], - dataLabels: { - enabled: true - }, - }; - const series = [14, 23, 21, 17, 15] - return ( - - ) -}; - -export default PolarChart; \ No newline at end of file diff --git a/src/components/dashboard/reports/index.jsx b/src/components/dashboard/reports/index.jsx index 9611b78..1626104 100644 --- a/src/components/dashboard/reports/index.jsx +++ b/src/components/dashboard/reports/index.jsx @@ -1,61 +1,11 @@ -import {Chip, Divider, Grid, Paper} from "@mui/material"; -import BarChart from "@/components/dashboard/reports/BarChart"; -import PolarChart from "@/components/dashboard/reports/PolarChart"; -import Pie from "@/components/dashboard/reports/PieChart"; - -const fakeData = [ - {name: "آذربایجان شرقی", data: 0}, - {name: "آذربایجان غربی", data: 33}, - {name: "اردبیل", data: 90}, - {name: "اصفهان", data: 30}, - {name: "البرز", data: 70}, - {name: "ایلام", data: 32}, - {name: "بوشهر", data: 12}, - {name: "تهران", data: 44}, - {name: "چهارمحال و بختیاری", data: 95}, - {name: "خراسان جنوبی", data: 30}, - {name: "خراسان رضوی", data: 70}, - {name: "خراسان شمالی", data: 10}, - {name: "خوزستان", data: 28}, - {name: "زنجان", data: 85}, - {name: "سمنان", data: 30}, - {name: "سیستان و بلوچستان", data: 70}, - {name: "فارس", data: 10}, - {name: "قزوین", data: 12}, - {name: "قم", data: 40}, - {name: "کردستان", data: 85}, - {name: "کرمان", data: 30}, - {name: "کرمانشاه", data: 67}, - {name: "کهگیلویه و بویراحمد", data: 100}, - {name: "گلستان", data: 97}, - {name: "گیلان", data: 5}, - {name: "لرستان", data: 27}, - {name: "مازندران", data: 31}, - {name: "مرکزی", data: 37}, - {name: "هرمزگان", data: 46}, - {name: "همدان", data: 52}, - {name: "یزد", data: 60} -]; +import LoanProgress from "@/components/dashboard/reports/LoanProgress"; +import LoanDistribution from "@/components/dashboard/reports/LoanDistribution"; const DashboardReportsComponent = (props) => { return ( <> - - - - - - - - - - - - - - - - + + ) }; From 734bb153a0bfaea57627d950df794cffa9f1ec19 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Tue, 7 Nov 2023 17:36:05 +0330 Subject: [PATCH 06/17] LFFE-10 complete sending data part from filters to main page of it and start to sending request and showing witch items are filtering after this --- public/locales/fa/app.json | 3 + .../reports/Filter/ProvinceFilter.jsx | 55 ++++++ .../dashboard/reports/Filter/YearFilter.jsx | 47 +++++ .../dashboard/reports/Filter/index.jsx | 174 ++++++------------ .../reports/LoanDistribution/index.jsx | 18 +- .../dashboard/reports/LoanProgress/index.jsx | 11 +- 6 files changed, 185 insertions(+), 123 deletions(-) create mode 100644 src/components/dashboard/reports/Filter/ProvinceFilter.jsx create mode 100644 src/components/dashboard/reports/Filter/YearFilter.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index adbf89a..07463ed 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -471,5 +471,8 @@ "button-add": "ثبت" }, "reports": { + "loan_progress": "درصد پیشرفت تسویه وام", + "loan_distribution": "درصد توضیع وام ها در هر مرحله", + "filter_as": "فیلتر های اعمال شده" } } diff --git a/src/components/dashboard/reports/Filter/ProvinceFilter.jsx b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx new file mode 100644 index 0000000..ead52f2 --- /dev/null +++ b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx @@ -0,0 +1,55 @@ +import {Box, Chip, FormControl, InputLabel, MenuItem, OutlinedInput, Select} from "@mui/material"; + +const provinceList = [ + {name: "قزوین", id: 1}, + {name: "تبریز", id: 2}, + {name: "مشهد", id: 3} +] + +const ProvinceFilter = ({formik, multiple}) => { + const provinceChange = (event) => { + const {target: {value}} = event; + formik.handleChange(event); + formik.setFieldValue('province_id', value); + }; + return ( + + انتخاب استان + + + ) +}; + +export default ProvinceFilter; \ No newline at end of file diff --git a/src/components/dashboard/reports/Filter/YearFilter.jsx b/src/components/dashboard/reports/Filter/YearFilter.jsx new file mode 100644 index 0000000..c96d704 --- /dev/null +++ b/src/components/dashboard/reports/Filter/YearFilter.jsx @@ -0,0 +1,47 @@ +import {Box, Chip, FormControl, InputLabel, MenuItem, OutlinedInput, Select} from "@mui/material"; +import moment from "jalali-moment"; + +const currentShamsiYear = moment().format('jYYYY'); +const shamsiYearList = Array.from({length: currentShamsiYear - 1399}, (_, index) => (currentShamsiYear - index).toString()); + +const YearFilter = ({formik, multiple}) => { + const yearChange = (event) => { + const {target: {value}} = event; + formik.handleChange(event); + formik.setFieldValue('date', value); + }; + return ( + + انتخاب سال + + + ) +}; + +export default YearFilter; \ No newline at end of file diff --git a/src/components/dashboard/reports/Filter/index.jsx b/src/components/dashboard/reports/Filter/index.jsx index 3c8ec43..43b63bd 100644 --- a/src/components/dashboard/reports/Filter/index.jsx +++ b/src/components/dashboard/reports/Filter/index.jsx @@ -1,135 +1,79 @@ -import { - Accordion, - AccordionDetails, - AccordionSummary, - Box, - Button, - Chip, - FormControl, - InputLabel, - MenuItem, - OutlinedInput, - Select, - Stack, - Typography -} from "@mui/material"; +import {Accordion, AccordionDetails, AccordionSummary, Box, Button, Stack, Typography} from "@mui/material"; import {useFormik} from "formik"; -import {useState} from "react"; -import QueryStatsIcon from '@mui/icons-material/QueryStats'; +import ProvinceFilter from "./ProvinceFilter"; +import YearFilter from "./YearFilter"; +import FilterAltIcon from '@mui/icons-material/FilterAlt'; +import {useTranslations} from "next-intl"; +import TroubleshootIcon from '@mui/icons-material/Troubleshoot'; +import moment from "jalali-moment"; -const provinceList = [ - 'قزوین', - 'تبریز', - 'مشهد', -]; -const yearList = [ - '1401', - '1402', - '1403', -] +const periodOfYear = (year) => { + const isLeapYear = moment.jIsLeapYear(year); + const firstDayGeorgian = moment.from(`${year}/01/01`, 'fa').format('YYYY-MM-DD'); + const lastDayGeorgian = moment.from(`${year}/12/${isLeapYear ? '30' : '29'}`, 'fa').format('YYYY-MM-DD'); + return { + from: firstDayGeorgian, + to: lastDayGeorgian + } +} + +const Filter = ({title, filterItem, expanded}) => { + const t = useTranslations(); + + const filter_by_province = filterItem.find((item) => item.type === "province"); + const filter_by_year = filterItem.find((item) => item.type === "year"); -const Filter = ({title}) => { - const [province, setProvince] = useState([]); - const [year, setYear] = useState([]); - const provinceChange = (event) => { - const { - target: {value}, - } = event; - setProvince(typeof value === 'string' ? value.split(',') : value); - }; - const yearChange = (event) => { - const { - target: {value}, - } = event; - setYear(typeof value === 'string' ? value.split(',') : value); - }; const formik = useFormik({ initialValues: { - date: "", - province_id: "", + ...(filter_by_year && { + date: filter_by_year.multiple ? [] : "" + }), + ...(filter_by_province && { + province_id: filter_by_province.multiple ? [] : "" + }) }, onSubmit: (values, {setSubmitting}) => { - const formData = new FormData(); - formData.append("date", values.date); - formData.append("province_id", values.province_id); - + const dates = values.date + dates.map((date) => { + periodOfYear(date); + }) + console.log("val", values); }, }); - return ( - - - - {title} - - - + + + + {title} + + | {t("reports.filter_as")} : + + + - - - - انتخاب استان - - - - انتخاب سال - - + + + {filter_by_province ? + : "" + } + {filter_by_year ? + : "" + } + + + + ) }; diff --git a/src/components/dashboard/reports/LoanDistribution/index.jsx b/src/components/dashboard/reports/LoanDistribution/index.jsx index f90529a..2e67323 100644 --- a/src/components/dashboard/reports/LoanDistribution/index.jsx +++ b/src/components/dashboard/reports/LoanDistribution/index.jsx @@ -1,6 +1,8 @@ -import {Chip, Divider, Grid, Paper} from "@mui/material"; +import {Grid, Paper} from "@mui/material"; import PolarChart from "./PolarChart"; import Pie from "./PieChart"; +import {useTranslations} from "next-intl"; +import Filter from "@/components/dashboard/reports/Filter"; const fakeData = [ {name: "آذربایجان شرقی", data: 0}, @@ -36,12 +38,16 @@ const fakeData = [ {name: "یزد", data: 60} ]; -const LoanDistribution = (props) => { +const LoanDistribution = () => { + const t = useTranslations(); return ( - - - - + + diff --git a/src/components/dashboard/reports/LoanProgress/index.jsx b/src/components/dashboard/reports/LoanProgress/index.jsx index 54db36d..4f24949 100644 --- a/src/components/dashboard/reports/LoanProgress/index.jsx +++ b/src/components/dashboard/reports/LoanProgress/index.jsx @@ -1,6 +1,7 @@ import {Grid, Paper} from "@mui/material"; import BarChart from "./BarChart"; import Filter from "../Filter"; +import {useTranslations} from "next-intl"; const fakeData = [ {name: "آذربایجان شرقی", data: 0}, @@ -36,10 +37,16 @@ const fakeData = [ {name: "یزد", data: 60} ]; -const LoanProgress = (props) => { +const LoanProgress = () => { + const t = useTranslations(); return ( - + From 3b39b995884c737fe4c291daeec5f4f33dce33aa Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Wed, 8 Nov 2023 15:59:57 +0330 Subject: [PATCH 07/17] bring radial chart and complete search part of province and year --- public/locales/fa/app.json | 13 +++- .../reports/Filter/ProvinceFilter.jsx | 59 ++++++++++++++----- .../dashboard/reports/Filter/YearFilter.jsx | 15 ++++- .../dashboard/reports/Filter/index.jsx | 17 +++--- .../reports/LoanDetails/RadialBarChart.jsx | 47 +++++++++++++++ .../dashboard/reports/LoanDetails/index.jsx | 31 ++++++++++ .../reports/LoanDistribution/PieChart.jsx | 8 +-- .../reports/LoanDistribution/PolarChart.jsx | 4 +- .../reports/LoanDistribution/index.jsx | 2 +- .../reports/LoanProgress/BarChart.jsx | 35 +---------- .../dashboard/reports/LoanProgress/index.jsx | 4 +- src/components/dashboard/reports/index.jsx | 2 + src/core/utils/gradientColorHandler.js | 31 ++++++++++ src/lib/app/contexts/chart.jsx | 0 14 files changed, 197 insertions(+), 71 deletions(-) create mode 100644 src/components/dashboard/reports/LoanDetails/RadialBarChart.jsx create mode 100644 src/components/dashboard/reports/LoanDetails/index.jsx create mode 100644 src/core/utils/gradientColorHandler.js delete mode 100644 src/lib/app/contexts/chart.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 07463ed..ddc3f09 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -472,7 +472,16 @@ }, "reports": { "loan_progress": "درصد پیشرفت تسویه وام", - "loan_distribution": "درصد توضیع وام ها در هر مرحله", - "filter_as": "فیلتر های اعمال شده" + "loan_distribution": "درصد توزیع وام ها در هر مرحله", + "filter_as": "فیلتر های اعمال شده", + "loan_details": "اطلاعات وام ها" + }, + "filters": { + "provinces": "استان های", + "province": "استان", + "year": "سال", + "years": "سال های", + "text_field_loading_provinces_list": "درحال دریافت استان ها", + "text_field_error_fetching_provinces": "خطا در دریافت استان ها" } } diff --git a/src/components/dashboard/reports/Filter/ProvinceFilter.jsx b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx index ead52f2..fc5d79b 100644 --- a/src/components/dashboard/reports/Filter/ProvinceFilter.jsx +++ b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx @@ -1,4 +1,6 @@ -import {Box, Chip, FormControl, InputLabel, MenuItem, OutlinedInput, Select} from "@mui/material"; +import {Box, FormControl, InputLabel, MenuItem, OutlinedInput, Select, Typography} from "@mui/material"; +import {useTranslations} from "next-intl"; +import useProvince from "@/lib/app/hooks/useProvince"; const provinceList = [ {name: "قزوین", id: 1}, @@ -6,11 +8,29 @@ const provinceList = [ {name: "مشهد", id: 3} ] -const ProvinceFilter = ({formik, multiple}) => { +const ProvinceFilter = ({formik, multiple, setFilteredText}) => { + const {errorProvinceList, isLoadingProvinceList, provinceList} = useProvince(); + const t = useTranslations(); const provinceChange = (event) => { const {target: {value}} = event; formik.handleChange(event); formik.setFieldValue('province_id', value); + if (Array.isArray(value)) { + const province_names = [] + value.map((item) => { + province_names.push(provinceList.find(province => province.id === item).name) + }) + setFilteredText(prevState => ({ + ...prevState, + province: province_names.length !== 0 ? `| ${t("filters.provinces")}: ${province_names.join(' , ')}` : "" + })); + } else { + const selectedProvince = provinceList.find(province => province.id === value); + setFilteredText(prevState => ({ + ...prevState, + province: `| ${t("filters.province")}: ${selectedProvince.name}` + })); + } }; return ( @@ -24,29 +44,38 @@ const ProvinceFilter = ({formik, multiple}) => { onChange={provinceChange} onBlur={formik.handleBlur("province_id")} input={} + disabled={isLoadingProvinceList || errorProvinceList} renderValue={multiple ? (selected) => ( - + {selected.map((value) => { const selectedProvince = provinceList.find(province => province.id === value); return ( - + + {selectedProvince ? selectedProvince.name : ''} + ); })} ) : undefined} > - {provinceList.map((province) => ( - - {province.name} + {isLoadingProvinceList ? ( + + {t("filters.text_field_loading_provinces_list")} - ))} + ) : errorProvinceList ? ( + + {t("filters.text_field_error_fetching_provinces")} + + ) : ( + provinceList.map((item) => ( + + {item.name} + + )) + )} ) diff --git a/src/components/dashboard/reports/Filter/YearFilter.jsx b/src/components/dashboard/reports/Filter/YearFilter.jsx index c96d704..022e8be 100644 --- a/src/components/dashboard/reports/Filter/YearFilter.jsx +++ b/src/components/dashboard/reports/Filter/YearFilter.jsx @@ -1,14 +1,27 @@ import {Box, Chip, FormControl, InputLabel, MenuItem, OutlinedInput, Select} from "@mui/material"; import moment from "jalali-moment"; +import {useTranslations} from "next-intl"; const currentShamsiYear = moment().format('jYYYY'); const shamsiYearList = Array.from({length: currentShamsiYear - 1399}, (_, index) => (currentShamsiYear - index).toString()); -const YearFilter = ({formik, multiple}) => { +const YearFilter = ({formik, multiple, setFilteredText}) => { + const t = useTranslations(); const yearChange = (event) => { const {target: {value}} = event; formik.handleChange(event); formik.setFieldValue('date', value); + if (Array.isArray(value)) { + setFilteredText(prevState => ({ + ...prevState, + year: `| ${t("filters.years")}: ${value.join(' , ')}` + })); + } else { + setFilteredText(prevState => ({ + ...prevState, + year: `| ${t("filters.year")}: ${value}` + })); + } }; return ( diff --git a/src/components/dashboard/reports/Filter/index.jsx b/src/components/dashboard/reports/Filter/index.jsx index 43b63bd..2ae310e 100644 --- a/src/components/dashboard/reports/Filter/index.jsx +++ b/src/components/dashboard/reports/Filter/index.jsx @@ -6,6 +6,7 @@ import FilterAltIcon from '@mui/icons-material/FilterAlt'; import {useTranslations} from "next-intl"; import TroubleshootIcon from '@mui/icons-material/Troubleshoot'; import moment from "jalali-moment"; +import {useState} from "react"; const periodOfYear = (year) => { const isLeapYear = moment.jIsLeapYear(year); @@ -19,10 +20,11 @@ const periodOfYear = (year) => { const Filter = ({title, filterItem, expanded}) => { const t = useTranslations(); - const filter_by_province = filterItem.find((item) => item.type === "province"); const filter_by_year = filterItem.find((item) => item.type === "year"); + const [filteredText, setFilteredText] = useState({province: "", year: ""}); + const formik = useFormik({ initialValues: { ...(filter_by_year && { @@ -32,11 +34,6 @@ const Filter = ({title, filterItem, expanded}) => { province_id: filter_by_province.multiple ? [] : "" }) }, onSubmit: (values, {setSubmitting}) => { - const dates = values.date - dates.map((date) => { - periodOfYear(date); - }) - console.log("val", values); }, }); return ( @@ -51,7 +48,7 @@ const Filter = ({title, filterItem, expanded}) => { {title} - | {t("reports.filter_as")} : + {filteredText.province} {filteredText.year} @@ -60,10 +57,12 @@ const Filter = ({title, filterItem, expanded}) => { {filter_by_province ? - : "" + : "" } {filter_by_year ? - : "" + : "" } diff --git a/src/components/dashboard/reports/LoanDetails/RadialBarChart.jsx b/src/components/dashboard/reports/LoanDetails/RadialBarChart.jsx new file mode 100644 index 0000000..69e0bc0 --- /dev/null +++ b/src/components/dashboard/reports/LoanDetails/RadialBarChart.jsx @@ -0,0 +1,47 @@ +import Chart from "@/core/components/Chart"; +import {calculateGradientColor} from "@/core/utils/gradientColorHandler"; + +const RadialBarChart = ({data}) => { + const specialOption = { + title: { + text: undefined, + }, + plotOptions: { + radialBar: { + startAngle: -90, + endAngle: 90, + track: { + background: "#e7e7e7", + strokeWidth: '90%', + margin: 5, // margin is in pixels + dropShadow: { + enabled: true, + top: 2, + left: 0, + color: '#999', + opacity: 1, + blur: 2 + } + }, + dataLabels: { + name: { + show: false + }, + value: { + offsetY: -2, + fontSize: '22px' + } + } + } + }, + fill: { + colors: calculateGradientColor(data) + }, + }; + const series = [data] + return ( + + ) +}; + +export default RadialBarChart; \ No newline at end of file diff --git a/src/components/dashboard/reports/LoanDetails/index.jsx b/src/components/dashboard/reports/LoanDetails/index.jsx new file mode 100644 index 0000000..7ecf452 --- /dev/null +++ b/src/components/dashboard/reports/LoanDetails/index.jsx @@ -0,0 +1,31 @@ +import {Grid, Paper} from "@mui/material"; +import {useTranslations} from "next-intl"; +import Filter from "@/components/dashboard/reports/Filter"; +import RadialBarChart from "@/components/dashboard/reports/LoanDetails/RadialBarChart"; + +const LoanDetails = () => { + const t = useTranslations(); + return ( + + + + + + + + + + + + + + + ) +}; + +export default LoanDetails; \ No newline at end of file diff --git a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx index 4dcc225..42fdec2 100644 --- a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx @@ -7,19 +7,15 @@ const Pie = ({data}) => { }, plotOptions: { pie: { - rings: { - strokeWidth: 3, - strokeColor: '#fff', - }, fill: { - colors: ['red', 'blue', 'green', 'yellow', 'pink'] + colors: ['#F99417', '#363062', '#005B41', '#C70039', '#EE9322'] } }, }, fill: { opacity: 0.9, }, - labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'], + labels: [' آیتم 1', ' آیتم 2', ' آیتم 3', ' آیتم 4', ' آیتم 5'], dataLabels: { enabled: true, style: { diff --git a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx index 97599c3..c334a01 100644 --- a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx @@ -12,14 +12,14 @@ const PolarChart = ({data}) => { strokeColor: '#e3e3e3', }, fill: { - colors: ['red', 'blue', 'green', 'yellow', 'pink'] + colors: ['#F99417', '#363062', '#005B41', '#C70039', '#EE9322'] } }, }, fill: { opacity: 0.9, }, - labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'], + labels: [' آیتم 1', ' آیتم 2', ' آیتم 3', ' آیتم 4', ' آیتم 5'], dataLabels: { enabled: true, style: { diff --git a/src/components/dashboard/reports/LoanDistribution/index.jsx b/src/components/dashboard/reports/LoanDistribution/index.jsx index 2e67323..f9a14bd 100644 --- a/src/components/dashboard/reports/LoanDistribution/index.jsx +++ b/src/components/dashboard/reports/LoanDistribution/index.jsx @@ -45,7 +45,7 @@ const LoanDistribution = () => { diff --git a/src/components/dashboard/reports/LoanProgress/BarChart.jsx b/src/components/dashboard/reports/LoanProgress/BarChart.jsx index 37e85a8..bf0b686 100644 --- a/src/components/dashboard/reports/LoanProgress/BarChart.jsx +++ b/src/components/dashboard/reports/LoanProgress/BarChart.jsx @@ -1,36 +1,5 @@ import Chart from "@/core/components/Chart"; - -function calculateGradientColor(percentage) { - let colorStops = [ - {percent: 0, color: [199, 18, 5]}, // 0%: #3D0C11 - {percent: 33, color: [240, 59, 47]}, // 33%: #D80032 - {percent: 34, color: [237, 204, 101]}, // 34%: #F2F7A1 - {percent: 66, color: [240, 184, 7]}, // 66%: #E9B824 - {percent: 67, color: [167, 211, 151]}, // 67%: #B0D9B1 - {percent: 100, color: [0, 91, 65]} // 100%: #005B41 - ]; - - let segment; - for (let i = 0; i < colorStops.length - 1; i++) { - if (percentage >= colorStops[i].percent && percentage <= colorStops[i + 1].percent) { - segment = i; - break; - } - } - - let color1 = colorStops[segment].color; - let color2 = colorStops[segment + 1].color; - let ratio = (percentage - colorStops[segment].percent) / (colorStops[segment + 1].percent - colorStops[segment].percent); - - let color = [ - Math.round(color1[0] + ratio * (color2[0] - color1[0])), - Math.round(color1[1] + ratio * (color2[1] - color1[1])), - Math.round(color1[2] + ratio * (color2[2] - color1[2])) - ]; - - return `rgb(${color[0]}, ${color[1]}, ${color[2]})`; - -} +import {calculateGradientColor} from "@/core/utils/gradientColorHandler"; const BarChart = ({data}) => { const usableArray = data.map(({name, data, ...rest}) => ({ @@ -83,7 +52,7 @@ const BarChart = ({data}) => { }, }; const series = [{ - name: 'اطلاعی ندارم', + name: 'درصد پیشرفت', data: usableArray }] return ( diff --git a/src/components/dashboard/reports/LoanProgress/index.jsx b/src/components/dashboard/reports/LoanProgress/index.jsx index 4f24949..62bf8aa 100644 --- a/src/components/dashboard/reports/LoanProgress/index.jsx +++ b/src/components/dashboard/reports/LoanProgress/index.jsx @@ -43,8 +43,8 @@ const LoanProgress = () => { diff --git a/src/components/dashboard/reports/index.jsx b/src/components/dashboard/reports/index.jsx index 1626104..5965e08 100644 --- a/src/components/dashboard/reports/index.jsx +++ b/src/components/dashboard/reports/index.jsx @@ -1,11 +1,13 @@ import LoanProgress from "@/components/dashboard/reports/LoanProgress"; import LoanDistribution from "@/components/dashboard/reports/LoanDistribution"; +import LoanDetails from "@/components/dashboard/reports/LoanDetails"; const DashboardReportsComponent = (props) => { return ( <> + ) }; diff --git a/src/core/utils/gradientColorHandler.js b/src/core/utils/gradientColorHandler.js new file mode 100644 index 0000000..780f856 --- /dev/null +++ b/src/core/utils/gradientColorHandler.js @@ -0,0 +1,31 @@ +export const calculateGradientColor = (percentage) => { + let colorStops = [ + {percent: 0, color: [199, 18, 5]}, // 0%: #3D0C11 + {percent: 33, color: [240, 59, 47]}, // 33%: #D80032 + {percent: 34, color: [237, 204, 101]}, // 34%: #F2F7A1 + {percent: 66, color: [240, 184, 7]}, // 66%: #E9B824 + {percent: 67, color: [167, 211, 151]}, // 67%: #B0D9B1 + {percent: 100, color: [0, 91, 65]} // 100%: #005B41 + ]; + + let segment; + for (let i = 0; i < colorStops.length - 1; i++) { + if (percentage >= colorStops[i].percent && percentage <= colorStops[i + 1].percent) { + segment = i; + break; + } + } + + let color1 = colorStops[segment].color; + let color2 = colorStops[segment + 1].color; + let ratio = (percentage - colorStops[segment].percent) / (colorStops[segment + 1].percent - colorStops[segment].percent); + + let color = [ + Math.round(color1[0] + ratio * (color2[0] - color1[0])), + Math.round(color1[1] + ratio * (color2[1] - color1[1])), + Math.round(color1[2] + ratio * (color2[2] - color1[2])) + ]; + + return `rgb(${color[0]}, ${color[1]}, ${color[2]})`; + +} \ No newline at end of file diff --git a/src/lib/app/contexts/chart.jsx b/src/lib/app/contexts/chart.jsx deleted file mode 100644 index e69de29..0000000 From ef03dea5cf76b9f7783f437db87a33b627ca62ae Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Wed, 8 Nov 2023 15:59:57 +0330 Subject: [PATCH 08/17] LFFE-10 bring radial chart and complete search part of province and year --- public/locales/fa/app.json | 13 +++- .../reports/Filter/ProvinceFilter.jsx | 59 ++++++++++++++----- .../dashboard/reports/Filter/YearFilter.jsx | 15 ++++- .../dashboard/reports/Filter/index.jsx | 17 +++--- .../reports/LoanDetails/RadialBarChart.jsx | 47 +++++++++++++++ .../dashboard/reports/LoanDetails/index.jsx | 31 ++++++++++ .../reports/LoanDistribution/PieChart.jsx | 8 +-- .../reports/LoanDistribution/PolarChart.jsx | 4 +- .../reports/LoanDistribution/index.jsx | 2 +- .../reports/LoanProgress/BarChart.jsx | 35 +---------- .../dashboard/reports/LoanProgress/index.jsx | 4 +- src/components/dashboard/reports/index.jsx | 2 + src/core/utils/gradientColorHandler.js | 31 ++++++++++ src/lib/app/contexts/chart.jsx | 0 14 files changed, 197 insertions(+), 71 deletions(-) create mode 100644 src/components/dashboard/reports/LoanDetails/RadialBarChart.jsx create mode 100644 src/components/dashboard/reports/LoanDetails/index.jsx create mode 100644 src/core/utils/gradientColorHandler.js delete mode 100644 src/lib/app/contexts/chart.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 07463ed..ddc3f09 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -472,7 +472,16 @@ }, "reports": { "loan_progress": "درصد پیشرفت تسویه وام", - "loan_distribution": "درصد توضیع وام ها در هر مرحله", - "filter_as": "فیلتر های اعمال شده" + "loan_distribution": "درصد توزیع وام ها در هر مرحله", + "filter_as": "فیلتر های اعمال شده", + "loan_details": "اطلاعات وام ها" + }, + "filters": { + "provinces": "استان های", + "province": "استان", + "year": "سال", + "years": "سال های", + "text_field_loading_provinces_list": "درحال دریافت استان ها", + "text_field_error_fetching_provinces": "خطا در دریافت استان ها" } } diff --git a/src/components/dashboard/reports/Filter/ProvinceFilter.jsx b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx index ead52f2..fc5d79b 100644 --- a/src/components/dashboard/reports/Filter/ProvinceFilter.jsx +++ b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx @@ -1,4 +1,6 @@ -import {Box, Chip, FormControl, InputLabel, MenuItem, OutlinedInput, Select} from "@mui/material"; +import {Box, FormControl, InputLabel, MenuItem, OutlinedInput, Select, Typography} from "@mui/material"; +import {useTranslations} from "next-intl"; +import useProvince from "@/lib/app/hooks/useProvince"; const provinceList = [ {name: "قزوین", id: 1}, @@ -6,11 +8,29 @@ const provinceList = [ {name: "مشهد", id: 3} ] -const ProvinceFilter = ({formik, multiple}) => { +const ProvinceFilter = ({formik, multiple, setFilteredText}) => { + const {errorProvinceList, isLoadingProvinceList, provinceList} = useProvince(); + const t = useTranslations(); const provinceChange = (event) => { const {target: {value}} = event; formik.handleChange(event); formik.setFieldValue('province_id', value); + if (Array.isArray(value)) { + const province_names = [] + value.map((item) => { + province_names.push(provinceList.find(province => province.id === item).name) + }) + setFilteredText(prevState => ({ + ...prevState, + province: province_names.length !== 0 ? `| ${t("filters.provinces")}: ${province_names.join(' , ')}` : "" + })); + } else { + const selectedProvince = provinceList.find(province => province.id === value); + setFilteredText(prevState => ({ + ...prevState, + province: `| ${t("filters.province")}: ${selectedProvince.name}` + })); + } }; return ( @@ -24,29 +44,38 @@ const ProvinceFilter = ({formik, multiple}) => { onChange={provinceChange} onBlur={formik.handleBlur("province_id")} input={} + disabled={isLoadingProvinceList || errorProvinceList} renderValue={multiple ? (selected) => ( - + {selected.map((value) => { const selectedProvince = provinceList.find(province => province.id === value); return ( - + + {selectedProvince ? selectedProvince.name : ''} + ); })} ) : undefined} > - {provinceList.map((province) => ( - - {province.name} + {isLoadingProvinceList ? ( + + {t("filters.text_field_loading_provinces_list")} - ))} + ) : errorProvinceList ? ( + + {t("filters.text_field_error_fetching_provinces")} + + ) : ( + provinceList.map((item) => ( + + {item.name} + + )) + )} ) diff --git a/src/components/dashboard/reports/Filter/YearFilter.jsx b/src/components/dashboard/reports/Filter/YearFilter.jsx index c96d704..022e8be 100644 --- a/src/components/dashboard/reports/Filter/YearFilter.jsx +++ b/src/components/dashboard/reports/Filter/YearFilter.jsx @@ -1,14 +1,27 @@ import {Box, Chip, FormControl, InputLabel, MenuItem, OutlinedInput, Select} from "@mui/material"; import moment from "jalali-moment"; +import {useTranslations} from "next-intl"; const currentShamsiYear = moment().format('jYYYY'); const shamsiYearList = Array.from({length: currentShamsiYear - 1399}, (_, index) => (currentShamsiYear - index).toString()); -const YearFilter = ({formik, multiple}) => { +const YearFilter = ({formik, multiple, setFilteredText}) => { + const t = useTranslations(); const yearChange = (event) => { const {target: {value}} = event; formik.handleChange(event); formik.setFieldValue('date', value); + if (Array.isArray(value)) { + setFilteredText(prevState => ({ + ...prevState, + year: `| ${t("filters.years")}: ${value.join(' , ')}` + })); + } else { + setFilteredText(prevState => ({ + ...prevState, + year: `| ${t("filters.year")}: ${value}` + })); + } }; return ( diff --git a/src/components/dashboard/reports/Filter/index.jsx b/src/components/dashboard/reports/Filter/index.jsx index 43b63bd..2ae310e 100644 --- a/src/components/dashboard/reports/Filter/index.jsx +++ b/src/components/dashboard/reports/Filter/index.jsx @@ -6,6 +6,7 @@ import FilterAltIcon from '@mui/icons-material/FilterAlt'; import {useTranslations} from "next-intl"; import TroubleshootIcon from '@mui/icons-material/Troubleshoot'; import moment from "jalali-moment"; +import {useState} from "react"; const periodOfYear = (year) => { const isLeapYear = moment.jIsLeapYear(year); @@ -19,10 +20,11 @@ const periodOfYear = (year) => { const Filter = ({title, filterItem, expanded}) => { const t = useTranslations(); - const filter_by_province = filterItem.find((item) => item.type === "province"); const filter_by_year = filterItem.find((item) => item.type === "year"); + const [filteredText, setFilteredText] = useState({province: "", year: ""}); + const formik = useFormik({ initialValues: { ...(filter_by_year && { @@ -32,11 +34,6 @@ const Filter = ({title, filterItem, expanded}) => { province_id: filter_by_province.multiple ? [] : "" }) }, onSubmit: (values, {setSubmitting}) => { - const dates = values.date - dates.map((date) => { - periodOfYear(date); - }) - console.log("val", values); }, }); return ( @@ -51,7 +48,7 @@ const Filter = ({title, filterItem, expanded}) => { {title} - | {t("reports.filter_as")} : + {filteredText.province} {filteredText.year} @@ -60,10 +57,12 @@ const Filter = ({title, filterItem, expanded}) => { {filter_by_province ? - : "" + : "" } {filter_by_year ? - : "" + : "" } diff --git a/src/components/dashboard/reports/LoanDetails/RadialBarChart.jsx b/src/components/dashboard/reports/LoanDetails/RadialBarChart.jsx new file mode 100644 index 0000000..69e0bc0 --- /dev/null +++ b/src/components/dashboard/reports/LoanDetails/RadialBarChart.jsx @@ -0,0 +1,47 @@ +import Chart from "@/core/components/Chart"; +import {calculateGradientColor} from "@/core/utils/gradientColorHandler"; + +const RadialBarChart = ({data}) => { + const specialOption = { + title: { + text: undefined, + }, + plotOptions: { + radialBar: { + startAngle: -90, + endAngle: 90, + track: { + background: "#e7e7e7", + strokeWidth: '90%', + margin: 5, // margin is in pixels + dropShadow: { + enabled: true, + top: 2, + left: 0, + color: '#999', + opacity: 1, + blur: 2 + } + }, + dataLabels: { + name: { + show: false + }, + value: { + offsetY: -2, + fontSize: '22px' + } + } + } + }, + fill: { + colors: calculateGradientColor(data) + }, + }; + const series = [data] + return ( + + ) +}; + +export default RadialBarChart; \ No newline at end of file diff --git a/src/components/dashboard/reports/LoanDetails/index.jsx b/src/components/dashboard/reports/LoanDetails/index.jsx new file mode 100644 index 0000000..7ecf452 --- /dev/null +++ b/src/components/dashboard/reports/LoanDetails/index.jsx @@ -0,0 +1,31 @@ +import {Grid, Paper} from "@mui/material"; +import {useTranslations} from "next-intl"; +import Filter from "@/components/dashboard/reports/Filter"; +import RadialBarChart from "@/components/dashboard/reports/LoanDetails/RadialBarChart"; + +const LoanDetails = () => { + const t = useTranslations(); + return ( + + + + + + + + + + + + + + + ) +}; + +export default LoanDetails; \ No newline at end of file diff --git a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx index 4dcc225..42fdec2 100644 --- a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx @@ -7,19 +7,15 @@ const Pie = ({data}) => { }, plotOptions: { pie: { - rings: { - strokeWidth: 3, - strokeColor: '#fff', - }, fill: { - colors: ['red', 'blue', 'green', 'yellow', 'pink'] + colors: ['#F99417', '#363062', '#005B41', '#C70039', '#EE9322'] } }, }, fill: { opacity: 0.9, }, - labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'], + labels: [' آیتم 1', ' آیتم 2', ' آیتم 3', ' آیتم 4', ' آیتم 5'], dataLabels: { enabled: true, style: { diff --git a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx index 97599c3..c334a01 100644 --- a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx @@ -12,14 +12,14 @@ const PolarChart = ({data}) => { strokeColor: '#e3e3e3', }, fill: { - colors: ['red', 'blue', 'green', 'yellow', 'pink'] + colors: ['#F99417', '#363062', '#005B41', '#C70039', '#EE9322'] } }, }, fill: { opacity: 0.9, }, - labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'], + labels: [' آیتم 1', ' آیتم 2', ' آیتم 3', ' آیتم 4', ' آیتم 5'], dataLabels: { enabled: true, style: { diff --git a/src/components/dashboard/reports/LoanDistribution/index.jsx b/src/components/dashboard/reports/LoanDistribution/index.jsx index 2e67323..f9a14bd 100644 --- a/src/components/dashboard/reports/LoanDistribution/index.jsx +++ b/src/components/dashboard/reports/LoanDistribution/index.jsx @@ -45,7 +45,7 @@ const LoanDistribution = () => { diff --git a/src/components/dashboard/reports/LoanProgress/BarChart.jsx b/src/components/dashboard/reports/LoanProgress/BarChart.jsx index 37e85a8..bf0b686 100644 --- a/src/components/dashboard/reports/LoanProgress/BarChart.jsx +++ b/src/components/dashboard/reports/LoanProgress/BarChart.jsx @@ -1,36 +1,5 @@ import Chart from "@/core/components/Chart"; - -function calculateGradientColor(percentage) { - let colorStops = [ - {percent: 0, color: [199, 18, 5]}, // 0%: #3D0C11 - {percent: 33, color: [240, 59, 47]}, // 33%: #D80032 - {percent: 34, color: [237, 204, 101]}, // 34%: #F2F7A1 - {percent: 66, color: [240, 184, 7]}, // 66%: #E9B824 - {percent: 67, color: [167, 211, 151]}, // 67%: #B0D9B1 - {percent: 100, color: [0, 91, 65]} // 100%: #005B41 - ]; - - let segment; - for (let i = 0; i < colorStops.length - 1; i++) { - if (percentage >= colorStops[i].percent && percentage <= colorStops[i + 1].percent) { - segment = i; - break; - } - } - - let color1 = colorStops[segment].color; - let color2 = colorStops[segment + 1].color; - let ratio = (percentage - colorStops[segment].percent) / (colorStops[segment + 1].percent - colorStops[segment].percent); - - let color = [ - Math.round(color1[0] + ratio * (color2[0] - color1[0])), - Math.round(color1[1] + ratio * (color2[1] - color1[1])), - Math.round(color1[2] + ratio * (color2[2] - color1[2])) - ]; - - return `rgb(${color[0]}, ${color[1]}, ${color[2]})`; - -} +import {calculateGradientColor} from "@/core/utils/gradientColorHandler"; const BarChart = ({data}) => { const usableArray = data.map(({name, data, ...rest}) => ({ @@ -83,7 +52,7 @@ const BarChart = ({data}) => { }, }; const series = [{ - name: 'اطلاعی ندارم', + name: 'درصد پیشرفت', data: usableArray }] return ( diff --git a/src/components/dashboard/reports/LoanProgress/index.jsx b/src/components/dashboard/reports/LoanProgress/index.jsx index 4f24949..62bf8aa 100644 --- a/src/components/dashboard/reports/LoanProgress/index.jsx +++ b/src/components/dashboard/reports/LoanProgress/index.jsx @@ -43,8 +43,8 @@ const LoanProgress = () => { diff --git a/src/components/dashboard/reports/index.jsx b/src/components/dashboard/reports/index.jsx index 1626104..5965e08 100644 --- a/src/components/dashboard/reports/index.jsx +++ b/src/components/dashboard/reports/index.jsx @@ -1,11 +1,13 @@ import LoanProgress from "@/components/dashboard/reports/LoanProgress"; import LoanDistribution from "@/components/dashboard/reports/LoanDistribution"; +import LoanDetails from "@/components/dashboard/reports/LoanDetails"; const DashboardReportsComponent = (props) => { return ( <> + ) }; diff --git a/src/core/utils/gradientColorHandler.js b/src/core/utils/gradientColorHandler.js new file mode 100644 index 0000000..780f856 --- /dev/null +++ b/src/core/utils/gradientColorHandler.js @@ -0,0 +1,31 @@ +export const calculateGradientColor = (percentage) => { + let colorStops = [ + {percent: 0, color: [199, 18, 5]}, // 0%: #3D0C11 + {percent: 33, color: [240, 59, 47]}, // 33%: #D80032 + {percent: 34, color: [237, 204, 101]}, // 34%: #F2F7A1 + {percent: 66, color: [240, 184, 7]}, // 66%: #E9B824 + {percent: 67, color: [167, 211, 151]}, // 67%: #B0D9B1 + {percent: 100, color: [0, 91, 65]} // 100%: #005B41 + ]; + + let segment; + for (let i = 0; i < colorStops.length - 1; i++) { + if (percentage >= colorStops[i].percent && percentage <= colorStops[i + 1].percent) { + segment = i; + break; + } + } + + let color1 = colorStops[segment].color; + let color2 = colorStops[segment + 1].color; + let ratio = (percentage - colorStops[segment].percent) / (colorStops[segment + 1].percent - colorStops[segment].percent); + + let color = [ + Math.round(color1[0] + ratio * (color2[0] - color1[0])), + Math.round(color1[1] + ratio * (color2[1] - color1[1])), + Math.round(color1[2] + ratio * (color2[2] - color1[2])) + ]; + + return `rgb(${color[0]}, ${color[1]}, ${color[2]})`; + +} \ No newline at end of file diff --git a/src/lib/app/contexts/chart.jsx b/src/lib/app/contexts/chart.jsx deleted file mode 100644 index e69de29..0000000 From 98d459dc388969ff337dfc7003da7b62a74b2c22 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Sat, 11 Nov 2023 17:34:55 +0330 Subject: [PATCH 09/17] LFFE-10 rdial bar with two types / making progress and making hook of fetching data for charts --- public/locales/fa/app.json | 6 +- .../dashboard/reports/Filter/index.jsx | 2 + ...art.jsx => RadialBarSemiCircularChart.jsx} | 33 +++++---- .../LoanDetails/RadialBarStrokedChart.jsx | 51 ++++++++++++++ .../dashboard/reports/LoanDetails/index.jsx | 21 +++--- .../reports/LoanDistribution/index.jsx | 6 +- .../reports/LoanProgress/BarChart.jsx | 42 ++++++------ .../dashboard/reports/LoanProgress/index.jsx | 67 ++++++++----------- src/core/data/apiRoutes.js | 4 ++ src/core/utils/gradientColorHandler.js | 4 +- src/lib/app/hooks/useChart.jsx | 28 ++++++++ 11 files changed, 174 insertions(+), 90 deletions(-) rename src/components/dashboard/reports/LoanDetails/{RadialBarChart.jsx => RadialBarSemiCircularChart.jsx} (54%) create mode 100644 src/components/dashboard/reports/LoanDetails/RadialBarStrokedChart.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index ddc3f09..b677113 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -474,7 +474,11 @@ "loan_progress": "درصد پیشرفت تسویه وام", "loan_distribution": "درصد توزیع وام ها در هر مرحله", "filter_as": "فیلتر های اعمال شده", - "loan_details": "اطلاعات وام ها" + "loan_details": "جزئیات وام ها", + "cost_of_loan_refer_to_bank": "مبلغ وام های معرفی به بانک", + "number_of_loan_refer_to_bank": "تعداد وام های معرفی به بانک", + "cost_of_payed_loan": "مبلغ وام های پرداخت شده", + "number_of_payed_loan": "تعداد وام های پرداخت شده" }, "filters": { "provinces": "استان های", diff --git a/src/components/dashboard/reports/Filter/index.jsx b/src/components/dashboard/reports/Filter/index.jsx index 2ae310e..198cf93 100644 --- a/src/components/dashboard/reports/Filter/index.jsx +++ b/src/components/dashboard/reports/Filter/index.jsx @@ -3,6 +3,7 @@ import {useFormik} from "formik"; import ProvinceFilter from "./ProvinceFilter"; import YearFilter from "./YearFilter"; import FilterAltIcon from '@mui/icons-material/FilterAlt'; +import EqualizerIcon from '@mui/icons-material/Equalizer'; import {useTranslations} from "next-intl"; import TroubleshootIcon from '@mui/icons-material/Troubleshoot'; import moment from "jalali-moment"; @@ -46,6 +47,7 @@ const Filter = ({title, filterItem, expanded}) => { + {title} {filteredText.province} {filteredText.year} diff --git a/src/components/dashboard/reports/LoanDetails/RadialBarChart.jsx b/src/components/dashboard/reports/LoanDetails/RadialBarSemiCircularChart.jsx similarity index 54% rename from src/components/dashboard/reports/LoanDetails/RadialBarChart.jsx rename to src/components/dashboard/reports/LoanDetails/RadialBarSemiCircularChart.jsx index 69e0bc0..4a8fd11 100644 --- a/src/components/dashboard/reports/LoanDetails/RadialBarChart.jsx +++ b/src/components/dashboard/reports/LoanDetails/RadialBarSemiCircularChart.jsx @@ -1,35 +1,33 @@ import Chart from "@/core/components/Chart"; import {calculateGradientColor} from "@/core/utils/gradientColorHandler"; -const RadialBarChart = ({data}) => { +const RadialBarSemiCircularChart = ({data, label}) => { const specialOption = { title: { text: undefined, }, plotOptions: { radialBar: { - startAngle: -90, - endAngle: 90, + startAngle: -110, + endAngle: 110, track: { background: "#e7e7e7", - strokeWidth: '90%', - margin: 5, // margin is in pixels - dropShadow: { - enabled: true, - top: 2, - left: 0, - color: '#999', - opacity: 1, - blur: 2 - } + strokeWidth: '80%', }, dataLabels: { name: { - show: false + fontSize: '20px', + offsetY: 110, + color: "#8c8c8c" }, value: { - offsetY: -2, - fontSize: '22px' + offsetY: 50, + fontSize: '50px', + fontWeight: 500, + color: "#8c8c8c", + formatter: function (val) { + return val + "%"; + } } } } @@ -37,6 +35,7 @@ const RadialBarChart = ({data}) => { fill: { colors: calculateGradientColor(data) }, + labels: [label], }; const series = [data] return ( @@ -44,4 +43,4 @@ const RadialBarChart = ({data}) => { ) }; -export default RadialBarChart; \ No newline at end of file +export default RadialBarSemiCircularChart; \ No newline at end of file diff --git a/src/components/dashboard/reports/LoanDetails/RadialBarStrokedChart.jsx b/src/components/dashboard/reports/LoanDetails/RadialBarStrokedChart.jsx new file mode 100644 index 0000000..6482994 --- /dev/null +++ b/src/components/dashboard/reports/LoanDetails/RadialBarStrokedChart.jsx @@ -0,0 +1,51 @@ +import Chart from "@/core/components/Chart"; +import {calculateGradientColor} from "@/core/utils/gradientColorHandler"; +import {useTranslations} from "next-intl"; + +const RadialBarStrokedChart = ({data, label}) => { + const t = useTranslations(); + const specialOption = { + title: { + text: undefined, + }, + plotOptions: { + radialBar: { + startAngle: -110, + endAngle: 110, + track: { + background: "#e7e7e7", + strokeWidth: '80%', + }, + dataLabels: { + name: { + fontSize: '20px', + offsetY: 110, + color: "#8c8c8c" + }, + value: { + offsetY: 50, + fontSize: '50px', + fontWeight: 500, + color: "#8c8c8c", + formatter: function (val) { + return val + "%"; + } + } + } + } + }, + stroke: { + dashArray: 4 + }, + fill: { + colors: calculateGradientColor(data) + }, + labels: [label], + }; + const series = [data] + return ( + + ) +}; + +export default RadialBarStrokedChart; \ No newline at end of file diff --git a/src/components/dashboard/reports/LoanDetails/index.jsx b/src/components/dashboard/reports/LoanDetails/index.jsx index 7ecf452..111535b 100644 --- a/src/components/dashboard/reports/LoanDetails/index.jsx +++ b/src/components/dashboard/reports/LoanDetails/index.jsx @@ -1,7 +1,9 @@ import {Grid, Paper} from "@mui/material"; import {useTranslations} from "next-intl"; import Filter from "@/components/dashboard/reports/Filter"; -import RadialBarChart from "@/components/dashboard/reports/LoanDetails/RadialBarChart"; +import RadialBarSemiCircularChart from "@/components/dashboard/reports/LoanDetails/RadialBarSemiCircularChart"; +import RadialBarStrokedChart from "@/components/dashboard/reports/LoanDetails/RadialBarStrokedChart"; + const LoanDetails = () => { const t = useTranslations(); @@ -13,15 +15,18 @@ const LoanDetails = () => { {type: "year", type_fa: "سال", multiple: false} ]} /> - - - + + + - - + + - - + + + + + diff --git a/src/components/dashboard/reports/LoanDistribution/index.jsx b/src/components/dashboard/reports/LoanDistribution/index.jsx index f9a14bd..1108270 100644 --- a/src/components/dashboard/reports/LoanDistribution/index.jsx +++ b/src/components/dashboard/reports/LoanDistribution/index.jsx @@ -48,11 +48,11 @@ const LoanDistribution = () => { {type: "year", type_fa: "سال", multiple: false} ]} /> - - + + - + diff --git a/src/components/dashboard/reports/LoanProgress/BarChart.jsx b/src/components/dashboard/reports/LoanProgress/BarChart.jsx index bf0b686..315f2d2 100644 --- a/src/components/dashboard/reports/LoanProgress/BarChart.jsx +++ b/src/components/dashboard/reports/LoanProgress/BarChart.jsx @@ -1,13 +1,14 @@ -import Chart from "@/core/components/Chart"; import {calculateGradientColor} from "@/core/utils/gradientColorHandler"; +import Chart from "@/core/components/Chart"; const BarChart = ({data}) => { - const usableArray = data.map(({name, data, ...rest}) => ({ - x: name, - y: data, - ...rest + console.log(data) + const usableArray = data.map(({province_name, percentage, ...rest}) => ({ + x: province_name, + y: percentage, + ...rest, })); - let colorArray = data.map(obj => calculateGradientColor(obj.data)); + let colorArray = data.map((obj) => calculateGradientColor(obj.percentage)); const specialOption = { title: { text: undefined, @@ -29,19 +30,19 @@ const BarChart = ({data}) => { trim: false, style: { fontWeight: 600, - fontSize: "11px", - colors: '#7e7e7e' - } - } + fontSize: '11px', + colors: '#7e7e7e', + }, + }, }, yaxis: { min: 0, max: 100, labels: { formatter: function (val) { - return val + '%' - } - } + return val + '%'; + }, + }, }, dataLabels: { enabled: true, @@ -51,13 +52,14 @@ const BarChart = ({data}) => { }, }, }; - const series = [{ - name: 'درصد پیشرفت', - data: usableArray - }] - return ( - - ) + const series = [ + { + name: 'درصد پیشرفت', + data: usableArray, + }, + ]; + + return ; }; export default BarChart; \ No newline at end of file diff --git a/src/components/dashboard/reports/LoanProgress/index.jsx b/src/components/dashboard/reports/LoanProgress/index.jsx index 62bf8aa..5bb1440 100644 --- a/src/components/dashboard/reports/LoanProgress/index.jsx +++ b/src/components/dashboard/reports/LoanProgress/index.jsx @@ -1,55 +1,44 @@ -import {Grid, Paper} from "@mui/material"; +import {Box, CircularProgress, Grid, Paper, Typography} from "@mui/material"; import BarChart from "./BarChart"; import Filter from "../Filter"; import {useTranslations} from "next-intl"; - -const fakeData = [ - {name: "آذربایجان شرقی", data: 0}, - {name: "آذربایجان غربی", data: 33}, - {name: "اردبیل", data: 90}, - {name: "اصفهان", data: 30}, - {name: "البرز", data: 70}, - {name: "ایلام", data: 32}, - {name: "بوشهر", data: 12}, - {name: "تهران", data: 44}, - {name: "چهارمحال و بختیاری", data: 95}, - {name: "خراسان جنوبی", data: 30}, - {name: "خراسان رضوی", data: 70}, - {name: "خراسان شمالی", data: 10}, - {name: "خوزستان", data: 28}, - {name: "زنجان", data: 85}, - {name: "سمنان", data: 30}, - {name: "سیستان و بلوچستان", data: 70}, - {name: "فارس", data: 10}, - {name: "قزوین", data: 12}, - {name: "قم", data: 40}, - {name: "کردستان", data: 85}, - {name: "کرمان", data: 30}, - {name: "کرمانشاه", data: 67}, - {name: "کهگیلویه و بویراحمد", data: 100}, - {name: "گلستان", data: 97}, - {name: "گیلان", data: 5}, - {name: "لرستان", data: 27}, - {name: "مازندران", data: 31}, - {name: "مرکزی", data: 37}, - {name: "هرمزگان", data: 46}, - {name: "همدان", data: 52}, - {name: "یزد", data: 60} -]; +import useChart from "@/lib/app/hooks/useChart"; +import {GET_PROVINCE_PROGRESS} from "@/core/data/apiRoutes"; const LoanProgress = () => { const t = useTranslations(); + const {errorReportList, isLoadingReportList, reportList} = useChart(GET_PROVINCE_PROGRESS); + + console.log(reportList) return ( - - - + + + {1 === 1 ? ( + + + + درحال دریافت اطلاعات + + + ) : errorReportList ? ( + درحال دریافت اطلاعات + ) : ( + + )} diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index dba065e..d18aeba 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -197,3 +197,7 @@ export const DELETE_ROLE_MANAGEMENT = export const GET_PERMISSIONS_LIST = BASE_URL + "/dashboard/permissions/list" //role management + +// reports +export const GET_PROVINCE_PROGRESS = BASE_URL + "/dashboard/reports/navgan/province_progress" +// reports diff --git a/src/core/utils/gradientColorHandler.js b/src/core/utils/gradientColorHandler.js index 780f856..e16b42a 100644 --- a/src/core/utils/gradientColorHandler.js +++ b/src/core/utils/gradientColorHandler.js @@ -1,7 +1,7 @@ export const calculateGradientColor = (percentage) => { let colorStops = [ - {percent: 0, color: [199, 18, 5]}, // 0%: #3D0C11 - {percent: 33, color: [240, 59, 47]}, // 33%: #D80032 + {percent: 0, color: [173, 3, 23]}, // 0%: #3D0C11 + {percent: 33, color: [245, 81, 81]}, // 33%: #D80032 {percent: 34, color: [237, 204, 101]}, // 34%: #F2F7A1 {percent: 66, color: [240, 184, 7]}, // 66%: #E9B824 {percent: 67, color: [167, 211, 151]}, // 67%: #B0D9B1 diff --git a/src/lib/app/hooks/useChart.jsx b/src/lib/app/hooks/useChart.jsx index e69de29..180d1f5 100644 --- a/src/lib/app/hooks/useChart.jsx +++ b/src/lib/app/hooks/useChart.jsx @@ -0,0 +1,28 @@ +import useRequest from "@/lib/app/hooks/useRequest"; +import useSWR from "swr"; + +const useChart = (chart_url) => { + const requestServer = useRequest({auth: true, notification: false}) + + //swr config + const fetcher = (...args) => { + return requestServer(args, 'get').then(({data}) => { + return data.data; + }).catch(() => { + }) + }; + + const {data, isLoading} = useSWR(chart_url, fetcher, { + revalidateIfStale: false, + revalidateOnFocus: false, + revalidateOnReconnect: false + }); + + return { + reportList: data, + isLoadingReportList: isLoading, + errorReportList: !data + } +}; + +export default useChart; \ No newline at end of file From f48672274d111c5ec55b45777075d4db2b4bc6f5 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Mon, 13 Nov 2023 17:18:25 +0330 Subject: [PATCH 10/17] LFFE-10 report page filter completed and problem of request solved and working on excel export --- public/locales/fa/app.json | 11 ++- .../dashboard/reports/ExcelExport/index.jsx | 44 ++++++++++ .../reports/Filter/ProvinceFilter.jsx | 4 +- .../dashboard/reports/Filter/YearFilter.jsx | 35 +++++--- .../dashboard/reports/Filter/index.jsx | 41 ++++++---- .../reports/LoanDistribution/PieChart.jsx | 11 +-- .../reports/LoanDistribution/PolarChart.jsx | 7 +- .../reports/LoanDistribution/index.jsx | 80 +++++++++---------- .../reports/LoanProgress/BarChart.jsx | 3 +- .../dashboard/reports/LoanProgress/index.jsx | 11 ++- src/components/dashboard/reports/index.jsx | 2 + src/core/data/apiRoutes.js | 2 + src/lib/app/hooks/useChart.jsx | 12 ++- 13 files changed, 165 insertions(+), 98 deletions(-) create mode 100644 src/components/dashboard/reports/ExcelExport/index.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index b677113..da7e0ee 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -478,14 +478,21 @@ "cost_of_loan_refer_to_bank": "مبلغ وام های معرفی به بانک", "number_of_loan_refer_to_bank": "تعداد وام های معرفی به بانک", "cost_of_payed_loan": "مبلغ وام های پرداخت شده", - "number_of_payed_loan": "تعداد وام های پرداخت شده" + "number_of_payed_loan": "تعداد وام های پرداخت شده", + "loading_fetching_reports": "درحال دریافت گزارشات", + "error_fetching_reports": "خطا در دریافت گزارشات" }, "filters": { + "choose_province": "انتخاب استان", + "choose_year": "انتخاب سال", "provinces": "استان های", "province": "استان", "year": "سال", "years": "سال های", "text_field_loading_provinces_list": "درحال دریافت استان ها", - "text_field_error_fetching_provinces": "خطا در دریافت استان ها" + "text_field_error_fetching_provinces": "خطا در دریافت استان ها", + "filter": "اعمال فیلتر", + "excel_export": "خروجی به اکسل", + "export": "دریافت" } } diff --git a/src/components/dashboard/reports/ExcelExport/index.jsx b/src/components/dashboard/reports/ExcelExport/index.jsx new file mode 100644 index 0000000..fd3a789 --- /dev/null +++ b/src/components/dashboard/reports/ExcelExport/index.jsx @@ -0,0 +1,44 @@ +import {Accordion, AccordionDetails, AccordionSummary, Box, Button, Stack, Typography} from "@mui/material"; +import FileUploadIcon from '@mui/icons-material/FileUpload'; +import AssignmentIcon from '@mui/icons-material/Assignment'; +import {useTranslations} from "next-intl"; + +const ExcelExport = () => { + const t = useTranslations(); + + return ( + + + + + + + {t("filters.excel_export")} + + + + + + + + + + + + + + + ) +}; + +export default ExcelExport; \ No newline at end of file diff --git a/src/components/dashboard/reports/Filter/ProvinceFilter.jsx b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx index fc5d79b..12ec7dc 100644 --- a/src/components/dashboard/reports/Filter/ProvinceFilter.jsx +++ b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx @@ -34,7 +34,7 @@ const ProvinceFilter = ({formik, multiple, setFilteredText}) => { }; return ( - انتخاب استان + {t("filters.choose_province")} { value={formik.values.date} onChange={yearChange} onBlur={formik.handleBlur("date")} - input={} + input={} renderValue={multiple ? (selected) => ( {selected.map((value) => ( @@ -44,14 +57,16 @@ const YearFilter = ({formik, multiple, setFilteredText}) => { ) : undefined} > - {shamsiYearList.map((year) => ( - - {year} - - ))} + { + shamsiYearList.map((year) => ( + + {year} + + )) + } ) diff --git a/src/components/dashboard/reports/Filter/index.jsx b/src/components/dashboard/reports/Filter/index.jsx index 198cf93..b5b0a23 100644 --- a/src/components/dashboard/reports/Filter/index.jsx +++ b/src/components/dashboard/reports/Filter/index.jsx @@ -1,25 +1,14 @@ import {Accordion, AccordionDetails, AccordionSummary, Box, Button, Stack, Typography} from "@mui/material"; import {useFormik} from "formik"; -import ProvinceFilter from "./ProvinceFilter"; -import YearFilter from "./YearFilter"; +import ProvinceFilter from "../Filter/ProvinceFilter"; +import YearFilter from "../Filter/YearFilter"; import FilterAltIcon from '@mui/icons-material/FilterAlt'; import EqualizerIcon from '@mui/icons-material/Equalizer'; import {useTranslations} from "next-intl"; import TroubleshootIcon from '@mui/icons-material/Troubleshoot'; -import moment from "jalali-moment"; import {useState} from "react"; -const periodOfYear = (year) => { - const isLeapYear = moment.jIsLeapYear(year); - const firstDayGeorgian = moment.from(`${year}/01/01`, 'fa').format('YYYY-MM-DD'); - const lastDayGeorgian = moment.from(`${year}/12/${isLeapYear ? '30' : '29'}`, 'fa').format('YYYY-MM-DD'); - return { - from: firstDayGeorgian, - to: lastDayGeorgian - } -} - -const Filter = ({title, filterItem, expanded}) => { +const Filter = ({title, filterItem, setFilterOption}) => { const t = useTranslations(); const filter_by_province = filterItem.find((item) => item.type === "province"); const filter_by_year = filterItem.find((item) => item.type === "year"); @@ -33,8 +22,26 @@ const Filter = ({title, filterItem, expanded}) => { }), ...(filter_by_province && { province_id: filter_by_province.multiple ? [] : "" - }) + }), + from_date: "", + to_date: "" }, onSubmit: (values, {setSubmitting}) => { + const province = values.province_id; + const fields = [ + values.from_date ? {key: "from_date", value: values.from_date} : null, + values.to_date ? {key: "to_date", value: values.to_date} : null, + ...(Array.isArray(province) + ? province.length !== 0 + ? province.map((item, index) => ({key: `province_id[${index}]`, value: item})) + : [] + : province + ? [{key: "province_id", value: province}] + : [] + ), + ].filter(Boolean); + console.log("fields", fields) + setFilterOption(fields) + setSubmitting(false) }, }); return ( @@ -48,7 +55,7 @@ const Filter = ({title, filterItem, expanded}) => { - {title} + دریافت گزارش تکمیلی {filteredText.province} {filteredText.year} @@ -71,7 +78,7 @@ const Filter = ({title, filterItem, expanded}) => { + >{t("filters.filter")} diff --git a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx index 42fdec2..8b26443 100644 --- a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx @@ -5,17 +5,10 @@ const Pie = ({data}) => { title: { text: undefined, }, - plotOptions: { - pie: { - fill: { - colors: ['#F99417', '#363062', '#005B41', '#C70039', '#EE9322'] - } - }, - }, fill: { opacity: 0.9, }, - labels: [' آیتم 1', ' آیتم 2', ' آیتم 3', ' آیتم 4', ' آیتم 5'], + labels: data.map((item) => ` ${item.state_name}`), dataLabels: { enabled: true, style: { @@ -24,7 +17,7 @@ const Pie = ({data}) => { }, }, }; - const series = [14, 23, 21, 17, 15] + const series = data.map((item) => +item.percentage) return ( ) diff --git a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx index c334a01..974f93d 100644 --- a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx @@ -11,15 +11,12 @@ const PolarChart = ({data}) => { strokeWidth: 2, strokeColor: '#e3e3e3', }, - fill: { - colors: ['#F99417', '#363062', '#005B41', '#C70039', '#EE9322'] - } }, }, fill: { opacity: 0.9, }, - labels: [' آیتم 1', ' آیتم 2', ' آیتم 3', ' آیتم 4', ' آیتم 5'], + labels: data.map((item) => ` ${item.state_name}`), dataLabels: { enabled: true, style: { @@ -28,7 +25,7 @@ const PolarChart = ({data}) => { }, }, }; - const series = [14, 23, 21, 17, 15] + const series = data.map((item) => +item.percentage) return ( ) diff --git a/src/components/dashboard/reports/LoanDistribution/index.jsx b/src/components/dashboard/reports/LoanDistribution/index.jsx index 1108270..9872291 100644 --- a/src/components/dashboard/reports/LoanDistribution/index.jsx +++ b/src/components/dashboard/reports/LoanDistribution/index.jsx @@ -1,60 +1,56 @@ -import {Grid, Paper} from "@mui/material"; +import {Box, CircularProgress, Grid, Paper, Typography} from "@mui/material"; import PolarChart from "./PolarChart"; import Pie from "./PieChart"; import {useTranslations} from "next-intl"; import Filter from "@/components/dashboard/reports/Filter"; - -const fakeData = [ - {name: "آذربایجان شرقی", data: 0}, - {name: "آذربایجان غربی", data: 33}, - {name: "اردبیل", data: 90}, - {name: "اصفهان", data: 30}, - {name: "البرز", data: 70}, - {name: "ایلام", data: 32}, - {name: "بوشهر", data: 12}, - {name: "تهران", data: 44}, - {name: "چهارمحال و بختیاری", data: 95}, - {name: "خراسان جنوبی", data: 30}, - {name: "خراسان رضوی", data: 70}, - {name: "خراسان شمالی", data: 10}, - {name: "خوزستان", data: 28}, - {name: "زنجان", data: 85}, - {name: "سمنان", data: 30}, - {name: "سیستان و بلوچستان", data: 70}, - {name: "فارس", data: 10}, - {name: "قزوین", data: 12}, - {name: "قم", data: 40}, - {name: "کردستان", data: 85}, - {name: "کرمان", data: 30}, - {name: "کرمانشاه", data: 67}, - {name: "کهگیلویه و بویراحمد", data: 100}, - {name: "گلستان", data: 97}, - {name: "گیلان", data: 5}, - {name: "لرستان", data: 27}, - {name: "مازندران", data: 31}, - {name: "مرکزی", data: 37}, - {name: "هرمزگان", data: 46}, - {name: "همدان", data: 52}, - {name: "یزد", data: 60} -]; +import useChart from "@/lib/app/hooks/useChart"; +import {GET_LOAN_DISTRIBUTION} from "@/core/data/apiRoutes"; const LoanDistribution = () => { const t = useTranslations(); + const {errorReportList, isLoadingReportList, reportList, setFilterOption} = useChart(GET_LOAN_DISTRIBUTION); + return ( - - - - - - + {isLoadingReportList ? ( + + + + + {t("reports.loading_fetching_reports")} + + + + ) : errorReportList ? ( + + {t("reports.error_fetching_reports")} + + ) : ( + <> + + + + + + + + )} ) diff --git a/src/components/dashboard/reports/LoanProgress/BarChart.jsx b/src/components/dashboard/reports/LoanProgress/BarChart.jsx index 315f2d2..745257c 100644 --- a/src/components/dashboard/reports/LoanProgress/BarChart.jsx +++ b/src/components/dashboard/reports/LoanProgress/BarChart.jsx @@ -2,10 +2,9 @@ import {calculateGradientColor} from "@/core/utils/gradientColorHandler"; import Chart from "@/core/components/Chart"; const BarChart = ({data}) => { - console.log(data) const usableArray = data.map(({province_name, percentage, ...rest}) => ({ x: province_name, - y: percentage, + y: +percentage, ...rest, })); let colorArray = data.map((obj) => calculateGradientColor(obj.percentage)); diff --git a/src/components/dashboard/reports/LoanProgress/index.jsx b/src/components/dashboard/reports/LoanProgress/index.jsx index 5bb1440..7bc6a35 100644 --- a/src/components/dashboard/reports/LoanProgress/index.jsx +++ b/src/components/dashboard/reports/LoanProgress/index.jsx @@ -7,19 +7,18 @@ import {GET_PROVINCE_PROGRESS} from "@/core/data/apiRoutes"; const LoanProgress = () => { const t = useTranslations(); - const {errorReportList, isLoadingReportList, reportList} = useChart(GET_PROVINCE_PROGRESS); - - console.log(reportList) + const {errorReportList, isLoadingReportList, reportList, setFilterOption} = useChart(GET_PROVINCE_PROGRESS); return ( - {1 === 1 ? ( + {isLoadingReportList ? ( { - درحال دریافت اطلاعات + {t("reports.loading_fetching_reports")} ) : errorReportList ? ( - درحال دریافت اطلاعات + {t("reports.error_fetching_reports")} ) : ( )} diff --git a/src/components/dashboard/reports/index.jsx b/src/components/dashboard/reports/index.jsx index 5965e08..56f513c 100644 --- a/src/components/dashboard/reports/index.jsx +++ b/src/components/dashboard/reports/index.jsx @@ -1,10 +1,12 @@ import LoanProgress from "@/components/dashboard/reports/LoanProgress"; import LoanDistribution from "@/components/dashboard/reports/LoanDistribution"; import LoanDetails from "@/components/dashboard/reports/LoanDetails"; +import ExcelExport from "@/components/dashboard/reports/ExcelExport"; const DashboardReportsComponent = (props) => { return ( <> + diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index d18aeba..f7025ee 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -199,5 +199,7 @@ export const GET_PERMISSIONS_LIST = //role management // reports +export const GET_EXPORTS = BASE_URL + "/dashboard/exports/navgan" export const GET_PROVINCE_PROGRESS = BASE_URL + "/dashboard/reports/navgan/province_progress" +export const GET_LOAN_DISTRIBUTION = BASE_URL + "/dashboard/reports/navgan/loan_distribution" // reports diff --git a/src/lib/app/hooks/useChart.jsx b/src/lib/app/hooks/useChart.jsx index 180d1f5..c010a03 100644 --- a/src/lib/app/hooks/useChart.jsx +++ b/src/lib/app/hooks/useChart.jsx @@ -1,9 +1,14 @@ import useRequest from "@/lib/app/hooks/useRequest"; import useSWR from "swr"; +import {useState} from "react"; const useChart = (chart_url) => { const requestServer = useRequest({auth: true, notification: false}) - + const [filterOption, setFilterOption] = useState([]); + const queryString = filterOption.length !== 0 + ? `?${filterOption.map((option) => `${option.key}=${option.value}`).join('&')}` + : ''; + console.log("check query", queryString) //swr config const fetcher = (...args) => { return requestServer(args, 'get').then(({data}) => { @@ -12,7 +17,7 @@ const useChart = (chart_url) => { }) }; - const {data, isLoading} = useSWR(chart_url, fetcher, { + const {data, isLoading} = useSWR(`${chart_url}${queryString}`, fetcher, { revalidateIfStale: false, revalidateOnFocus: false, revalidateOnReconnect: false @@ -21,7 +26,8 @@ const useChart = (chart_url) => { return { reportList: data, isLoadingReportList: isLoading, - errorReportList: !data + errorReportList: !data, + setFilterOption: setFilterOption } }; From c9326730d8e7e78bd21abda77c2ee6c924013a18 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Tue, 14 Nov 2023 17:29:10 +0330 Subject: [PATCH 11/17] LFFE-10 complete excel export of charts and solve problem of reloading and add refresh chart data and some other actions --- package.json | 1 + .../dashboard/reports/ExcelExport/index.jsx | 126 +++++++++++++----- .../reports/Filter/ProvinceFilter.jsx | 31 ++++- .../dashboard/reports/Filter/YearFilter.jsx | 11 +- .../dashboard/reports/Filter/index.jsx | 92 +++++++++---- .../dashboard/reports/LoanDetails/index.jsx | 15 ++- .../reports/LoanDistribution/index.jsx | 5 +- .../dashboard/reports/LoanProgress/index.jsx | 4 +- src/core/data/apiRoutes.js | 2 +- src/core/utils/yearPeriodFinder.js | 11 ++ src/lib/app/hooks/useChart.jsx | 15 ++- src/lib/app/hooks/useProvince.jsx | 3 +- src/lib/app/hooks/useRole.jsx | 3 +- 13 files changed, 236 insertions(+), 83 deletions(-) create mode 100644 src/core/utils/yearPeriodFinder.js diff --git a/package.json b/package.json index a560c0c..229374d 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "date-fns-jalali": "^2.13.0-0", "dayjs": "^1.11.9", "eslint": "8.36.0", + "file-saver": "^2.0.5", "formik": "^2.2.9", "fs-extra": "^11.1.1", "image-resize": "^1.3.2", diff --git a/src/components/dashboard/reports/ExcelExport/index.jsx b/src/components/dashboard/reports/ExcelExport/index.jsx index fd3a789..2ab8e35 100644 --- a/src/components/dashboard/reports/ExcelExport/index.jsx +++ b/src/components/dashboard/reports/ExcelExport/index.jsx @@ -2,42 +2,108 @@ import {Accordion, AccordionDetails, AccordionSummary, Box, Button, Stack, Typog import FileUploadIcon from '@mui/icons-material/FileUpload'; import AssignmentIcon from '@mui/icons-material/Assignment'; import {useTranslations} from "next-intl"; +import ProvinceFilter from "@/components/dashboard/reports/Filter/ProvinceFilter"; +import YearFilter from "@/components/dashboard/reports/Filter/YearFilter"; +import {useState} from "react"; +import {useFormik} from "formik"; +import {GET_EXPORT} from "@/core/data/apiRoutes"; +import moment from "jalali-moment"; +import FileSaver from 'file-saver'; +import useRequest from "@/lib/app/hooks/useRequest"; const ExcelExport = () => { const t = useTranslations(); + const requestServer = useRequest() + const filterItem = [ + {type: "province", type_fa: "استان", multiple: false}, + {type: "year", type_fa: "سال", multiple: false} + ]; + const filter_by_province = filterItem.find((item) => item.type === "province"); + const filter_by_year = filterItem.find((item) => item.type === "year"); + + const [filteredText, setFilteredText] = useState({province: "", year: ""}); + + const formik = useFormik({ + initialValues: { + ...(filter_by_year && { + date: filter_by_year.multiple ? [] : `${moment().format('jYYYY')}` + }), + ...(filter_by_province && { + province_id: filter_by_province.multiple ? [] : "" + }), + from_date: "", + to_date: "" + }, onSubmit: (values, {setSubmitting}) => { + const province = values.province_id; + const fields = [ + values.from_date ? {key: "from_date", value: values.from_date} : null, + values.to_date ? {key: "to_date", value: values.to_date} : null, + ...(Array.isArray(province) + ? province.length !== 0 + ? province.map((item, index) => ({key: `province_id[${index}]`, value: item})) + : [] + : province + ? [{key: "province_id", value: province}] + : [] + ), + ].filter(Boolean); + const queryString = fields.length !== 0 + ? `?${fields.map((option) => `${option.key}=${option.value}`).join('&')}` + : ''; + requestServer(`${GET_EXPORT}${queryString}`, 'GET', {auth: true, requestOptions: {responseType: 'blob'}}) + .then((response) => { + const filename = `گزارش درخواست های وام ناوگان تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`; + FileSaver.saveAs(response.data, filename); + }).catch(() => { + }).finally(() => { + setSubmitting(false); + }); + }, + }); return ( - - - - - - - {t("filters.excel_export")} - + + + + + + + + {t("filters.excel_export")} + + + - - - - - - - - - - - - + + + + {filter_by_province ? + : "" + } + {filter_by_year ? + : "" + } + + + + + + + ) }; diff --git a/src/components/dashboard/reports/Filter/ProvinceFilter.jsx b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx index 12ec7dc..16a1133 100644 --- a/src/components/dashboard/reports/Filter/ProvinceFilter.jsx +++ b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx @@ -1,6 +1,17 @@ -import {Box, FormControl, InputLabel, MenuItem, OutlinedInput, Select, Typography} from "@mui/material"; +import { + Box, + FormControl, + IconButton, + InputAdornment, + InputLabel, + MenuItem, + OutlinedInput, + Select, + Typography +} from "@mui/material"; import {useTranslations} from "next-intl"; import useProvince from "@/lib/app/hooks/useProvince"; +import ClearIcon from '@mui/icons-material/Clear'; const provinceList = [ {name: "قزوین", id: 1}, @@ -32,6 +43,9 @@ const ProvinceFilter = ({formik, multiple, setFilteredText}) => { })); } }; + const needAdorment = multiple + ? formik.values.province_id.length === 0 : + formik.values.province_id === ""; return ( {t("filters.choose_province")} @@ -48,7 +62,7 @@ const ProvinceFilter = ({formik, multiple, setFilteredText}) => { renderValue={multiple ? (selected) => ( {selected.map((value) => { const selectedProvince = provinceList.find(province => province.id === value); @@ -60,6 +74,19 @@ const ProvinceFilter = ({formik, multiple, setFilteredText}) => { })} ) : undefined} + endAdornment={ + !needAdorment ? + + multiple + ? formik.setFieldValue('province_id', []) + : formik.setFieldValue('province_id', "") + } + size="small"> + + + : null + } > {isLoadingProvinceList ? ( diff --git a/src/components/dashboard/reports/Filter/YearFilter.jsx b/src/components/dashboard/reports/Filter/YearFilter.jsx index 0f7aff6..66a3db6 100644 --- a/src/components/dashboard/reports/Filter/YearFilter.jsx +++ b/src/components/dashboard/reports/Filter/YearFilter.jsx @@ -1,20 +1,11 @@ import {Box, Chip, FormControl, InputLabel, MenuItem, OutlinedInput, Select} from "@mui/material"; import moment from "jalali-moment"; import {useTranslations} from "next-intl"; +import {periodOfYear} from "@/core/utils/yearPeriodFinder"; const currentShamsiYear = moment().format('jYYYY'); const shamsiYearList = Array.from({length: currentShamsiYear - 1399}, (_, index) => (currentShamsiYear - index).toString()); -const periodOfYear = (year) => { - const isLeapYear = moment.jIsLeapYear(year); - const firstDayGeorgian = moment.from(`${year}/01/01`, 'fa').format('YYYY-MM-DD'); - const lastDayGeorgian = moment.from(`${year}/12/${isLeapYear ? '30' : '29'}`, 'fa').format('YYYY-MM-DD'); - return { - from: firstDayGeorgian, - to: lastDayGeorgian - } -} - const YearFilter = ({formik, multiple, setFilteredText}) => { const t = useTranslations(); const yearChange = (event) => { diff --git a/src/components/dashboard/reports/Filter/index.jsx b/src/components/dashboard/reports/Filter/index.jsx index b5b0a23..f8757c1 100644 --- a/src/components/dashboard/reports/Filter/index.jsx +++ b/src/components/dashboard/reports/Filter/index.jsx @@ -1,4 +1,14 @@ -import {Accordion, AccordionDetails, AccordionSummary, Box, Button, Stack, Typography} from "@mui/material"; +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + Button, + CircularProgress, + IconButton, + Stack, + Typography +} from "@mui/material"; import {useFormik} from "formik"; import ProvinceFilter from "../Filter/ProvinceFilter"; import YearFilter from "../Filter/YearFilter"; @@ -6,26 +16,35 @@ import FilterAltIcon from '@mui/icons-material/FilterAlt'; import EqualizerIcon from '@mui/icons-material/Equalizer'; import {useTranslations} from "next-intl"; import TroubleshootIcon from '@mui/icons-material/Troubleshoot'; -import {useState} from "react"; +import CachedIcon from '@mui/icons-material/Cached'; +import {useEffect, useState} from "react"; +import moment from "jalali-moment"; +import {periodOfYear} from "@/core/utils/yearPeriodFinder"; -const Filter = ({title, filterItem, setFilterOption}) => { +CachedIcon +const Filter = ({title, filterItem, setFilterOption, isLoadingReportList, mutate}) => { const t = useTranslations(); const filter_by_province = filterItem.find((item) => item.type === "province"); const filter_by_year = filterItem.find((item) => item.type === "year"); + const [expanded, setExpanded] = useState(false); const [filteredText, setFilteredText] = useState({province: "", year: ""}); + const [stepValue, setStepValue] = useState({ + ...(filter_by_year && { + date: filter_by_year.multiple ? [] : `${moment().format('jYYYY')}` + }), + ...(filter_by_province && { + province_id: filter_by_province.multiple ? [] : "" + }), + from_date: periodOfYear(moment().format('jYYYY')).from, + to_date: periodOfYear(moment().format('jYYYY')).to + }) + const formik = useFormik({ - initialValues: { - ...(filter_by_year && { - date: filter_by_year.multiple ? [] : "" - }), - ...(filter_by_province && { - province_id: filter_by_province.multiple ? [] : "" - }), - from_date: "", - to_date: "" - }, onSubmit: (values, {setSubmitting}) => { + enableReinitialize: true, + initialValues: stepValue, onSubmit: (values, {setSubmitting}) => { + setStepValue(values) const province = values.province_id; const fields = [ values.from_date ? {key: "from_date", value: values.from_date} : null, @@ -39,28 +58,54 @@ const Filter = ({title, filterItem, setFilterOption}) => { : [] ), ].filter(Boolean); - console.log("fields", fields) setFilterOption(fields) - setSubmitting(false) }, }); + + useEffect(() => { + const province = formik.values.province_id; + const fields = [ + formik.values.from_date ? {key: "from_date", value: formik.values.from_date} : null, + formik.values.to_date ? {key: "to_date", value: formik.values.to_date} : null, + ...(Array.isArray(province) + ? province.length !== 0 + ? province.map((item, index) => ({key: `province_id[${index}]`, value: item})) + : [] + : province + ? [{key: "province_id", value: province}] + : [] + ), + ].filter(Boolean); + setFilterOption(fields) + }, []); + return ( - { + }} sx={{ mb: 2, borderBottom: 2, borderBottomColor: "divider", - backgroundColor: "#f1f1f1" + backgroundColor: "#f1f1f1", }}> - + - دریافت گزارش تکمیلی + {title} {filteredText.province} {filteredText.year} - + + mutate()} + size="small"> + + + setExpanded((prevExpanded) => !prevExpanded)} + size="small"> + + + @@ -76,12 +121,13 @@ const Filter = ({title, filterItem, setFilterOption}) => { - ) }; diff --git a/src/components/dashboard/reports/LoanDetails/index.jsx b/src/components/dashboard/reports/LoanDetails/index.jsx index 111535b..aaf5090 100644 --- a/src/components/dashboard/reports/LoanDetails/index.jsx +++ b/src/components/dashboard/reports/LoanDetails/index.jsx @@ -1,6 +1,5 @@ import {Grid, Paper} from "@mui/material"; import {useTranslations} from "next-intl"; -import Filter from "@/components/dashboard/reports/Filter"; import RadialBarSemiCircularChart from "@/components/dashboard/reports/LoanDetails/RadialBarSemiCircularChart"; import RadialBarStrokedChart from "@/components/dashboard/reports/LoanDetails/RadialBarStrokedChart"; @@ -9,12 +8,14 @@ const LoanDetails = () => { const t = useTranslations(); return ( - + {/**/} diff --git a/src/components/dashboard/reports/LoanDistribution/index.jsx b/src/components/dashboard/reports/LoanDistribution/index.jsx index 9872291..1bf2abb 100644 --- a/src/components/dashboard/reports/LoanDistribution/index.jsx +++ b/src/components/dashboard/reports/LoanDistribution/index.jsx @@ -8,8 +8,7 @@ import {GET_LOAN_DISTRIBUTION} from "@/core/data/apiRoutes"; const LoanDistribution = () => { const t = useTranslations(); - const {errorReportList, isLoadingReportList, reportList, setFilterOption} = useChart(GET_LOAN_DISTRIBUTION); - + const {errorReportList, isLoadingReportList, reportList, setFilterOption, mutate} = useChart(GET_LOAN_DISTRIBUTION); return ( { {type: "year", type_fa: "سال", multiple: false} ]} setFilterOption={setFilterOption} + isLoadingReportList={isLoadingReportList} + mutate={mutate} /> {isLoadingReportList ? ( diff --git a/src/components/dashboard/reports/LoanProgress/index.jsx b/src/components/dashboard/reports/LoanProgress/index.jsx index 7bc6a35..0c7bf11 100644 --- a/src/components/dashboard/reports/LoanProgress/index.jsx +++ b/src/components/dashboard/reports/LoanProgress/index.jsx @@ -7,7 +7,7 @@ import {GET_PROVINCE_PROGRESS} from "@/core/data/apiRoutes"; const LoanProgress = () => { const t = useTranslations(); - const {errorReportList, isLoadingReportList, reportList, setFilterOption} = useChart(GET_PROVINCE_PROGRESS); + const {errorReportList, isLoadingReportList, reportList, setFilterOption, mutate} = useChart(GET_PROVINCE_PROGRESS); return ( { {type: "year", type_fa: "سال", multiple: false} ]} setFilterOption={setFilterOption} + isLoadingReportList={isLoadingReportList} + mutate={mutate} /> diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index f7025ee..7ca5fca 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -199,7 +199,7 @@ export const GET_PERMISSIONS_LIST = //role management // reports -export const GET_EXPORTS = BASE_URL + "/dashboard/exports/navgan" +export const GET_EXPORT = BASE_URL + "/dashboard/exports/navgan" export const GET_PROVINCE_PROGRESS = BASE_URL + "/dashboard/reports/navgan/province_progress" export const GET_LOAN_DISTRIBUTION = BASE_URL + "/dashboard/reports/navgan/loan_distribution" // reports diff --git a/src/core/utils/yearPeriodFinder.js b/src/core/utils/yearPeriodFinder.js new file mode 100644 index 0000000..73c01b9 --- /dev/null +++ b/src/core/utils/yearPeriodFinder.js @@ -0,0 +1,11 @@ +import moment from "jalali-moment"; + +export const periodOfYear = (year) => { + const isLeapYear = moment.jIsLeapYear(year); + const firstDayGeorgian = moment.from(`${year}/01/01`, 'fa').format('YYYY-MM-DD'); + const lastDayGeorgian = moment.from(`${year}/12/${isLeapYear ? '30' : '29'}`, 'fa').format('YYYY-MM-DD'); + return { + from: firstDayGeorgian, + to: lastDayGeorgian + } +} \ No newline at end of file diff --git a/src/lib/app/hooks/useChart.jsx b/src/lib/app/hooks/useChart.jsx index c010a03..707f21d 100644 --- a/src/lib/app/hooks/useChart.jsx +++ b/src/lib/app/hooks/useChart.jsx @@ -8,7 +8,6 @@ const useChart = (chart_url) => { const queryString = filterOption.length !== 0 ? `?${filterOption.map((option) => `${option.key}=${option.value}`).join('&')}` : ''; - console.log("check query", queryString) //swr config const fetcher = (...args) => { return requestServer(args, 'get').then(({data}) => { @@ -17,17 +16,23 @@ const useChart = (chart_url) => { }) }; - const {data, isLoading} = useSWR(`${chart_url}${queryString}`, fetcher, { + const { + data, + isValidating, + mutate + } = useSWR(filterOption.length !== 0 ? `${chart_url}${queryString}` : "", fetcher, { revalidateIfStale: false, revalidateOnFocus: false, - revalidateOnReconnect: false + revalidateOnReconnect: false, + keepPreviousData: true }); return { reportList: data, - isLoadingReportList: isLoading, + isLoadingReportList: isValidating, errorReportList: !data, - setFilterOption: setFilterOption + setFilterOption: setFilterOption, + mutate: mutate } }; diff --git a/src/lib/app/hooks/useProvince.jsx b/src/lib/app/hooks/useProvince.jsx index d0fbda0..3443a6e 100644 --- a/src/lib/app/hooks/useProvince.jsx +++ b/src/lib/app/hooks/useProvince.jsx @@ -16,7 +16,8 @@ const useProvince = () => { const {data, isLoading} = useSWR(GET_PROVINCE_LIST, fetcher, { revalidateIfStale: false, revalidateOnFocus: false, - revalidateOnReconnect: false + revalidateOnReconnect: false, + keepPreviousData: true }); return { diff --git a/src/lib/app/hooks/useRole.jsx b/src/lib/app/hooks/useRole.jsx index fc3dd18..b4c231c 100644 --- a/src/lib/app/hooks/useRole.jsx +++ b/src/lib/app/hooks/useRole.jsx @@ -16,7 +16,8 @@ const useRole = () => { const {data, isLoading} = useSWR(GET_ROLE_LIST, fetcher, { revalidateIfStale: false, revalidateOnFocus: false, - revalidateOnReconnect: false + revalidateOnReconnect: false, + keepPreviousData: true }); return { From fd3f99f93e7043d8c13e0d723d3ef9fdf59877f2 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Wed, 15 Nov 2023 09:52:09 +0330 Subject: [PATCH 12/17] LFFE-10 complete excel and working on loading --- .../dashboard/reports/ExcelExport/index.jsx | 8 +++++-- .../dashboard/reports/LoanProgress/index.jsx | 24 +++++++------------ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/components/dashboard/reports/ExcelExport/index.jsx b/src/components/dashboard/reports/ExcelExport/index.jsx index 2ab8e35..f095cc7 100644 --- a/src/components/dashboard/reports/ExcelExport/index.jsx +++ b/src/components/dashboard/reports/ExcelExport/index.jsx @@ -1,6 +1,7 @@ import {Accordion, AccordionDetails, AccordionSummary, Box, Button, Stack, Typography} from "@mui/material"; import FileUploadIcon from '@mui/icons-material/FileUpload'; import AssignmentIcon from '@mui/icons-material/Assignment'; +import BackupIcon from '@mui/icons-material/Backup'; import {useTranslations} from "next-intl"; import ProvinceFilter from "@/components/dashboard/reports/Filter/ProvinceFilter"; import YearFilter from "@/components/dashboard/reports/Filter/YearFilter"; @@ -10,6 +11,7 @@ import {GET_EXPORT} from "@/core/data/apiRoutes"; import moment from "jalali-moment"; import FileSaver from 'file-saver'; import useRequest from "@/lib/app/hooks/useRequest"; +import {periodOfYear} from "@/core/utils/yearPeriodFinder"; const ExcelExport = () => { const t = useTranslations(); @@ -31,8 +33,8 @@ const ExcelExport = () => { ...(filter_by_province && { province_id: filter_by_province.multiple ? [] : "" }), - from_date: "", - to_date: "" + from_date: periodOfYear(moment().format('jYYYY')).from, + to_date: periodOfYear(moment().format('jYYYY')).to }, onSubmit: (values, {setSubmitting}) => { const province = values.province_id; const fields = [ @@ -50,6 +52,7 @@ const ExcelExport = () => { const queryString = fields.length !== 0 ? `?${fields.map((option) => `${option.key}=${option.value}`).join('&')}` : ''; + setSubmitting(true) requestServer(`${GET_EXPORT}${queryString}`, 'GET', {auth: true, requestOptions: {responseType: 'blob'}}) .then((response) => { const filename = `گزارش درخواست های وام ناوگان تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`; @@ -97,6 +100,7 @@ const ExcelExport = () => { diff --git a/src/components/dashboard/reports/LoanProgress/index.jsx b/src/components/dashboard/reports/LoanProgress/index.jsx index 0c7bf11..a516d04 100644 --- a/src/components/dashboard/reports/LoanProgress/index.jsx +++ b/src/components/dashboard/reports/LoanProgress/index.jsx @@ -1,9 +1,10 @@ -import {Box, CircularProgress, Grid, Paper, Typography} from "@mui/material"; +import {Grid, Paper, Typography} from "@mui/material"; import BarChart from "./BarChart"; import Filter from "../Filter"; import {useTranslations} from "next-intl"; import useChart from "@/lib/app/hooks/useChart"; import {GET_PROVINCE_PROGRESS} from "@/core/data/apiRoutes"; +import LoadingHardPage from "@/core/components/LoadingHardPage"; const LoanProgress = () => { const t = useTranslations(); @@ -21,21 +22,12 @@ const LoanProgress = () => { {isLoadingReportList ? ( - - - - {t("reports.loading_fetching_reports")} - - - ) : errorReportList ? ( + // + + ) : errorReportList ? ( {t("reports.error_fetching_reports")} ) : ( From e928e0aa412bf88db2227557476484dc46aaad67 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Wed, 15 Nov 2023 14:27:23 +0330 Subject: [PATCH 13/17] LFFE-10 complete chart page of loan --- public/locales/fa/app.json | 4 +- .../dashboard/reports/ExcelExport/index.jsx | 29 +++++++++-- .../reports/Filter/ProvinceFilter.jsx | 2 +- .../dashboard/reports/Filter/YearFilter.jsx | 2 +- .../dashboard/reports/Filter/index.jsx | 29 +++++++---- .../reports/LoanDistribution/index.jsx | 44 ++++++++-------- .../dashboard/reports/LoanProgress/index.jsx | 50 ++++++++++++++----- src/lib/app/hooks/useChart.jsx | 2 +- 8 files changed, 110 insertions(+), 52 deletions(-) diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index b36f081..12a1600 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -523,8 +523,10 @@ "years": "سال های", "text_field_loading_provinces_list": "درحال دریافت استان ها", "text_field_error_fetching_provinces": "خطا در دریافت استان ها", + "filter_btn": "فیلتر", "filter": "اعمال فیلتر", "excel_export": "خروجی به اکسل", - "export": "دریافت" + "export": "دریافت", + "update_again": "بروزرسانی مجدد" } } diff --git a/src/components/dashboard/reports/ExcelExport/index.jsx b/src/components/dashboard/reports/ExcelExport/index.jsx index f095cc7..472d8b8 100644 --- a/src/components/dashboard/reports/ExcelExport/index.jsx +++ b/src/components/dashboard/reports/ExcelExport/index.jsx @@ -1,4 +1,13 @@ -import {Accordion, AccordionDetails, AccordionSummary, Box, Button, Stack, Typography} from "@mui/material"; +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + Button, + CircularProgress, + Stack, + Typography +} from "@mui/material"; import FileUploadIcon from '@mui/icons-material/FileUpload'; import AssignmentIcon from '@mui/icons-material/Assignment'; import BackupIcon from '@mui/icons-material/Backup'; @@ -53,7 +62,11 @@ const ExcelExport = () => { ? `?${fields.map((option) => `${option.key}=${option.value}`).join('&')}` : ''; setSubmitting(true) - requestServer(`${GET_EXPORT}${queryString}`, 'GET', {auth: true, requestOptions: {responseType: 'blob'}}) + requestServer(`${GET_EXPORT}${queryString}`, 'GET', { + auth: true, + notification: false, + requestOptions: {responseType: 'blob'} + }) .then((response) => { const filename = `گزارش درخواست های وام ناوگان تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`; FileSaver.saveAs(response.data, filename); @@ -85,7 +98,13 @@ const ExcelExport = () => { + sx={{ + display: "flex", + flexDirection: {xs: "column", sm: "row"}, + justifyContent: "space-between", + alignItems: "center", + mx: "auto", + }}> {filter_by_province ? { diff --git a/src/components/dashboard/reports/Filter/ProvinceFilter.jsx b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx index 16a1133..7dacacc 100644 --- a/src/components/dashboard/reports/Filter/ProvinceFilter.jsx +++ b/src/components/dashboard/reports/Filter/ProvinceFilter.jsx @@ -47,7 +47,7 @@ const ProvinceFilter = ({formik, multiple, setFilteredText}) => { ? formik.values.province_id.length === 0 : formik.values.province_id === ""; return ( - + {t("filters.choose_province")} { const t = useTranslations(); const filter_by_province = filterItem.find((item) => item.type === "province"); @@ -97,18 +97,27 @@ const Filter = ({title, filterItem, setFilterOption, isLoadingReportList, mutate - mutate()} - size="small"> - - - setExpanded((prevExpanded) => !prevExpanded)} - size="small"> - - + + mutate()} + size="small"> + + + + + setExpanded((prevExpanded) => !prevExpanded)} + size="small"> + + + - + {filter_by_province ? { const t = useTranslations(); @@ -20,34 +22,32 @@ const LoanDistribution = () => { isLoadingReportList={isLoadingReportList} mutate={mutate} /> - + {isLoadingReportList ? ( - - - - - {t("reports.loading_fetching_reports")} - - - + + } + loading={isLoadingReportList} + label={t("reports.loading_fetching_reports")} + width={100} + height={100} + sx={{position: "absolute", bgcolor: "#f7f7f7e6"}} + /> + ) : errorReportList ? ( - - {t("reports.error_fetching_reports")} + + {t("reports.error_fetching_reports")} ) : ( <> - + - + diff --git a/src/components/dashboard/reports/LoanProgress/index.jsx b/src/components/dashboard/reports/LoanProgress/index.jsx index a516d04..dadac1e 100644 --- a/src/components/dashboard/reports/LoanProgress/index.jsx +++ b/src/components/dashboard/reports/LoanProgress/index.jsx @@ -5,6 +5,7 @@ import {useTranslations} from "next-intl"; import useChart from "@/lib/app/hooks/useChart"; import {GET_PROVINCE_PROGRESS} from "@/core/data/apiRoutes"; import LoadingHardPage from "@/core/components/LoadingHardPage"; +import AnalyticsIcon from '@mui/icons-material/Analytics'; const LoanProgress = () => { const t = useTranslations(); @@ -20,19 +21,44 @@ const LoanProgress = () => { mutate={mutate} /> - - {isLoadingReportList ? ( - // - - ) : errorReportList ? ( - {t("reports.error_fetching_reports")} - ) : ( + {isLoadingReportList ? ( + + } + loading={isLoadingReportList} + label={t("reports.loading_fetching_reports")} + width={100} + height={100} + sx={{position: "absolute", bgcolor: "#f7f7f7e6"}} + /> + + ) : errorReportList ? ( + + {t("reports.error_fetching_reports")} + + ) : ( + - )} - + + )} ) diff --git a/src/lib/app/hooks/useChart.jsx b/src/lib/app/hooks/useChart.jsx index 707f21d..d1dd454 100644 --- a/src/lib/app/hooks/useChart.jsx +++ b/src/lib/app/hooks/useChart.jsx @@ -21,7 +21,7 @@ const useChart = (chart_url) => { isValidating, mutate } = useSWR(filterOption.length !== 0 ? `${chart_url}${queryString}` : "", fetcher, { - revalidateIfStale: false, + revalidateIfStale: true, revalidateOnFocus: false, revalidateOnReconnect: false, keepPreviousData: true From 656b01f82aa2e228af12e05681534975f07d0a09 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Sat, 18 Nov 2023 10:50:56 +0330 Subject: [PATCH 14/17] LFFE-10 complete responsive part of charts --- .../dashboard/reports/LoanDistribution/PieChart.jsx | 8 ++++++++ .../dashboard/reports/LoanDistribution/PolarChart.jsx | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx index 8b26443..4475355 100644 --- a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx @@ -1,6 +1,11 @@ import Chart from "@/core/components/Chart"; +import {useTheme} from "@mui/material/styles"; + const Pie = ({data}) => { + const theme = useTheme(); + const windowsWidth = window.innerWidth; + console.log(windowsWidth <= theme.breakpoints.values.sm) const specialOption = { title: { text: undefined, @@ -16,6 +21,9 @@ const Pie = ({data}) => { fontWeight: 300, }, }, + legend: { + show: windowsWidth > theme.breakpoints.values.sm + } }; const series = data.map((item) => +item.percentage) return ( diff --git a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx index 974f93d..b821cec 100644 --- a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx @@ -1,6 +1,10 @@ import Chart from "@/core/components/Chart"; +import {useTheme} from "@mui/material/styles"; const PolarChart = ({data}) => { + const theme = useTheme(); + const windowsWidth = window.innerWidth; + console.log(windowsWidth <= theme.breakpoints.values.sm) const specialOption = { title: { text: undefined, @@ -24,6 +28,9 @@ const PolarChart = ({data}) => { fontWeight: 400, }, }, + legend: { + show: windowsWidth > theme.breakpoints.values.sm + } }; const series = data.map((item) => +item.percentage) return ( From 1f7d07859424aa5e3a5225cb502a248be4a98093 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Sat, 18 Nov 2023 11:00:17 +0330 Subject: [PATCH 15/17] LFFE-10 remove logs --- src/components/dashboard/reports/LoanDistribution/PieChart.jsx | 1 - src/components/dashboard/reports/LoanDistribution/PolarChart.jsx | 1 - 2 files changed, 2 deletions(-) diff --git a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx index 4475355..b2908c0 100644 --- a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx @@ -5,7 +5,6 @@ import {useTheme} from "@mui/material/styles"; const Pie = ({data}) => { const theme = useTheme(); const windowsWidth = window.innerWidth; - console.log(windowsWidth <= theme.breakpoints.values.sm) const specialOption = { title: { text: undefined, diff --git a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx index b821cec..01e4286 100644 --- a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx @@ -4,7 +4,6 @@ import {useTheme} from "@mui/material/styles"; const PolarChart = ({data}) => { const theme = useTheme(); const windowsWidth = window.innerWidth; - console.log(windowsWidth <= theme.breakpoints.values.sm) const specialOption = { title: { text: undefined, From 2e823e7ade2bd2ae7988ca5a2d733138509b0a30 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Sat, 18 Nov 2023 11:07:24 +0330 Subject: [PATCH 16/17] LFFE-10 responsive debug --- .../dashboard/reports/LoanDistribution/PieChart.jsx | 5 +++-- .../dashboard/reports/LoanDistribution/PolarChart.jsx | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx index b2908c0..9da086e 100644 --- a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx @@ -1,10 +1,11 @@ import Chart from "@/core/components/Chart"; import {useTheme} from "@mui/material/styles"; +import {useMediaQuery} from "@mui/material"; const Pie = ({data}) => { const theme = useTheme(); - const windowsWidth = window.innerWidth; + const upperSm = useMediaQuery((theme.breakpoints.up("sm"))) const specialOption = { title: { text: undefined, @@ -21,7 +22,7 @@ const Pie = ({data}) => { }, }, legend: { - show: windowsWidth > theme.breakpoints.values.sm + show: upperSm } }; const series = data.map((item) => +item.percentage) diff --git a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx index 01e4286..2b62915 100644 --- a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx @@ -1,9 +1,10 @@ import Chart from "@/core/components/Chart"; import {useTheme} from "@mui/material/styles"; +import {useMediaQuery} from "@mui/material"; const PolarChart = ({data}) => { const theme = useTheme(); - const windowsWidth = window.innerWidth; + const upperSm = useMediaQuery((theme.breakpoints.up("sm"))) const specialOption = { title: { text: undefined, @@ -28,7 +29,7 @@ const PolarChart = ({data}) => { }, }, legend: { - show: windowsWidth > theme.breakpoints.values.sm + show: upperSm } }; const series = data.map((item) => +item.percentage) From 3b8d2b8d017b2a5bd9d85fca23ac8e5e45e16f14 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Sat, 18 Nov 2023 11:08:51 +0330 Subject: [PATCH 17/17] LFFE-10 responsive debug --- .../dashboard/reports/LoanDistribution/PieChart.jsx | 4 ++-- .../dashboard/reports/LoanDistribution/PolarChart.jsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx index 9da086e..1ce3242 100644 --- a/src/components/dashboard/reports/LoanDistribution/PieChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PieChart.jsx @@ -5,7 +5,7 @@ import {useMediaQuery} from "@mui/material"; const Pie = ({data}) => { const theme = useTheme(); - const upperSm = useMediaQuery((theme.breakpoints.up("sm"))) + const upperMd = useMediaQuery((theme.breakpoints.up("md"))) const specialOption = { title: { text: undefined, @@ -22,7 +22,7 @@ const Pie = ({data}) => { }, }, legend: { - show: upperSm + show: upperMd } }; const series = data.map((item) => +item.percentage) diff --git a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx index 2b62915..d6b73ff 100644 --- a/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx +++ b/src/components/dashboard/reports/LoanDistribution/PolarChart.jsx @@ -4,7 +4,7 @@ import {useMediaQuery} from "@mui/material"; const PolarChart = ({data}) => { const theme = useTheme(); - const upperSm = useMediaQuery((theme.breakpoints.up("sm"))) + const upperMd = useMediaQuery((theme.breakpoints.up("md"))) const specialOption = { title: { text: undefined, @@ -29,7 +29,7 @@ const PolarChart = ({data}) => { }, }, legend: { - show: upperSm + show: upperMd } }; const series = data.map((item) => +item.percentage)