From f5af09cc508c9e2a2b283f9753884d8e40df2927 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Sat, 4 Nov 2023 15:20:22 +0330 Subject: [PATCH 01/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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) From 182499cd5db118b7838635ba19bacba5b2f1587c Mon Sep 17 00:00:00 2001 From: AmirHossein Mahmoodi Date: Sat, 18 Nov 2023 11:17:24 +0330 Subject: [PATCH 18/32] LFFE-28 Fixed bug sidebar in mobile --- src/components/layouts/Dashboard/Sidebar/SidebarListItem.jsx | 1 + .../layouts/Dashboard/Sidebar/SidebarListSubItem.jsx | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/components/layouts/Dashboard/Sidebar/SidebarListItem.jsx b/src/components/layouts/Dashboard/Sidebar/SidebarListItem.jsx index 81fd444..fffd570 100644 --- a/src/components/layouts/Dashboard/Sidebar/SidebarListItem.jsx +++ b/src/components/layouts/Dashboard/Sidebar/SidebarListItem.jsx @@ -51,6 +51,7 @@ const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => { if (hasSubItems) { dispatch({type: "COLLAPSE_MENU", key: item.key}); } + handleDrawerToggle() }} sx={{ minHeight: 48, diff --git a/src/components/layouts/Dashboard/Sidebar/SidebarListSubItem.jsx b/src/components/layouts/Dashboard/Sidebar/SidebarListSubItem.jsx index 3ef8731..41bff6d 100644 --- a/src/components/layouts/Dashboard/Sidebar/SidebarListSubItem.jsx +++ b/src/components/layouts/Dashboard/Sidebar/SidebarListSubItem.jsx @@ -43,6 +43,9 @@ const SidebarListSubItem = ({item, handleDrawerToggle}) => { to={{ pathname: subitem.route, }} + onClick={() => { + handleDrawerToggle() + }} sx={{ minHeight: 48, }} From a1d9cb7f97c25b7ad5982bb1148b685bfc98a714 Mon Sep 17 00:00:00 2001 From: AmirHossein Mahmoodi Date: Sat, 18 Nov 2023 11:57:47 +0330 Subject: [PATCH 19/32] Fixed any bug --- public/locales/fa/app.json | 2 +- src/core/data/sidebarMenu.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 12a1600..8de5762 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -7,7 +7,7 @@ "login": "ورود", "login_expert": "ورود کارشناس", "expert": "کارشناس", - "last_updated_at": "اخرین بروز رسانی", + "last_updated_at": "آخرین بروزرسانی", "filter_mode": "حالت فیلتر", "date_picker_label": "فیلتر بر اساس تاریخ", "lessThan": "کوچکتر از", diff --git a/src/core/data/sidebarMenu.jsx b/src/core/data/sidebarMenu.jsx index 09b81da..029ca26 100644 --- a/src/core/data/sidebarMenu.jsx +++ b/src/core/data/sidebarMenu.jsx @@ -30,7 +30,7 @@ const sidebarMenu = [ name: "reports", type: "page", route: "/dashboard/reports", - icon: , + icon: , selected: false, permission: "all", }, From d6e8c93b88b3563f2070712d52a2e011e0c949d5 Mon Sep 17 00:00:00 2001 From: AminGhasempoor Date: Sat, 18 Nov 2023 13:53:41 +0330 Subject: [PATCH 20/32] LFFE-26 excel report output for passenger office --- public/locales/fa/app.json | 3 +- .../passenger-office/Buttons/printReport.jsx | 68 +++++++++++++++++++ .../passenger-office/TableToolbar.jsx | 13 ++++ .../dashboard/passenger-office/index.jsx | 4 +- src/core/components/DataTable.jsx | 1 + src/core/data/apiRoutes.js | 3 + 6 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/components/dashboard/passenger-office/Buttons/printReport.jsx create mode 100644 src/components/dashboard/passenger-office/TableToolbar.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 12a1600..97a43fc 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -170,7 +170,8 @@ "state_name": "وضعیت درخواست", "confirm": "ارجاع به کارشناس ماشین آلات", "upload_file_unit": "فایل بارگذاری شده باید حداکثر 2Mb باشد", - "upload_file_format": "فرمت قابل قبول : png,jpg,pdf" + "upload_file_format": "فرمت قابل قبول : png,jpg,pdf", + "excel_report": "گزارش اکسل" }, "CommercialChief": { "name": "نام", diff --git a/src/components/dashboard/passenger-office/Buttons/printReport.jsx b/src/components/dashboard/passenger-office/Buttons/printReport.jsx new file mode 100644 index 0000000..8917799 --- /dev/null +++ b/src/components/dashboard/passenger-office/Buttons/printReport.jsx @@ -0,0 +1,68 @@ +import {Button, CircularProgress} from "@mui/material"; +import {useTranslations} from "next-intl"; +import {useMemo, useState} from "react"; +import useRequest from "@/lib/app/hooks/useRequest"; +import {EXPORT_PASSENGER_OFFICE} from "@/core/data/apiRoutes"; +import moment from "jalali-moment"; +import FileSaver from 'file-saver'; +import TableChartIcon from '@mui/icons-material/TableChart'; + +const PrintReport = ({table}) => { + const t = useTranslations(); + const [loading, setLoading] = useState(false) + const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}}) + const {columnFilters, columnFilterFns, sorting} = table.getState() + const columns = table.getAllColumns() + + const fetchUrl = useMemo(() => { + const params = new URLSearchParams(); + const filters = columnFilters.map((filter) => { + let datatype; + for (const i in columns) { + if (columns[i].id == filter.id) { + datatype = columns[i].columnDef.datatype; + } + } + return { + ...filter, fn: columnFilterFns[filter.id], datatype: datatype, + }; + }); + params.set("start", '0'); + params.set("filters", JSON.stringify(filters ?? [])); + params.set("sorting", JSON.stringify(sorting ?? [])); + return params; + }, [columnFilters, columnFilterFns, sorting, columns,]); + + + const clickHandler = () => { + setLoading(true) + requestServer(`${EXPORT_PASSENGER_OFFICE}?${fetchUrl}`, 'get', { + auth: true, + notification: false, + requestOptions: {responseType: 'blob'} + }).then((response) => { + const filename = `گزارش اداره مسافر تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`; + FileSaver.saveAs(response.data, filename); + }).catch(() => { + }).finally(() => { + setLoading(false) + }) + } + + + return ( + + ) +} + +export default PrintReport \ No newline at end of file diff --git a/src/components/dashboard/passenger-office/TableToolbar.jsx b/src/components/dashboard/passenger-office/TableToolbar.jsx new file mode 100644 index 0000000..98a3821 --- /dev/null +++ b/src/components/dashboard/passenger-office/TableToolbar.jsx @@ -0,0 +1,13 @@ +import {Stack} from "@mui/material"; +import PrintReport from "@/components/dashboard/passenger-office/Buttons/printReport"; + +const TableToolbar = ({table}) => { + + return ( + + + + ) +} + +export default TableToolbar \ No newline at end of file diff --git a/src/components/dashboard/passenger-office/index.jsx b/src/components/dashboard/passenger-office/index.jsx index b8292a0..1e4f705 100644 --- a/src/components/dashboard/passenger-office/index.jsx +++ b/src/components/dashboard/passenger-office/index.jsx @@ -6,6 +6,7 @@ import TableRowActions from "./TableRowActions"; import moment from "jalali-moment"; import DataTable from "@/core/components/DataTable"; import MuiDatePicker from "@/core/components/MuiDatePicker"; +import TableToolbar from "@/components/dashboard/passenger-office/TableToolbar"; function DashboardPassengerOfficeComponent() { const t = useTranslations(); @@ -161,7 +162,8 @@ function DashboardPassengerOfficeComponent() { tableUrl={GET_PASSENGER_OFFICE} columns={columns} selectableRow={false} - enableCustomToolbar={false} + enableCustomToolbar={true} + CustomToolbar={TableToolbar} enableLastUpdate={true} sorting={[{ id: 'id', desc: false diff --git a/src/core/components/DataTable.jsx b/src/core/components/DataTable.jsx index ea3a117..8274f96 100644 --- a/src/core/components/DataTable.jsx +++ b/src/core/components/DataTable.jsx @@ -114,6 +114,7 @@ function DataTable(props) { renderTopToolbarCustomActions={({table}) => (<> {props.enableCustomToolbar /* send condition */ ? /* send component */ : } )} renderBottomToolbarCustomActions={({table}) => (<> diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index 7ca5fca..0922436 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -21,6 +21,9 @@ export const CONFIRM_PASSENGER_OFFICE = export const REJECT_PASSENGER_OFFICE = BASE_URL + "/dashboard/passenger_office_chief/reject"; + +export const EXPORT_PASSENGER_OFFICE = + BASE_URL + "/dashboard/passenger_office_chief/export" //passenger office //passenger boss From b62ca917cb6ba4c6f69878b215674fa166c30299 Mon Sep 17 00:00:00 2001 From: AminGhasempoor Date: Sat, 18 Nov 2023 14:03:34 +0330 Subject: [PATCH 21/32] LFFE-26 change icon --- .../dashboard/passenger-office/Buttons/printReport.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/dashboard/passenger-office/Buttons/printReport.jsx b/src/components/dashboard/passenger-office/Buttons/printReport.jsx index 8917799..041fe6a 100644 --- a/src/components/dashboard/passenger-office/Buttons/printReport.jsx +++ b/src/components/dashboard/passenger-office/Buttons/printReport.jsx @@ -5,7 +5,7 @@ import useRequest from "@/lib/app/hooks/useRequest"; import {EXPORT_PASSENGER_OFFICE} from "@/core/data/apiRoutes"; import moment from "jalali-moment"; import FileSaver from 'file-saver'; -import TableChartIcon from '@mui/icons-material/TableChart'; +import DescriptionIcon from '@mui/icons-material/Description'; const PrintReport = ({table}) => { const t = useTranslations(); @@ -57,7 +57,7 @@ const PrintReport = ({table}) => { size="small" disabled={loading} sx={{textTransform: "unset", alignSelf: "center"}} - startIcon={loading ? : } + startIcon={loading ? : } onClick={clickHandler} > {t("PassengerOffice.excel_report")} From a0e69e37fd44c8f00fcb43493ae52622d61139d0 Mon Sep 17 00:00:00 2001 From: AminGhasempoor Date: Mon, 20 Nov 2023 10:18:07 +0330 Subject: [PATCH 22/32] LFFE-26 report toolbar transportation assistance --- public/locales/fa/app.json | 3 +- .../passenger-office/Buttons/printReport.jsx | 4 +- .../Buttons/printReport.jsx | 68 +++++++++++++++++++ .../TableToolbar.jsx | 13 ++++ .../transportation-assistance/index.jsx | 4 +- src/core/data/apiRoutes.js | 2 + 6 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 src/components/dashboard/transportation-assistance/Buttons/printReport.jsx create mode 100644 src/components/dashboard/transportation-assistance/TableToolbar.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 97a43fc..82b5230 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -285,7 +285,8 @@ "state_name": "وضعیت درخواست", "confirm": "ارجاع به مدیر کل استانی", "upload_file_unit": "فایل بارگذاری شده باید حداکثر 2Mb باشد", - "upload_file_format": "فرمت قابل قبول : png,jpg,pdf" + "upload_file_format": "فرمت قابل قبول : png,jpg,pdf", + "excel_report": "گزارش اکسل" }, "InspectorExpert": { "name": "نام", diff --git a/src/components/dashboard/passenger-office/Buttons/printReport.jsx b/src/components/dashboard/passenger-office/Buttons/printReport.jsx index 041fe6a..74f4bcc 100644 --- a/src/components/dashboard/passenger-office/Buttons/printReport.jsx +++ b/src/components/dashboard/passenger-office/Buttons/printReport.jsx @@ -14,7 +14,7 @@ const PrintReport = ({table}) => { const {columnFilters, columnFilterFns, sorting} = table.getState() const columns = table.getAllColumns() - const fetchUrl = useMemo(() => { + const filterParams = useMemo(() => { const params = new URLSearchParams(); const filters = columnFilters.map((filter) => { let datatype; @@ -36,7 +36,7 @@ const PrintReport = ({table}) => { const clickHandler = () => { setLoading(true) - requestServer(`${EXPORT_PASSENGER_OFFICE}?${fetchUrl}`, 'get', { + requestServer(`${EXPORT_PASSENGER_OFFICE}?${filterParams}`, 'get', { auth: true, notification: false, requestOptions: {responseType: 'blob'} diff --git a/src/components/dashboard/transportation-assistance/Buttons/printReport.jsx b/src/components/dashboard/transportation-assistance/Buttons/printReport.jsx new file mode 100644 index 0000000..4185d29 --- /dev/null +++ b/src/components/dashboard/transportation-assistance/Buttons/printReport.jsx @@ -0,0 +1,68 @@ +import {Button, CircularProgress} from "@mui/material"; +import {useTranslations} from "next-intl"; +import {useMemo, useState} from "react"; +import useRequest from "@/lib/app/hooks/useRequest"; +import {EXPORT_TRANSPORTATION_ASSISTANCE} from "@/core/data/apiRoutes"; +import moment from "jalali-moment"; +import FileSaver from 'file-saver'; +import DescriptionIcon from '@mui/icons-material/Description'; + +const PrintReport = ({table}) => { + const t = useTranslations(); + const [loading, setLoading] = useState(false) + const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}}) + const {columnFilters, columnFilterFns, sorting} = table.getState() + const columns = table.getAllColumns() + + const filterParams = useMemo(() => { + const params = new URLSearchParams(); + const filters = columnFilters.map((filter) => { + let datatype; + for (const i in columns) { + if (columns[i].id == filter.id) { + datatype = columns[i].columnDef.datatype; + } + } + return { + ...filter, fn: columnFilterFns[filter.id], datatype: datatype, + }; + }); + params.set("start", '0'); + params.set("filters", JSON.stringify(filters ?? [])); + params.set("sorting", JSON.stringify(sorting ?? [])); + return params; + }, [columnFilters, columnFilterFns, sorting, columns,]); + + + const clickHandler = () => { + setLoading(true) + requestServer(`${EXPORT_TRANSPORTATION_ASSISTANCE}?${filterParams}`, 'get', { + auth: true, + notification: false, + requestOptions: {responseType: 'blob'} + }).then((response) => { + const filename = `گزارش معاونت حمل و نقل تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`; + FileSaver.saveAs(response.data, filename); + }).catch(() => { + }).finally(() => { + setLoading(false) + }) + } + + + return ( + + ) +} + +export default PrintReport \ No newline at end of file diff --git a/src/components/dashboard/transportation-assistance/TableToolbar.jsx b/src/components/dashboard/transportation-assistance/TableToolbar.jsx new file mode 100644 index 0000000..08de307 --- /dev/null +++ b/src/components/dashboard/transportation-assistance/TableToolbar.jsx @@ -0,0 +1,13 @@ +import {Stack} from "@mui/material"; +import PrintReport from "@/components/dashboard/transportation-assistance/Buttons/printReport"; + +const TableToolbar = ({table}) => { + + return ( + + + + ) +} + +export default TableToolbar \ No newline at end of file diff --git a/src/components/dashboard/transportation-assistance/index.jsx b/src/components/dashboard/transportation-assistance/index.jsx index 473837c..a1cdae0 100644 --- a/src/components/dashboard/transportation-assistance/index.jsx +++ b/src/components/dashboard/transportation-assistance/index.jsx @@ -6,6 +6,7 @@ import TableRowActions from "./TableRowActions"; import moment from "jalali-moment"; import DataTable from "@/core/components/DataTable"; import MuiDatePicker from "@/core/components/MuiDatePicker"; +import TableToolbar from "@/components/dashboard/transportation-assistance/TableToolbar"; function DashboardTransportationAssistanceComponent() { const t = useTranslations(); @@ -161,7 +162,8 @@ function DashboardTransportationAssistanceComponent() { tableUrl={GET_TRANSPORTATION_ASSISTANCE} columns={columns} selectableRow={false} - enableCustomToolbar={false} + enableCustomToolbar={true} + CustomToolbar={TableToolbar} enableLastUpdate={true} sorting={[{ id: 'id', desc: false diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index 0922436..0e6d724 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -46,6 +46,8 @@ export const CONFIRM_TRANSPORTATION_ASSISTANCE = export const REJECT_TRANSPORTATION_ASSISTANCE = BASE_URL + "/dashboard/transportation_assistant/reject"; +export const EXPORT_TRANSPORTATION_ASSISTANCE = + BASE_URL + "/dashboard/transportation_assistant/export"; //transportation assistance //machinary office From f973faffd9adc551a4c1effccaf79f74f46539c4 Mon Sep 17 00:00:00 2001 From: AminGhasempoor Date: Mon, 20 Nov 2023 10:32:00 +0330 Subject: [PATCH 23/32] LFFE-26 report toolbar machinary office --- public/locales/fa/app.json | 3 +- .../machinary-office/Buttons/printExcel.jsx | 68 +++++++++++++++++++ .../machinary-office/TableToolbar.jsx | 4 +- src/core/data/apiRoutes.js | 2 + 4 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 src/components/dashboard/machinary-office/Buttons/printExcel.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 82b5230..70bb147 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -315,7 +315,8 @@ "upload_file_unit": "فایل بارگذاری شده باید حداکثر 2Mb باشد", "upload_file_format": "فرمت قابل قبول : png,jpg,pdf", "print_report": "چاپ گزارش کارشناسی ماشین آلات", - "max_amount": "حداکثر مبلغ پیشنهادی {value} میلیون ریال می باشد" + "max_amount": "حداکثر مبلغ پیشنهادی {value} میلیون ریال می باشد", + "excel_report": "گزارش اکسل" }, "UserManagement": { "name": "نام", diff --git a/src/components/dashboard/machinary-office/Buttons/printExcel.jsx b/src/components/dashboard/machinary-office/Buttons/printExcel.jsx new file mode 100644 index 0000000..cba05a0 --- /dev/null +++ b/src/components/dashboard/machinary-office/Buttons/printExcel.jsx @@ -0,0 +1,68 @@ +import {Button, CircularProgress} from "@mui/material"; +import {useTranslations} from "next-intl"; +import {useMemo, useState} from "react"; +import useRequest from "@/lib/app/hooks/useRequest"; +import {EXPORT_MACHINARY_OFFICE} from "@/core/data/apiRoutes"; +import moment from "jalali-moment"; +import FileSaver from 'file-saver'; +import DescriptionIcon from '@mui/icons-material/Description'; + +const PrintExcel = ({table}) => { + const t = useTranslations(); + const [loading, setLoading] = useState(false) + const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}}) + const {columnFilters, columnFilterFns, sorting} = table.getState() + const columns = table.getAllColumns() + + const filterParams = useMemo(() => { + const params = new URLSearchParams(); + const filters = columnFilters.map((filter) => { + let datatype; + for (const i in columns) { + if (columns[i].id == filter.id) { + datatype = columns[i].columnDef.datatype; + } + } + return { + ...filter, fn: columnFilterFns[filter.id], datatype: datatype, + }; + }); + params.set("start", '0'); + params.set("filters", JSON.stringify(filters ?? [])); + params.set("sorting", JSON.stringify(sorting ?? [])); + return params; + }, [columnFilters, columnFilterFns, sorting, columns,]); + + + const clickHandler = () => { + setLoading(true) + requestServer(`${EXPORT_MACHINARY_OFFICE}?${filterParams}`, 'get', { + auth: true, + notification: false, + requestOptions: {responseType: 'blob'} + }).then((response) => { + const filename = `گزارش ماشین آلات تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`; + FileSaver.saveAs(response.data, filename); + }).catch(() => { + }).finally(() => { + setLoading(false) + }) + } + + + return ( + + ) +} + +export default PrintExcel \ No newline at end of file diff --git a/src/components/dashboard/machinary-office/TableToolbar.jsx b/src/components/dashboard/machinary-office/TableToolbar.jsx index 9704f95..cdf1562 100644 --- a/src/components/dashboard/machinary-office/TableToolbar.jsx +++ b/src/components/dashboard/machinary-office/TableToolbar.jsx @@ -1,10 +1,12 @@ import {Stack} from "@mui/material"; import PrintReport from "@/components/dashboard/machinary-office/Buttons/printReport"; +import PrintExcel from "@/components/dashboard/machinary-office/Buttons/printExcel"; -const TableToolbar = () => { +const TableToolbar = ({table}) => { return ( + ) } diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index 0e6d724..15c32a4 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -59,6 +59,8 @@ export const CONFIRM_MACHINARY_OFFICE = export const REJECT_MACHINARY_OFFICE = BASE_URL + "/dashboard/machinery_expert/reject"; +export const EXPORT_MACHINARY_OFFICE = + BASE_URL + "/dashboard/machinery_expert/export"; //machinary office //commercial chief From 22b879c40811e1c358c299f2c0d204e3abe51ca5 Mon Sep 17 00:00:00 2001 From: AminGhasempoor Date: Mon, 20 Nov 2023 10:39:07 +0330 Subject: [PATCH 24/32] LFFE-26 report toolbar passenger boss --- public/locales/fa/app.json | 3 +- .../passenger-boss/Buttons/printExcel.jsx | 68 +++++++++++++++++++ .../dashboard/passenger-boss/TableToolbar.jsx | 4 +- .../{printReport.jsx => printExcel.jsx} | 4 +- .../passenger-office/TableToolbar.jsx | 4 +- .../{printReport.jsx => printExcel.jsx} | 4 +- .../TableToolbar.jsx | 4 +- src/core/data/apiRoutes.js | 2 + 8 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 src/components/dashboard/passenger-boss/Buttons/printExcel.jsx rename src/components/dashboard/passenger-office/Buttons/{printReport.jsx => printExcel.jsx} (97%) rename src/components/dashboard/transportation-assistance/Buttons/{printReport.jsx => printExcel.jsx} (97%) diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 70bb147..aeb5a87 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -214,7 +214,8 @@ "upload_file_unit": "فایل بارگذاری شده باید حداکثر 2Mb باشد", "upload_file_format": "فرمت قابل قبول : png,jpg,pdf", "print_final_credit_amount": "چاپ صورت جلسه تعیین مبلغ نهایی", - "max_amount": "حداکثر مبلغ تصویب شده {value} میلیون ریال می باشد" + "max_amount": "حداکثر مبلغ تصویب شده {value} میلیون ریال می باشد", + "excel_report": "گزارش اکسل" }, "RefahiProvinceManager": { "name": "نام", diff --git a/src/components/dashboard/passenger-boss/Buttons/printExcel.jsx b/src/components/dashboard/passenger-boss/Buttons/printExcel.jsx new file mode 100644 index 0000000..d04f129 --- /dev/null +++ b/src/components/dashboard/passenger-boss/Buttons/printExcel.jsx @@ -0,0 +1,68 @@ +import {Button, CircularProgress} from "@mui/material"; +import {useTranslations} from "next-intl"; +import {useMemo, useState} from "react"; +import useRequest from "@/lib/app/hooks/useRequest"; +import {EXPORT_PASSENGER_BOSS} from "@/core/data/apiRoutes"; +import moment from "jalali-moment"; +import FileSaver from 'file-saver'; +import DescriptionIcon from '@mui/icons-material/Description'; + +const PrintExcel = ({table}) => { + const t = useTranslations(); + const [loading, setLoading] = useState(false) + const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}}) + const {columnFilters, columnFilterFns, sorting} = table.getState() + const columns = table.getAllColumns() + + const filterParams = useMemo(() => { + const params = new URLSearchParams(); + const filters = columnFilters.map((filter) => { + let datatype; + for (const i in columns) { + if (columns[i].id == filter.id) { + datatype = columns[i].columnDef.datatype; + } + } + return { + ...filter, fn: columnFilterFns[filter.id], datatype: datatype, + }; + }); + params.set("start", '0'); + params.set("filters", JSON.stringify(filters ?? [])); + params.set("sorting", JSON.stringify(sorting ?? [])); + return params; + }, [columnFilters, columnFilterFns, sorting, columns,]); + + + const clickHandler = () => { + setLoading(true) + requestServer(`${EXPORT_PASSENGER_BOSS}?${filterParams}`, 'get', { + auth: true, + notification: false, + requestOptions: {responseType: 'blob'} + }).then((response) => { + const filename = `گزارش کارگروه استانی تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`; + FileSaver.saveAs(response.data, filename); + }).catch(() => { + }).finally(() => { + setLoading(false) + }) + } + + + return ( + + ) +} + +export default PrintExcel \ No newline at end of file diff --git a/src/components/dashboard/passenger-boss/TableToolbar.jsx b/src/components/dashboard/passenger-boss/TableToolbar.jsx index ed224f4..91db1f3 100644 --- a/src/components/dashboard/passenger-boss/TableToolbar.jsx +++ b/src/components/dashboard/passenger-boss/TableToolbar.jsx @@ -1,10 +1,12 @@ import {Stack} from "@mui/material"; import PrintFinalCreditAmount from "@/components/dashboard/passenger-boss/Buttons/printFinalCreditAmount"; +import PrintExcel from "@/components/dashboard/passenger-boss/Buttons/printExcel"; -const TableToolbar = () => { +const TableToolbar = ({table}) => { return ( + ) } diff --git a/src/components/dashboard/passenger-office/Buttons/printReport.jsx b/src/components/dashboard/passenger-office/Buttons/printExcel.jsx similarity index 97% rename from src/components/dashboard/passenger-office/Buttons/printReport.jsx rename to src/components/dashboard/passenger-office/Buttons/printExcel.jsx index 74f4bcc..c78075a 100644 --- a/src/components/dashboard/passenger-office/Buttons/printReport.jsx +++ b/src/components/dashboard/passenger-office/Buttons/printExcel.jsx @@ -7,7 +7,7 @@ import moment from "jalali-moment"; import FileSaver from 'file-saver'; import DescriptionIcon from '@mui/icons-material/Description'; -const PrintReport = ({table}) => { +const PrintExcel = ({table}) => { const t = useTranslations(); const [loading, setLoading] = useState(false) const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}}) @@ -65,4 +65,4 @@ const PrintReport = ({table}) => { ) } -export default PrintReport \ No newline at end of file +export default PrintExcel \ No newline at end of file diff --git a/src/components/dashboard/passenger-office/TableToolbar.jsx b/src/components/dashboard/passenger-office/TableToolbar.jsx index 98a3821..23f3c20 100644 --- a/src/components/dashboard/passenger-office/TableToolbar.jsx +++ b/src/components/dashboard/passenger-office/TableToolbar.jsx @@ -1,11 +1,11 @@ import {Stack} from "@mui/material"; -import PrintReport from "@/components/dashboard/passenger-office/Buttons/printReport"; +import PrintExcel from "@/components/dashboard/passenger-office/Buttons/printExcel"; const TableToolbar = ({table}) => { return ( - + ) } diff --git a/src/components/dashboard/transportation-assistance/Buttons/printReport.jsx b/src/components/dashboard/transportation-assistance/Buttons/printExcel.jsx similarity index 97% rename from src/components/dashboard/transportation-assistance/Buttons/printReport.jsx rename to src/components/dashboard/transportation-assistance/Buttons/printExcel.jsx index 4185d29..b74eecc 100644 --- a/src/components/dashboard/transportation-assistance/Buttons/printReport.jsx +++ b/src/components/dashboard/transportation-assistance/Buttons/printExcel.jsx @@ -7,7 +7,7 @@ import moment from "jalali-moment"; import FileSaver from 'file-saver'; import DescriptionIcon from '@mui/icons-material/Description'; -const PrintReport = ({table}) => { +const PrintExcel = ({table}) => { const t = useTranslations(); const [loading, setLoading] = useState(false) const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}}) @@ -65,4 +65,4 @@ const PrintReport = ({table}) => { ) } -export default PrintReport \ No newline at end of file +export default PrintExcel \ No newline at end of file diff --git a/src/components/dashboard/transportation-assistance/TableToolbar.jsx b/src/components/dashboard/transportation-assistance/TableToolbar.jsx index 08de307..1f7c2d2 100644 --- a/src/components/dashboard/transportation-assistance/TableToolbar.jsx +++ b/src/components/dashboard/transportation-assistance/TableToolbar.jsx @@ -1,11 +1,11 @@ import {Stack} from "@mui/material"; -import PrintReport from "@/components/dashboard/transportation-assistance/Buttons/printReport"; +import PrintExcel from "@/components/dashboard/transportation-assistance/Buttons/printExcel"; const TableToolbar = ({table}) => { return ( - + ) } diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index 15c32a4..69d404f 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -35,6 +35,8 @@ export const CONFIRM_PASSENGER_BOSS = export const REJECT_PASSENGER_BOSS = BASE_URL + "/dashboard/province_working_group/reject"; +export const EXPORT_PASSENGER_BOSS = + BASE_URL + "/dashboard/province_working_group/export"; //passenger boss //transportation assistance From 05009a222acf1e2e8f9890448bf39e591621c49f Mon Sep 17 00:00:00 2001 From: AminGhasempoor Date: Mon, 20 Nov 2023 10:47:39 +0330 Subject: [PATCH 25/32] LFFE-26 report toolbar navgan province manager --- public/locales/fa/app.json | 3 +- .../Buttons/printExcel.jsx | 68 +++++++++++++++++++ .../navgan-province-manager/TableToolbar.jsx | 13 ++++ .../navgan-province-manager/index.jsx | 4 +- src/core/data/apiRoutes.js | 2 + 5 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 src/components/dashboard/navgan-province-manager/Buttons/printExcel.jsx create mode 100644 src/components/dashboard/navgan-province-manager/TableToolbar.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index aeb5a87..e8683b3 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -196,7 +196,8 @@ "state_name": "وضعیت درخواست", "confirm": "تایید نهایی و ارجاع به بانک", "upload_file_unit": "فایل بارگذاری شده باید حداکثر 2Mb باشد", - "upload_file_format": "فرمت قابل قبول : png,jpg,pdf" + "upload_file_format": "فرمت قابل قبول : png,jpg,pdf", + "excel_report": "گزارش اکسل" }, "PassengerBoss": { "name": "نام", diff --git a/src/components/dashboard/navgan-province-manager/Buttons/printExcel.jsx b/src/components/dashboard/navgan-province-manager/Buttons/printExcel.jsx new file mode 100644 index 0000000..6c0aac3 --- /dev/null +++ b/src/components/dashboard/navgan-province-manager/Buttons/printExcel.jsx @@ -0,0 +1,68 @@ +import {Button, CircularProgress} from "@mui/material"; +import {useTranslations} from "next-intl"; +import {useMemo, useState} from "react"; +import useRequest from "@/lib/app/hooks/useRequest"; +import {EXPORT_NAVGAN_PROVINCE_MANAGER} from "@/core/data/apiRoutes"; +import moment from "jalali-moment"; +import FileSaver from 'file-saver'; +import DescriptionIcon from '@mui/icons-material/Description'; + +const PrintExcel = ({table}) => { + const t = useTranslations(); + const [loading, setLoading] = useState(false) + const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}}) + const {columnFilters, columnFilterFns, sorting} = table.getState() + const columns = table.getAllColumns() + + const filterParams = useMemo(() => { + const params = new URLSearchParams(); + const filters = columnFilters.map((filter) => { + let datatype; + for (const i in columns) { + if (columns[i].id == filter.id) { + datatype = columns[i].columnDef.datatype; + } + } + return { + ...filter, fn: columnFilterFns[filter.id], datatype: datatype, + }; + }); + params.set("start", '0'); + params.set("filters", JSON.stringify(filters ?? [])); + params.set("sorting", JSON.stringify(sorting ?? [])); + return params; + }, [columnFilters, columnFilterFns, sorting, columns,]); + + + const clickHandler = () => { + setLoading(true) + requestServer(`${EXPORT_NAVGAN_PROVINCE_MANAGER}?${filterParams}`, 'get', { + auth: true, + notification: false, + requestOptions: {responseType: 'blob'} + }).then((response) => { + const filename = `گزارش مدیر کل استانی تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`; + FileSaver.saveAs(response.data, filename); + }).catch(() => { + }).finally(() => { + setLoading(false) + }) + } + + + return ( + + ) +} + +export default PrintExcel \ No newline at end of file diff --git a/src/components/dashboard/navgan-province-manager/TableToolbar.jsx b/src/components/dashboard/navgan-province-manager/TableToolbar.jsx new file mode 100644 index 0000000..44a75d9 --- /dev/null +++ b/src/components/dashboard/navgan-province-manager/TableToolbar.jsx @@ -0,0 +1,13 @@ +import {Stack} from "@mui/material"; +import PrintExcel from "@/components/dashboard/navgan-province-manager/Buttons/printExcel"; + +const TableToolbar = ({table}) => { + + return ( + + + + ) +} + +export default TableToolbar \ No newline at end of file diff --git a/src/components/dashboard/navgan-province-manager/index.jsx b/src/components/dashboard/navgan-province-manager/index.jsx index e0e6a39..0397fc5 100644 --- a/src/components/dashboard/navgan-province-manager/index.jsx +++ b/src/components/dashboard/navgan-province-manager/index.jsx @@ -6,6 +6,7 @@ import TableRowActions from "./TableRowActions"; import moment from "jalali-moment"; import DataTable from "@/core/components/DataTable"; import MuiDatePicker from "@/core/components/MuiDatePicker"; +import TableToolbar from "@/components/dashboard/navgan-province-manager/TableToolbar"; function DashboardNavganProvinceManagerComponent() { const t = useTranslations(); @@ -162,7 +163,8 @@ function DashboardNavganProvinceManagerComponent() { tableUrl={GET_NAVGAN_PROVINCE_MANAGER} columns={columns} selectableRow={false} - enableCustomToolbar={false} + enableCustomToolbar={true} + CustomToolbar={TableToolbar} enableLastUpdate={true} sorting={[{ id: 'id', desc: false diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index 69d404f..27fbefd 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -85,6 +85,8 @@ export const CONFIRM_NAVGAN_PROVINCE_MANAGER = export const REJECT_NAVGAN_PROVINCE_MANAGER = BASE_URL + "/dashboard/province_manager/reject"; +export const EXPORT_NAVGAN_PROVINCE_MANAGER = + BASE_URL + "/dashboard/province_manager/export"; //navgan province manager // refahi province manager From b154160a37c7eaf5af9bb2dfc4e8d6bea97b12ec Mon Sep 17 00:00:00 2001 From: AminGhasempoor Date: Mon, 20 Nov 2023 16:42:38 +0330 Subject: [PATCH 26/32] LFFE-29 first demo of loan history --- package.json | 1 + public/locales/fa/app.json | 9 +- .../Form/HistoryForm/HistoryContent.jsx | 190 ++++++++++++++++++ .../loan-history/Form/HistoryForm/index.jsx | 31 +++ .../loan-history/TableRowActions.jsx | 16 ++ .../dashboard/loan-history/index.jsx | 187 +++++++++++++++++ src/core/data/sidebarMenu.jsx | 10 + src/pages/dashboard/loan-history/index.jsx | 21 ++ 8 files changed, 463 insertions(+), 2 deletions(-) create mode 100644 src/components/dashboard/loan-history/Form/HistoryForm/HistoryContent.jsx create mode 100644 src/components/dashboard/loan-history/Form/HistoryForm/index.jsx create mode 100644 src/components/dashboard/loan-history/TableRowActions.jsx create mode 100644 src/components/dashboard/loan-history/index.jsx create mode 100644 src/pages/dashboard/loan-history/index.jsx diff --git a/package.json b/package.json index 4583a4c..c03278c 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@emotion/styled": "^11.10.6", "@mui/icons-material": "^5.11.16", "@mui/material": "^5.12.0", + "@mui/x-data-grid": "^6.18.1", "@mui/x-date-pickers": "^6.9.2", "apexcharts": "^3.44.0", "axios": "^1.4.0", diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index b9b8070..9b1e9f4 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -57,7 +57,8 @@ "expert-management": "مدیریت کارشناسان", "user-management": "مدیریت کاربر", "role-management": "مدیریت نقش ها", - "edit-profile": "ویرایش پروفایل" + "edit-profile": "ویرایش پروفایل", + "loan-history": "تاریخچه وام ها" }, "secondary": { "passenger-office": "توزیع درخواست", @@ -115,7 +116,8 @@ "role_management_page": "مدیریت نقش ها", "edit_profile": "ویرایش پروفایل", "expert_management": "مدیریت کارشناسان", - "user_management_page": "مدیریت کاربر" + "user_management_page": "مدیریت کاربر", + "loan_history": "تاریخچهِ وام ها" }, "MuiDatePicker": { "date_picker_birthday": "تاریخ" @@ -533,5 +535,8 @@ "excel_export": "خروجی به اکسل", "export": "دریافت", "update_again": "بروزرسانی مجدد" + }, + "LoanHistory": { + "history": "تاریخچه" } } diff --git a/src/components/dashboard/loan-history/Form/HistoryForm/HistoryContent.jsx b/src/components/dashboard/loan-history/Form/HistoryForm/HistoryContent.jsx new file mode 100644 index 0000000..d2c23d0 --- /dev/null +++ b/src/components/dashboard/loan-history/Form/HistoryForm/HistoryContent.jsx @@ -0,0 +1,190 @@ +import { + Button, + CircularProgress, + DialogActions, + DialogContent, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow +} from "@mui/material" +import {useTranslations} from "next-intl"; +import {useFormik} from "formik"; +import {EXPORT_MACHINARY_OFFICE} from "@/core/data/apiRoutes"; +import moment from "jalali-moment"; +import DescriptionIcon from "@mui/icons-material/Description"; +import {useState} from "react"; + +const fakeData = [ + { + date: "1401/08/28", + name: "امین قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "امیر قاسم پور", + place: "اداره راه و شهرسازی مشهد", + toDo: "ارجاع به معاونت حمل و نقل" + }, + { + date: "1401/08/28", + name: "محمد جلالی", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "احمد قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "اکبر قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "اصغر قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "نیما قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "مهدی قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "مهدی قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "مهدی قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "مهدی قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "مهدی قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "مهدی قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "مهدی قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, + { + date: "1401/08/28", + name: "مهدی قاسم پور", + place: "اداره راه و شهرسازی تهران", + toDo: "ارجاع به کارشناس" + }, +] +const HistoryContent = ({mutate, setOpenConfirmDialog, rowId}) => { + const t = useTranslations(); + const [loading, setLoading] = useState(false) + const clickHandler = () => { + setLoading(true) + requestServer(`${EXPORT_MACHINARY_OFFICE}?${filterParams}`, 'get', { + auth: true, + notification: false, + requestOptions: {responseType: 'blob'} + }).then((response) => { + const filename = `گزارش ماشین آلات تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`; + FileSaver.saveAs(response.data, filename); + }).catch(() => { + }).finally(() => { + setLoading(false) + }) + } + const formik = useFormik({}); + + return ( + <> + + + + + + نام + تاریخ + سازمان + وضعیت + فایل ضمیمه + + + + {fakeData.map((singleData) => ( + + + {singleData.name} + + {singleData.date} + {singleData.place} + {singleData.toDo} + + + + + ))} + +
+
+
+ + + + + ) + +} +export default HistoryContent \ No newline at end of file diff --git a/src/components/dashboard/loan-history/Form/HistoryForm/index.jsx b/src/components/dashboard/loan-history/Form/HistoryForm/index.jsx new file mode 100644 index 0000000..de20f60 --- /dev/null +++ b/src/components/dashboard/loan-history/Form/HistoryForm/index.jsx @@ -0,0 +1,31 @@ +import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material"; +import {useTranslations} from "next-intl"; +import {useState} from "react"; +import HistoryIcon from '@mui/icons-material/History'; +import HistoryContent from "@/components/dashboard/loan-history/Form/HistoryForm/HistoryContent"; + +const History = ({rowId, mutate}) => { + const t = useTranslations(); + const [openConfirmDialog, setOpenConfirmDialog] = useState(false); + return ( + <> + + { + setOpenConfirmDialog(true) + }} + > + + + + + {t("LoanHistory.history")} + + + + ) + +} +export default History; \ No newline at end of file diff --git a/src/components/dashboard/loan-history/TableRowActions.jsx b/src/components/dashboard/loan-history/TableRowActions.jsx new file mode 100644 index 0000000..d0a967f --- /dev/null +++ b/src/components/dashboard/loan-history/TableRowActions.jsx @@ -0,0 +1,16 @@ +import {Box} from "@mui/material"; +import History from "@/components/dashboard/loan-history/Form/HistoryForm"; + +const TableRow = ({row, mutate}) => { + return ( + + + + ); +}; + +export default TableRow; diff --git a/src/components/dashboard/loan-history/index.jsx b/src/components/dashboard/loan-history/index.jsx new file mode 100644 index 0000000..0f0a261 --- /dev/null +++ b/src/components/dashboard/loan-history/index.jsx @@ -0,0 +1,187 @@ +import {Box, Typography} from "@mui/material"; +import {useMemo} from "react"; +import {GET_MACHINARY_OFFICE} from "@/core/data/apiRoutes"; +import {useTranslations} from "next-intl"; +import TableRowActions from "./TableRowActions"; +import moment from "jalali-moment"; +import DataTable from "@/core/components/DataTable"; +import MuiDatePicker from "@/core/components/MuiDatePicker"; + +function DashboardLoanHistoryComponent() { + const t = useTranslations(); + const columns = useMemo( + () => [ + { + accessorFn: (row) => row.id, + id: "id", + header: t("PassengerOffice.id"), + enableColumnFilter: true, + datatype: "numeric", + filterFn: "equals", + columnFilterModeOptions: [ + "equals", + "notEquals", + "contains", + "lessThan", + "greaterThan", + "between", + ], + Cell: ({renderedCellValue}) => ( + {renderedCellValue} + ), + }, + { + accessorFn: (row) => row.name, + id: "name", + header: t("MachinaryOffice.name"), + enableColumnFilter: true, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["contains", "equals", "notEquals"], + Cell: ({renderedCellValue}) => ( + {renderedCellValue} + ), + }, + { + accessorFn: (row) => row.national_id, + id: "national_id", + header: t("MachinaryOffice.national_id"), + enableColumnFilter: true, + datatype: "numeric", + filterFn: "equals", + columnFilterModeOptions: [ + "equals", + "notEquals", + "contains", + "lessThan", + "greaterThan", + "between", + ], + Cell: ({renderedCellValue}) => ( + {renderedCellValue} + ), + }, + { + accessorFn: (row) => row.phone_number, + id: "phone_number", + header: t("MachinaryOffice.phone_number"), + enableColumnFilter: true, + datatype: "numeric", + filterFn: "equals", + columnFilterModeOptions: [ + "equals", + "notEquals", + "contains", + "lessThan", + "greaterThan", + "between", + ], + Cell: ({renderedCellValue}) => ( + {renderedCellValue} + ), + }, + { + accessorFn: (row) => + moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"), + id: "created_at", + header: t("MachinaryOffice.created_at"), + enableColumnFilter: true, + datatype: "date", + filterFn: "lessThan", + columnFilterModeOptions: ["lessThan", "greaterThan"], + Cell: ({renderedCellValue}) => { + return {renderedCellValue}; + }, + Header: ({column}) => <>{column.columnDef.header}, + Filter: ({column}) => { + return ( + + ); + }, + }, + { + accessorFn: (row) => + moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"), + id: "updated_at", + header: t("MachinaryOffice.updated_at"), + enableColumnFilter: false, + datatype: "numeric", + Cell: ({renderedCellValue}) => ( + {renderedCellValue} + ), + }, + { + accessorFn: (row) => row.navgan_id, + id: "navgan_id", + header: t("MachinaryOffice.navgan_id"), + enableColumnFilter: true, + datatype: "numeric", + filterFn: "equals", + columnFilterModeOptions: [ + "equals", + "notEquals", + "contains", + "lessThan", + "greaterThan", + "between", + ], + Cell: ({renderedCellValue}) => ( + {renderedCellValue} + ), + }, + { + accessorFn: (row) => row.vehicle_type, + id: "vehicle_type", + header: t("MachinaryOffice.vehicle_type"), + enableColumnFilter: true, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["contains", "equals", "notEquals"], + Cell: ({renderedCellValue}) => ( + {renderedCellValue} + ), + }, + { + accessorFn: (row) => row.state_name, + id: "state_id", + header: t("MachinaryOffice.state_name"), + enableColumnFilter: false, + datatype: "numeric", + Cell: ({renderedCellValue}) => ( + {renderedCellValue} + ), + }, + ], + [] + ); + const data = [{ + id: 1 + }] + return ( + + + + ); +} + +export default DashboardLoanHistoryComponent; diff --git a/src/core/data/sidebarMenu.jsx b/src/core/data/sidebarMenu.jsx index 029ca26..f858852 100644 --- a/src/core/data/sidebarMenu.jsx +++ b/src/core/data/sidebarMenu.jsx @@ -14,6 +14,7 @@ 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'; +import AccessTimeIcon from '@mui/icons-material/AccessTime'; const sidebarMenu = [ [ @@ -176,6 +177,15 @@ const sidebarMenu = [ selected: false, permission: "manage_roles", }, + { + key: "sidebar.loan-history", + name: "loan-history", + type: "page", + route: "/dashboard/loan-history", + icon: , + selected: false, + permission: "manage_navgan_loan", + }, ], ]; diff --git a/src/pages/dashboard/loan-history/index.jsx b/src/pages/dashboard/loan-history/index.jsx new file mode 100644 index 0000000..d84d43e --- /dev/null +++ b/src/pages/dashboard/loan-history/index.jsx @@ -0,0 +1,21 @@ +import {parse} from "next-useragent"; +import DashboardLoanHistoryComponent from "@/components/dashboard/loan-history"; + +export default function LoanHistory() { + 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.loan_history", + isBot, + locale, + layout: {name: 'DashboardLayout', props: {permissions: ["manage_navgan_loan"]}} + }, + }; +} From d8eb780a32437959a009d23991725be5ae7175b1 Mon Sep 17 00:00:00 2001 From: AminGhasempoor Date: Tue, 21 Nov 2023 10:59:51 +0330 Subject: [PATCH 27/32] LFFE-29 table content structured --- .../Form/HistoryForm/HistoryContent.jsx | 172 +------------- .../Form/HistoryForm/TableContent.jsx | 210 ++++++++++++++++++ 2 files changed, 214 insertions(+), 168 deletions(-) create mode 100644 src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx diff --git a/src/components/dashboard/loan-history/Form/HistoryForm/HistoryContent.jsx b/src/components/dashboard/loan-history/Form/HistoryForm/HistoryContent.jsx index d2c23d0..040aef8 100644 --- a/src/components/dashboard/loan-history/Form/HistoryForm/HistoryContent.jsx +++ b/src/components/dashboard/loan-history/Form/HistoryForm/HistoryContent.jsx @@ -1,181 +1,17 @@ -import { - Button, - CircularProgress, - DialogActions, - DialogContent, - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow -} from "@mui/material" +import {Button, DialogActions, DialogContent,} from "@mui/material" import {useTranslations} from "next-intl"; import {useFormik} from "formik"; -import {EXPORT_MACHINARY_OFFICE} from "@/core/data/apiRoutes"; -import moment from "jalali-moment"; -import DescriptionIcon from "@mui/icons-material/Description"; -import {useState} from "react"; +import TableContent from "@/components/dashboard/loan-history/Form/HistoryForm/TableContent"; -const fakeData = [ - { - date: "1401/08/28", - name: "امین قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "امیر قاسم پور", - place: "اداره راه و شهرسازی مشهد", - toDo: "ارجاع به معاونت حمل و نقل" - }, - { - date: "1401/08/28", - name: "محمد جلالی", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "احمد قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "اکبر قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "اصغر قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "نیما قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, -] const HistoryContent = ({mutate, setOpenConfirmDialog, rowId}) => { const t = useTranslations(); - const [loading, setLoading] = useState(false) - const clickHandler = () => { - setLoading(true) - requestServer(`${EXPORT_MACHINARY_OFFICE}?${filterParams}`, 'get', { - auth: true, - notification: false, - requestOptions: {responseType: 'blob'} - }).then((response) => { - const filename = `گزارش ماشین آلات تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`; - FileSaver.saveAs(response.data, filename); - }).catch(() => { - }).finally(() => { - setLoading(false) - }) - } + const formik = useFormik({}); return ( <> - - - - - نام - تاریخ - سازمان - وضعیت - فایل ضمیمه - - - - {fakeData.map((singleData) => ( - - - {singleData.name} - - {singleData.date} - {singleData.place} - {singleData.toDo} - - - - - ))} - -
-
+
+ ) +} + +export default PrintHistory \ No newline at end of file diff --git a/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx b/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx index 3a6603d..cd0569b 100644 --- a/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx +++ b/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx @@ -1,210 +1,88 @@ import { - Button, - CircularProgress, + Box, + LinearProgress, Paper, Table, TableBody, TableCell, TableContainer, TableHead, - TableRow + TableRow, + Typography } from "@mui/material"; -import DescriptionIcon from "@mui/icons-material/Description"; -import {useState} from "react"; import {useTranslations} from "next-intl"; +import useHistory from "@/lib/app/hooks/useHistory"; +import {GET_HISTORY_DETAIL} from "@/core/data/apiRoutes"; +import moment from "jalali-moment"; +import PrintHistory from "@/components/dashboard/loan-history/Form/HistoryForm/PrintHistory"; -const fakeData = [ - { - date: "1401/08/28", - name: "امین قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "امیر قاسم پور", - place: "اداره راه و شهرسازی مشهد", - toDo: "ارجاع به معاونت حمل و نقل" - }, - { - date: "1401/08/28", - name: "محمد جلالی", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "احمد قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "اکبر قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "اصغر قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "نیما قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, - { - date: "1401/08/28", - name: "مهدی قاسم پور", - place: "اداره راه و شهرسازی تهران", - toDo: "ارجاع به کارشناس" - }, -] -const TableContent = () => { +const TableContent = ({rowId}) => { const t = useTranslations(); - const [loading, setLoading] = useState(false) - - const clickHandler = () => { - } + const {history_details, isLoading, error} = useHistory(`${GET_HISTORY_DETAIL}/${rowId}`) return ( - + {error ? ({t("LoanHistory.Table_history_error")}) : + (isLoading ? () : ( + history_details.latest_histories.length === 0 ? ( + {t("LoanHistory.empty_history_detail")} + ) : ( + + + + + + {t("LoanHistory.Table_head_name")} + {t("LoanHistory.Table_head_date")} + {t("LoanHistory.Table_head_position")} + {t("LoanHistory.Table_head_action")} + {t("LoanHistory.Table_head_file")} + + + + { + history_details.latest_histories.map((latest_history, index) => { + return ( + + + {latest_history.expert.name} + + {moment(latest_history.created_at).locale("fa").format("HH:mm | yyyy/MM/DD")} + {latest_history.expert.position} + {latest_history.previous_state_name} + + {latest_history.attachment ? ( + + ) : null} + + + ) + }) + } + +
+
+
+ ) + )) } - }}> - - - - - نام - تاریخ - سمت - عملیات - فایل پیوست - - - - {fakeData.map((singleData, index) => { - return ( - - - {singleData.name} - - {singleData.date} - {singleData.place} - {singleData.toDo} - - - - - ) - })} - -
-
-
+ + ) } export default TableContent \ No newline at end of file diff --git a/src/components/dashboard/loan-history/index.jsx b/src/components/dashboard/loan-history/index.jsx index 0f0a261..c2bb293 100644 --- a/src/components/dashboard/loan-history/index.jsx +++ b/src/components/dashboard/loan-history/index.jsx @@ -1,6 +1,6 @@ import {Box, Typography} from "@mui/material"; import {useMemo} from "react"; -import {GET_MACHINARY_OFFICE} from "@/core/data/apiRoutes"; +import {GET_LOAN_HISTORY} from "@/core/data/apiRoutes"; import {useTranslations} from "next-intl"; import TableRowActions from "./TableRowActions"; import moment from "jalali-moment"; @@ -154,14 +154,10 @@ function DashboardLoanHistoryComponent() { ], [] ); - const data = [{ - id: 1 - }] return ( { + + const requestServer = useRequest({auth: true, notification: false}) + + //swr config + const fetcher = (...args) => { + return requestServer(args, 'get').then((response) => { + return response.data.data; + }).catch(() => { + }) + }; + + const {data, isLoading, error} = useSWR(url, fetcher) + const history_details = data + //swr config + + // render data + return {history_details, isLoading, error} +} +export default useHistory \ No newline at end of file From 1b56aff3a625f95db48c2e241684856705628edd Mon Sep 17 00:00:00 2001 From: AminGhasempoor Date: Tue, 28 Nov 2023 16:36:58 +0330 Subject: [PATCH 29/32] LFFE-29 structured table of data --- .../loan-history/Form/HistoryForm/TableContent.jsx | 14 ++++++++++++-- src/core/data/sidebarMenu.jsx | 4 ++-- src/lib/app/hooks/useHistory.jsx | 6 +++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx b/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx index cd0569b..2459b47 100644 --- a/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx +++ b/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx @@ -22,11 +22,21 @@ const TableContent = ({rowId}) => { return ( - {error ? ({t("LoanHistory.Table_history_error")}) : + {error ? ({t("LoanHistory.Table_history_error")}) : (isLoading ? () : ( history_details.latest_histories.length === 0 ? ( {t("LoanHistory.empty_history_detail")} ) : ( , + icon: , selected: false, permission: "manage_navgan_loan", }, diff --git a/src/lib/app/hooks/useHistory.jsx b/src/lib/app/hooks/useHistory.jsx index 86d4d09..10aa3fc 100644 --- a/src/lib/app/hooks/useHistory.jsx +++ b/src/lib/app/hooks/useHistory.jsx @@ -13,7 +13,11 @@ const useHistory = (url) => { }) }; - const {data, isLoading, error} = useSWR(url, fetcher) + const {data, isLoading, error} = useSWR(url, fetcher, { + revalidateIfStale: false, + revalidateOnFocus: false, + revalidateOnReconnect: false + }) const history_details = data //swr config From a398de7bd36b4cb76fe2e01b16ce1a3e9a0c7638 Mon Sep 17 00:00:00 2001 From: Mohammad Jalali Date: Wed, 29 Nov 2023 11:45:39 +0330 Subject: [PATCH 30/32] LFFE-29 debug history part and remove useHistory hook --- .../Form/HistoryForm/TableContent.jsx | 21 ++++++++++++--- src/lib/app/hooks/useHistory.jsx | 27 ------------------- 2 files changed, 17 insertions(+), 31 deletions(-) delete mode 100644 src/lib/app/hooks/useHistory.jsx diff --git a/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx b/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx index 2459b47..34b1529 100644 --- a/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx +++ b/src/components/dashboard/loan-history/Form/HistoryForm/TableContent.jsx @@ -11,14 +11,27 @@ import { Typography } from "@mui/material"; import {useTranslations} from "next-intl"; -import useHistory from "@/lib/app/hooks/useHistory"; import {GET_HISTORY_DETAIL} from "@/core/data/apiRoutes"; import moment from "jalali-moment"; import PrintHistory from "@/components/dashboard/loan-history/Form/HistoryForm/PrintHistory"; +import useRequest from "@/lib/app/hooks/useRequest"; +import {useEffect, useState} from "react"; const TableContent = ({rowId}) => { const t = useTranslations(); - const {history_details, isLoading, error} = useHistory(`${GET_HISTORY_DETAIL}/${rowId}`) + const requestServer = useRequest({auth: true, notification: false}) + const [historyDetails, setHistoryDetails] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(false); + + useEffect(() => { + requestServer(`${GET_HISTORY_DETAIL}/${rowId}`, 'get').then((response) => { + setIsLoading(false); + setHistoryDetails(response.data.data); + }).catch(() => { + setError(true); + }) + }, []); return ( @@ -29,7 +42,7 @@ const TableContent = ({rowId}) => { justifyContent: "center" }}>{t("LoanHistory.Table_history_error")}) : (isLoading ? () : ( - history_details.latest_histories.length === 0 ? ( + historyDetails.latest_histories.length === 0 ? ( { { - history_details.latest_histories.map((latest_history, index) => { + historyDetails.latest_histories.map((latest_history, index) => { return ( { - - const requestServer = useRequest({auth: true, notification: false}) - - //swr config - const fetcher = (...args) => { - return requestServer(args, 'get').then((response) => { - return response.data.data; - }).catch(() => { - }) - }; - - const {data, isLoading, error} = useSWR(url, fetcher, { - revalidateIfStale: false, - revalidateOnFocus: false, - revalidateOnReconnect: false - }) - const history_details = data - //swr config - - // render data - return {history_details, isLoading, error} -} -export default useHistory \ No newline at end of file From 46c1a2eb2b88c3b240950d0bceffe2a0369c7c8b Mon Sep 17 00:00:00 2001 From: Yasiu1376 Date: Wed, 29 Nov 2023 17:00:16 +0330 Subject: [PATCH 31/32] LFFE-21 transportation assistance --- .../Form/ConfirmForm/ConfirmContent.jsx | 214 ++++++++++++++---- .../Form/ConfirmForm/ImageContent.jsx | 35 +++ .../Form/ConfirmForm/index.jsx | 28 ++- src/core/components/CustomAccordion.jsx | 72 ++++++ src/core/components/DownloadSection.jsx | 38 ++++ src/core/data/apiRoutes.js | 2 + 6 files changed, 334 insertions(+), 55 deletions(-) create mode 100644 src/components/dashboard/transportation-assistance/Form/ConfirmForm/ImageContent.jsx create mode 100644 src/core/components/CustomAccordion.jsx create mode 100644 src/core/components/DownloadSection.jsx diff --git a/src/components/dashboard/transportation-assistance/Form/ConfirmForm/ConfirmContent.jsx b/src/components/dashboard/transportation-assistance/Form/ConfirmForm/ConfirmContent.jsx index 0dcec2a..fa9f438 100644 --- a/src/components/dashboard/transportation-assistance/Form/ConfirmForm/ConfirmContent.jsx +++ b/src/components/dashboard/transportation-assistance/Form/ConfirmForm/ConfirmContent.jsx @@ -1,21 +1,88 @@ import UploadSystem from "@/core/components/UploadSystem"; import useNotification from "@/lib/app/hooks/useNotification"; import useRequest from "@/lib/app/hooks/useRequest"; -import {Button, DialogActions, DialogContent, FormHelperText, Stack, TextField, Typography} from "@mui/material" +import { + Box, + Button, + DialogActions, + DialogContent, + FormHelperText, Grid, LinearProgress, + Stack, + TextField, + Typography +} from "@mui/material" import {useFormik} from "formik"; import {useTranslations} from "next-intl"; -import {CONFIRM_TRANSPORTATION_ASSISTANCE} from "@/core/data/apiRoutes"; -import {useState} from "react"; +import {CONFIRM_TRANSPORTATION_ASSISTANCE, GET_TRANSPORTATION_ASSISTANCE_DETAILS} from "@/core/data/apiRoutes"; +import {useEffect, useState} from "react"; import * as Yup from "yup"; - -const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => { +import CustomAccordion from "@/core/components/CustomAccordion"; +import ImageContent from "@/components/dashboard/transportation-assistance/Form/ConfirmForm/ImageContent"; +const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog ,handleSizeChangeClick}) => { const t = useTranslations(); const [selectedImage, setSelectedImage] = useState(""); const [fileType, setfileType] = useState(null); const [fileName, setfileName] = useState(null); const [showAddIcon, setShowAddIcon] = useState(true); - const requestServer = useRequest({auth: true}) - const {update_notification} = useNotification() + const requestServer = useRequest({auth: true , notification: false}) + const [accordionStates, setAccordionStates] = useState([]); + const [hasAccordionOpened, setHasAccordionOpened] = useState([]); + const {update_notification} = useNotification(); + const [hasImageShown, sethasImageShown] = useState(false); + const [imageLink, setimageLink] = useState(null); + const [detailsList, setDetailsData] = useState(null); + const [loading, setLoading] = useState(true); + const [isSkeleton, setIsSkeleton] = useState(false); + const [isButtonDisabled, setIsButtonDisabled] = useState(true); + + useEffect(() => { + requestServer(`${GET_TRANSPORTATION_ASSISTANCE_DETAILS}/${rowId}`, 'get') + .then((response) => { + const booleanArray = Array.from({ length: response.data.data.attachment_files.length }, () => false); + setAccordionStates(booleanArray); + setHasAccordionOpened(booleanArray); + setDetailsData(response.data) + }) + .catch((error) => { + + }).finally(() => { + setLoading(false); + }); + }, []); + + useEffect(() => { + if (detailsList && detailsList.data && detailsList.data.attachment_files && detailsList.data.attachment_files.length !== 0) { + setIsButtonDisabled(true); + } else { + setIsButtonDisabled(false); + } + }, [detailsList]); + + const handleAccordionChange = (index) => { + const newAccordionStates = accordionStates.map((state, i) => i === index ? !state : false); + setAccordionStates(newAccordionStates); + + if (newAccordionStates[index]===false) + { + handleSizeChangeClick(index , false); + sethasImageShown(false); + setIsSkeleton(false) + } + else { + handleSizeChangeClick(index , true); + sethasImageShown(true); + setimageLink(detailsList.data.attachment_files[index]) + setIsSkeleton(true) + const newHasAccordionOpened = [...hasAccordionOpened]; + newHasAccordionOpened[index] = true; + setHasAccordionOpened(newHasAccordionOpened); + + if (newHasAccordionOpened.every(opened => opened === true)) { + setIsButtonDisabled(false) + } + } + }; + const validationSchema = Yup.object().shape({ confirm_img: Yup.mixed().notRequired(t("ConfirmDialog.approved_amount_error")) @@ -72,51 +139,96 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => { } }; + const renderCustomAccordions = () => { + if (detailsList && detailsList.data && detailsList.data.attachment_files) { + return detailsList.data.attachment_files.map((file, index) => ( + handleAccordionChange(index)} + accordionIndex={index} + handleSizeChange={() => handleSizeChange(index)} + /> + )); + } + return null; + }; + return ( <> - - - - {t("ConfirmDialog.description")}{t("ConfirmDialog.optional")}} - value={formik.values.description} - onChange={handleDescriptionChange} - fullWidth - variant="outlined" - sx={{mt: 1}} - /> - - - {t("UploadSystem.upload_file")}{t("UploadSystem.optional")} - formik.handleBlur("confirm_img")} - error={ - formik.touched.confirm_img && - Boolean(formik.errors.confirm_img) - } - /> - - {formik.touched.confirm_img && formik.errors.confirm_img} - - - + + + + {t("ConfirmDialog.approved_amount")} {t("sidebar.machinery-expert")} + + {isNaN((detailsList?.data?.proposed_amount) / 10) + ? "" + : ((detailsList?.data?.proposed_amount) / 10).toLocaleString()}{" "} + {t("ConfirmDialog.unit")} + + + + {t("ConfirmDialog.approved_amount")} {t("secondary.passenger-boss")} + + {isNaN((detailsList?.data?.approved_amount) / 10) + ? "" + : ((detailsList?.data?.approved_amount) / 10).toLocaleString()}{" "} + {t("ConfirmDialog.unit")} + + + {loading ? : renderCustomAccordions()} + + + + {t("ConfirmDialog.description")}{t("ConfirmDialog.optional")}} + value={formik.values.description} + onChange={handleDescriptionChange} + fullWidth + variant="outlined" + sx={{mt: 1}} + /> + + + {t("UploadSystem.upload_file")}{t("UploadSystem.optional")} + formik.handleBlur("confirm_img")} + error={ + formik.touched.confirm_img && + Boolean(formik.errors.confirm_img) + } + /> + + {formik.touched.confirm_img && formik.errors.confirm_img} + + + + + + + + + + diff --git a/src/components/dashboard/transportation-assistance/Form/ConfirmForm/ImageContent.jsx b/src/components/dashboard/transportation-assistance/Form/ConfirmForm/ImageContent.jsx new file mode 100644 index 0000000..9d3afa9 --- /dev/null +++ b/src/components/dashboard/transportation-assistance/Form/ConfirmForm/ImageContent.jsx @@ -0,0 +1,35 @@ +import {Box, Skeleton, Stack} from "@mui/material"; +import {useEffect} from "react"; +const ImageContent = (link) => { + useEffect(() => { + const timer = setTimeout(() => { + link.setIsSkeleton(false); + }, 1000); + + return () => clearTimeout(timer); + }, [link.isSkeleton]); + + const isPDF = link && link.imageLink && link.imageLink.attachment && link.imageLink.attachment.endsWith('.pdf'); + return ( + <> + + {link.isSkeleton && ( + + + + )} + {isPDF ? ( + + ) : ( + link && link.imageLink && link.imageLink.attachment && ( + + + + ) + )} + + + ) + +} +export default ImageContent; \ No newline at end of file diff --git a/src/components/dashboard/transportation-assistance/Form/ConfirmForm/index.jsx b/src/components/dashboard/transportation-assistance/Form/ConfirmForm/index.jsx index 2ef7d25..b33f30d 100644 --- a/src/components/dashboard/transportation-assistance/Form/ConfirmForm/index.jsx +++ b/src/components/dashboard/transportation-assistance/Form/ConfirmForm/index.jsx @@ -1,27 +1,45 @@ -import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material"; +import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material"; import {useTranslations} from "next-intl"; -import {useState} from "react"; +import {useState , useEffect} from "react"; import ConfirmContent from "./ConfirmContent"; import CallMadeIcon from '@mui/icons-material/CallMade'; const Confirm = ({rowId, mutate}) => { const t = useTranslations(); const [openConfirmDialog, setOpenConfirmDialog] = useState(false); + const [dialogSize, setDialogSize] = useState('sm'); + + useEffect(() => { + if (!openConfirmDialog) { + setDialogSize('sm'); + } + }, [openConfirmDialog]); + + const handleSizeChangeClick = (num , state) => { + if (state===true){ + setDialogSize('xl'); + + } + else { + setDialogSize('sm'); + } + }; + return ( <> { - setOpenConfirmDialog(true) + setOpenConfirmDialog(true); }} > + PaperProps={{sx: {transition: 'all .3s', boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}} maxWidth={dialogSize}> {t("TransportationAssistance.confirm")} - + ) diff --git a/src/core/components/CustomAccordion.jsx b/src/core/components/CustomAccordion.jsx new file mode 100644 index 0000000..eb2efcc --- /dev/null +++ b/src/core/components/CustomAccordion.jsx @@ -0,0 +1,72 @@ +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + Typography, + Grid, ButtonGroup, Button, CircularProgress +} from "@mui/material"; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import VerifiedIcon from '@mui/icons-material/Verified'; +import Check from "@mui/icons-material/Check"; +import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined"; +import VisibilityRoundedIcon from "@mui/icons-material/VisibilityRounded"; +import {useTranslations} from "next-intl"; +import {useState} from "react"; + +const CustomAccordion = ({ title, + hasOpened, + hasAccordionOpened, + handleAccordionChange, + accordionIndex, + handleSizeChange }) => { + const t = useTranslations(); + const [downloadStatus, setDownloadStatus] = useState('initial'); + const handleDownloadClick = (setStatus) => { + + console.log(setStatus) + setStatus('downloading'); + setTimeout(() => { + setStatus('completed'); + setTimeout(() => { + setStatus('initial'); + }, 2500); + }, 2000); + // Perform the actual download logic here + }; + return( + handleAccordionChange(accordionIndex)} sx={{ + mb: 2, + boxShadow: 1, + backgroundColor: "#f7f7f7" + }}> + }> + + + {title} + {hasAccordionOpened && } + + + + + + + + + + + + + +); +} + +export default CustomAccordion; diff --git a/src/core/components/DownloadSection.jsx b/src/core/components/DownloadSection.jsx new file mode 100644 index 0000000..fc20d9c --- /dev/null +++ b/src/core/components/DownloadSection.jsx @@ -0,0 +1,38 @@ +import FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined'; +import Check from '@mui/icons-material/Check'; +import {CircularProgress} from "@mui/material" +const DownloadSection = ({ downloadStatus, onDownloadClick }) => { + return ( +
+ {downloadStatus === 'completed' ? ( + <> + + + ) : downloadStatus === 'downloading' ? ( + + ) : ( + <> + + + )} +
+ ); +}; + +export default DownloadSection; diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index dba065e..06d8ac9 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -38,6 +38,8 @@ export const REJECT_PASSENGER_BOSS = export const GET_TRANSPORTATION_ASSISTANCE = BASE_URL + "/dashboard/transportation_assistant/show"; +export const GET_TRANSPORTATION_ASSISTANCE_DETAILS = + BASE_URL + "/dashboard/transportation_assistant"; export const CONFIRM_TRANSPORTATION_ASSISTANCE = BASE_URL + "/dashboard/transportation_assistant/confirm"; From 0d530bac4e8ee7c57c60f2fae9cd6c9c399222ef Mon Sep 17 00:00:00 2001 From: AmirHossein Mahmoodi Date: Sat, 2 Dec 2023 10:25:56 +0330 Subject: [PATCH 32/32] change version to 1.22.3 --- example.env.local | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example.env.local b/example.env.local index f6cb8f0..e8913b3 100644 --- a/example.env.local +++ b/example.env.local @@ -1,5 +1,5 @@ NEXT_PUBLIC_API_NAME = "Loan Facilities Dashboard" -NEXT_PUBLIC_API_VERSION = "1.18.2" +NEXT_PUBLIC_API_VERSION = "1.22.3" NEXT_PUBLIC_DEFAULT_LANGUAGE = "fa" NEXT_PUBLIC_DEFAULT_DIRECTION = "rtl"