Feature/user info request

This commit is contained in:
2024-11-11 11:41:59 +00:00
committed by AmirHossein Mahmoodi
parent 987ac1d316
commit a71458ce20
328 changed files with 11965 additions and 8254 deletions

View File

@@ -8,6 +8,8 @@ NEXT_PUBLIC_SECONDARY_MAIN = "#FF4E00"
NEXT_PUBLIC_FACILITY_BANK = 33 NEXT_PUBLIC_FACILITY_BANK = 33
NEXT_PUBLIC_FACILITY_PERSON = 10 NEXT_PUBLIC_FACILITY_PERSON = 10
NEXT_PUBLIC_BUS_AMOUNT=10000
NEXT_PUBLIC_MINIBUS_AMOUNT=4000
NEXT_PUBLIC_BASE_URL = "https://loan-v2.witel.ir" NEXT_PUBLIC_BASE_URL = "https://loan-v2.witel.ir"
NEXT_PUBLIC_POWERED_BY_URL = "https://witel.ir" NEXT_PUBLIC_POWERED_BY_URL = "https://witel.ir"

View File

@@ -1,3 +1,3 @@
{ {
"extends": "next/core-web-vitals" "extends" : ["next/core-web-vitals","prettier"]
} }

12
.prettierrc Normal file
View File

@@ -0,0 +1,12 @@
{
"printWidth": 120,
"tabWidth": 4,
"useTabs": false,
"semi": true,
"singleQuote": false,
"trailingComma": "es5",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"arrowParens": "always",
"endOfLine": "crlf"
}

View File

@@ -9,6 +9,7 @@
"start": "next start", "start": "next start",
"publish-3002": "next start -p 3002", "publish-3002": "next start -p 3002",
"lint": "next lint", "lint": "next lint",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,html,css,scss}\"",
"test": "jest", "test": "jest",
"test:watch": "jest --watchAll", "test:watch": "jest --watchAll",
"cypress:open": "cypress open", "cypress:open": "cypress open",
@@ -41,6 +42,7 @@
"next-intl": "^2.13.1", "next-intl": "^2.13.1",
"next-useragent": "^2.8.0", "next-useragent": "^2.8.0",
"nextjs-progressbar": "^0.0.16", "nextjs-progressbar": "^0.0.16",
"prettier": "^3.3.3",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-apexcharts": "^1.4.1", "react-apexcharts": "^1.4.1",

View File

@@ -267,7 +267,7 @@
"upload_expert_file_required": "وارد کردن گزارش کارشناسی الزامیست", "upload_expert_file_required": "وارد کردن گزارش کارشناسی الزامیست",
"upload_expert_file_unit": "فایل بارگذاری شده باید حداکثر 5Mb باشد", "upload_expert_file_unit": "فایل بارگذاری شده باید حداکثر 5Mb باشد",
"upload_expert_file_format": "فرمت قابل قبول : png,jpg,pdf", "upload_expert_file_format": "فرمت قابل قبول : png,jpg,pdf",
"max_amount": "حداکثر مبلغ تصویب شده {value} میلیون ریال می باشد", "max_amount": "حداکثر مبلغ تصویب شده {value} {amount} ریال می باشد",
"excel_report": "گزارش اکسل", "excel_report": "گزارش اکسل",
"first_form": "فرم الف را بارگذاری کنید", "first_form": "فرم الف را بارگذاری کنید",
"second_form": "فرم ب را بارگذاری کنید" "second_form": "فرم ب را بارگذاری کنید"
@@ -599,6 +599,7 @@
"participation_period_number": "دوره مشارکت باید عدد باشد", "participation_period_number": "دوره مشارکت باید عدد باشد",
"tanafos_period_number": "دوره تنفس باید عدد باشد", "tanafos_period_number": "دوره تنفس باید عدد باشد",
"toman": "میلیون تومان", "toman": "میلیون تومان",
"milyard_toman": "میلیارد تومان",
"facility_bank_max_amount": "جمع مبلغ سهم دولت و سهم بانک نباید از مبلغ تصویب شده بیشتر باشد .", "facility_bank_max_amount": "جمع مبلغ سهم دولت و سهم بانک نباید از مبلغ تصویب شده بیشتر باشد .",
"facility_gov_max_amount": "جمع مبلغ سهم دولت و سهم بانک نباید از مبلغ تصویب شده بیشتر باشد .", "facility_gov_max_amount": "جمع مبلغ سهم دولت و سهم بانک نباید از مبلغ تصویب شده بیشتر باشد .",
"tanafos_period_month": "ماه", "tanafos_period_month": "ماه",
@@ -662,7 +663,7 @@
"unit": " (میلیون ریال)", "unit": " (میلیون ریال)",
"button-revise": "ارسال", "button-revise": "ارسال",
"approved_amount_positive": "مبلغ مصوب باید مثبت باشد", "approved_amount_positive": "مبلغ مصوب باید مثبت باشد",
"max_amount": "حداکثر مبلغ مصوب {value} میلیون ریال می باشد", "max_amount": "حداکثر مبلغ مصوب {value} {amount} ریال می باشد",
"approved_amount_number": "مبلغ مصوب باید عدد باشد", "approved_amount_number": "مبلغ مصوب باید عدد باشد",
"description": "توضیحات خود را وارد نمائید" "description": "توضیحات خود را وارد نمائید"
}, },
@@ -780,6 +781,60 @@
"typography": "آیا از حدف این مورد اطمینان دارید ؟", "typography": "آیا از حدف این مورد اطمینان دارید ؟",
"button-delete": "حذف کردن" "button-delete": "حذف کردن"
}, },
"UserInfoDialog": {
"user_info": "اطلاعات درخواست کاربر",
"user_info_tooltip" : "اطلاعات کاربر",
"applicant_payment" : "آورده متقاضی",
"id" : "کد یکتا",
"toman" : "{value} میلیون ریال",
"milyard" : "{value} میلیارد ریال",
"user_committed_employment" :"تعداد اشتغال متعهد متقاضی",
"user_existing_employment" : "تعداد اشتغال موجود متقاضی",
"phone_number": "شماره تلفن",
"requested_facilities" : "تسهیلات مورد تقاضا",
"physical_progress" : "درصد پیشرفت فیزیکی",
"investment" : "سرمایه گذاری انجام شده",
"no_info" : "اطلاعاتی موجود نیست !!!",
"is_legal_person": "نوع شخص",
"legal_person" : "شخص حقوقی",
"real_person" : "شخص حقیقی",
"activity_type": "نوع فعالیت",
"navgan_plan_id": "عنوان پروژه",
"shenasname_serial": "سریال پشت کارت ملی",
"national_tracking_code": "کد رهگیری کارت ملی",
"national_id": "کد ملی",
"boss_national_id": "کد ملی مدیر عامل",
"register_number": "شماره ثبت شرکت",
"postal_code": "کد پستی",
"national_serial_number": "سریال پشت کارت ملی",
"address": "آدرس",
"committed_employment": "اشتغال ایجاد شده",
"existing_employment": "اشتغال موجود",
"plate" : "پلاک",
"male" : "مرد",
"female" : "زن",
"IRAN" : "ایران",
"company_name": "نام شرکت",
"company_register_date": "تاریخ ثبت شرکت",
"father_name": "نام پدر",
"birthday": "تاریخ تولد",
"navgan_id": "کد ناوگان",
"province_id": "استان",
"city_id": "شهر",
"boss_father_name": "نام پدر مدیر عامل",
"education_id": "تحصیلات",
"occupation_id": "شغل",
"navgan_type": "نوع ناوگان",
"shenase_meli": "شناسه ملی شرکت",
"first_name": "نام",
"boss_first_name": "نام مدیر عامل",
"boss_last_name": "نام خانوادگی مدیر عامل",
"gender": "جنسیت",
"last_name": "نام خانوادگی",
"vehicle_type": "نوع وسیله",
"tel_number": "شماره ثابت (با پیش شماره استان)",
"button-cancel": "بستن"
},
"ReferDialog": { "ReferDialog": {
"refer-passenger-boss": "ارجاع به کارگروه", "refer-passenger-boss": "ارجاع به کارگروه",
"refer-user": "ارجاع به کاربر", "refer-user": "ارجاع به کاربر",
@@ -916,5 +971,61 @@
"Table_head_refer_reason": "علت ارجاع", "Table_head_refer_reason": "علت ارجاع",
"Table_head_expert_description": "توضیحات", "Table_head_expert_description": "توضیحات",
"empty_history_detail": "سابقه ای برای این وام وجود ندارد" "empty_history_detail": "سابقه ای برای این وام وجود ندارد"
},
"CouncilHistory": {
"id": "کد یکتا",
"name": "نام",
"close": "بستن",
"more": "بیشتر",
"council_opinion": "نظر شورا برنامه ریزی :",
"council_history": "نتیجه شورای برنامه ریزی",
"council_history_detail": "نتیجه شورای برنامه ریزی",
"score": "اولویت",
"existing_employment": "اشتغال موجود",
"bank_facility": "سهم بانک",
"facility_bank": "سهم بانک",
"government_facility": "سهم دولت",
"facility_gov": "سهم دولت",
"user_facility": "سهم متقاضی",
"facility_person": "سهم متقاضی",
"physical_progress": "درصد پیشرفت فیزیکی",
"committed_employment": "اشتغال ایجاد شده",
"available_jobs": "اشتغال موجود",
"navgan_capacity": "ظرفیت",
"manufacture_date": "سال ساخت",
"shenase_meli": "شناسه ملی",
"is_legal_person": "نوع شخص",
"haghighi": "حقیقی",
"hoghoghi": "حقوقی",
"tanafos_period": "دوره تنفس",
"repayment_period": "دوره بازپرداخت",
"sakht_period": "دوره ساخت",
"national_id": "کد ملی",
"postal_code": "کد پستی",
"phone_number": "موبایل",
"proposed_amount": "مبلغ پیشنهادی",
"approved_amount": "مبلغ مصوب",
"created_at": "تاریخ درخواست",
"updated_at": "تاریخ بروزرسانی",
"navgan_id": "کد ناوگان",
"button-cancel": "بستن",
"vehicle_type": "نوع ماشین",
"state_name": "وضعیت درخواست",
"history": "تاریخچه",
"province_name": "استان",
"Table_history_error": "خطا در دریافت اطلاعات",
"history_report": "فایل ضمیمه",
"Table_head_name": "نام",
"Table_head_id": "کد یکتا",
"Table_head_date": "تاریخ",
"Table_head_planning_council_loan": "تاریخ",
"Table_head_position": "سمت",
"Table_head_council_comment": "توضیحات",
"Table_head_council_reason_name": "عملیات",
"Table_head_file": "فایل پیوست",
"Table_head_state": "وضعیت",
"Table_head_council_confirm": "وضعیت",
"Table_head_refer_reason": "علت ارجاع",
"Table_head_expert_description": "توضیحات"
} }
} }

View File

@@ -7,14 +7,11 @@ import {ADD_ADMIN_SETTING} from "@/core/data/apiRoutes";
const CreateContent = ({ mutate, setOpenConfirmDialog }) => { const CreateContent = ({ mutate, setOpenConfirmDialog }) => {
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
name: Yup.string("AddDialog.name_string") name: Yup.string("AddDialog.name_string").required(t("AddDialog.setting_name_error")),
.required(t("AddDialog.setting_name_error")), name_fa: Yup.string("AddDialog.name_fa_string").required(t("AddDialog.setting_name_fa_error")),
name_fa: Yup.string("AddDialog.name_fa_string") value: Yup.string("AddDialog.value_string").required(t("AddDialog.value_error")),
.required(t("AddDialog.setting_name_fa_error")),
value: Yup.string("AddDialog.value_string")
.required(t("AddDialog.value_error")),
}); });
const formik = useFormik({ const formik = useFormik({
@@ -22,20 +19,24 @@ const CreateContent = ({mutate, setOpenConfirmDialog}) => {
name: "", name: "",
name_fa: "", name_fa: "",
value: "", value: "",
}, validationSchema, onSubmit: (values, {setSubmitting}) => { },
validationSchema,
onSubmit: (values, { setSubmitting }) => {
const formData = new FormData(); const formData = new FormData();
formData.append("name", values.name); formData.append("name", values.name);
formData.append("name_fa", values.name_fa); formData.append("name_fa", values.name_fa);
formData.append("value", values.value); formData.append("value", values.value);
requestServer(ADD_ADMIN_SETTING, 'post', { requestServer(ADD_ADMIN_SETTING, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenConfirmDialog(false) .then((response) => {
mutate() setOpenConfirmDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -92,16 +93,25 @@ const CreateContent = ({mutate, setOpenConfirmDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("AddDialog.button-cancel")} {t("AddDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("AddDialog.button-add")} {t("AddDialog.button-add")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
} };
export default CreateContent export default CreateContent;

View File

@@ -18,18 +18,25 @@ const CreateForm = ({mutate}) => {
sx={{ textTransform: "unset", alignSelf: "center" }} sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={<DataSaverOnIcon />} startIcon={<DataSaverOnIcon />}
onClick={() => { onClick={() => {
setOpenConfirmDialog(true) setOpenConfirmDialog(true);
}} }}
> >
{t("AddDialog.add")} {t("AddDialog.add")}
</Button> </Button>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openConfirmDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openConfirmDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("AddDialog.add")}</DialogTitle> <DialogTitle>{t("AddDialog.add")}</DialogTitle>
<CreateContent mutate={mutate} setOpenConfirmDialog={setOpenConfirmDialog} /> <CreateContent mutate={mutate} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog> </Dialog>
</Stack> </Stack>
) );
} };
export default CreateForm export default CreateForm;

View File

@@ -8,9 +8,9 @@ import {
DialogTitle, DialogTitle,
IconButton, IconButton,
Tooltip, Tooltip,
Typography Typography,
} from "@mui/material"; } from "@mui/material";
import DeleteIcon from '@mui/icons-material/Delete'; import DeleteIcon from "@mui/icons-material/Delete";
import { DELETE_ADMIN_SETTING } from "@/core/data/apiRoutes"; import { DELETE_ADMIN_SETTING } from "@/core/data/apiRoutes";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
@@ -18,19 +18,21 @@ import useNotification from "@/lib/app/hooks/useNotification";
const Delete = ({ rowId, mutate }) => { const Delete = ({ rowId, mutate }) => {
const t = useTranslations(); const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false); const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false) const [isSubmitting, setIsSubmitting] = useState(false);
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const handleSubmit = () => { const handleSubmit = () => {
setIsSubmitting(true) setIsSubmitting(true);
requestServer(`${DELETE_ADMIN_SETTING}/${rowId}`, 'delete').then((response) => { requestServer(`${DELETE_ADMIN_SETTING}/${rowId}`, "delete")
mutate() .then((response) => {
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
setIsSubmitting(false) .catch(() => {})
.finally(() => {
setIsSubmitting(false);
}); });
} };
return ( return (
<> <>
@@ -38,25 +40,36 @@ const Delete = ({rowId, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenConfirmDialog(true) setOpenConfirmDialog(true);
}} }}
> >
<DeleteIcon /> <DeleteIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog maxWidth="sm" open={openConfirmDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> maxWidth="sm"
open={openConfirmDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("DeleteDialog.delete")}</DialogTitle> <DialogTitle>{t("DeleteDialog.delete")}</DialogTitle>
<DialogContent> <DialogContent>
<Typography>{t("DeleteDialog.typography")}</Typography> <Typography>{t("DeleteDialog.typography")}</Typography>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary" <Button
disabled={isSubmitting} autoFocus> onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={isSubmitting}
autoFocus
>
{t("DeleteDialog.button-cancel")} {t("DeleteDialog.button-cancel")}
</Button> </Button>
<Button onClick={handleSubmit} variant="contained" color="primary" <Button onClick={handleSubmit} variant="contained" color="primary" disabled={isSubmitting}>
disabled={isSubmitting}>
{t("DeleteDialog.button-delete")} {t("DeleteDialog.button-delete")}
</Button> </Button>
</DialogActions> </DialogActions>

View File

@@ -1,23 +1,20 @@
import { UPDATE_ADMIN_SETTING } from "@/core/data/apiRoutes"; import { UPDATE_ADMIN_SETTING } from "@/core/data/apiRoutes";
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField} from "@mui/material" import { Button, DialogActions, DialogContent, Stack, TextField } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import * as Yup from "yup"; import * as Yup from "yup";
const UpdateContent = ({ row, mutate, setOpenConfirmDialog }) => { const UpdateContent = ({ row, mutate, setOpenConfirmDialog }) => {
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
name: Yup.string("UpdateDialog.name_string") name: Yup.string("UpdateDialog.name_string").required(t("UpdateDialog.setting_name_error")),
.required(t("UpdateDialog.setting_name_error")), name_fa: Yup.string("UpdateDialog.name_fa_string").required(t("UpdateDialog.setting_name_fa_error")),
name_fa: Yup.string("UpdateDialog.name_fa_string") value: Yup.string("UpdateDialog.value_string").required(t("UpdateDialog.value_error")),
.required(t("UpdateDialog.setting_name_fa_error")),
value: Yup.string("UpdateDialog.value_string")
.required(t("UpdateDialog.value_error")),
}); });
const formik = useFormik({ const formik = useFormik({
@@ -25,19 +22,23 @@ const UpdateContent = ({row, mutate, setOpenConfirmDialog}) => {
name: row.getValue("name"), name: row.getValue("name"),
name_fa: row.getValue("name_fa"), name_fa: row.getValue("name_fa"),
value: row.getValue("value"), value: row.getValue("value"),
}, validationSchema, onSubmit: (values, {setSubmitting}) => { },
validationSchema,
onSubmit: (values, { setSubmitting }) => {
const formData = new FormData(); const formData = new FormData();
formData.append("name", values.name); formData.append("name", values.name);
formData.append("name_fa", values.name_fa); formData.append("name_fa", values.name_fa);
formData.append("value", values.value); formData.append("value", values.value);
requestServer(`${UPDATE_ADMIN_SETTING}/${row.getValue("id")}`, 'post', { requestServer(`${UPDATE_ADMIN_SETTING}/${row.getValue("id")}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenConfirmDialog(false) .then((response) => {
mutate() setOpenConfirmDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -94,16 +95,25 @@ const UpdateContent = ({row, mutate, setOpenConfirmDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("UpdateDialog.button-cancel")} {t("UpdateDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("UpdateDialog.button-update")} {t("UpdateDialog.button-update")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
} };
export default UpdateContent export default UpdateContent;

View File

@@ -1,5 +1,5 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material" import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import EditIcon from '@mui/icons-material/Edit'; import EditIcon from "@mui/icons-material/Edit";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
import UpdateContent from "./UpdateContent"; import UpdateContent from "./UpdateContent";
@@ -13,18 +13,25 @@ const Update = ({row, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenConfirmDialog(true) setOpenConfirmDialog(true);
}} }}
> >
<EditIcon /> <EditIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openConfirmDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openConfirmDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("UpdateDialog.update")}</DialogTitle> <DialogTitle>{t("UpdateDialog.update")}</DialogTitle>
<UpdateContent row={row} mutate={mutate} setOpenConfirmDialog={setOpenConfirmDialog} /> <UpdateContent row={row} mutate={mutate} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog> </Dialog>
</> </>
) );
} };
export default Update export default Update;

View File

@@ -5,14 +5,8 @@ import Delete from "@/components/dashboard/admin-setting/Form/DeleteForm";
const TableRow = ({ row, mutate }) => { const TableRow = ({ row, mutate }) => {
return ( return (
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}> <Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
<Update <Update row={row} mutate={mutate} />
row={row} <Delete rowId={row.getValue("id")} mutate={mutate} />
mutate={mutate}
/>
<Delete
rowId={row.getValue("id")}
mutate={mutate}
/>
</Box> </Box>
); );
}; };

View File

@@ -4,8 +4,7 @@ import CreateForm from "@/components/dashboard/admin-setting/Form/CreateForm";
function TableToolbar({ mutate }) { function TableToolbar({ mutate }) {
const t = useTranslations(); const t = useTranslations();
return <CreateForm mutate={mutate}/> return <CreateForm mutate={mutate} />;
} }
export default TableToolbar; export default TableToolbar;

View File

@@ -18,9 +18,7 @@ function DashboardAdminSettingComponent() {
datatype: "number", datatype: "number",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.name_fa, accessorFn: (row) => row.name_fa,
@@ -30,9 +28,7 @@ function DashboardAdminSettingComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals"], columnFilterModeOptions: ["contains", "equals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.name, accessorFn: (row) => row.name,
@@ -42,9 +38,7 @@ function DashboardAdminSettingComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals"], columnFilterModeOptions: ["contains", "equals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.value, accessorFn: (row) => row.value,
@@ -53,13 +47,8 @@ function DashboardAdminSettingComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "contains"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"contains",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
], ],
[] []
@@ -73,12 +62,15 @@ function DashboardAdminSettingComponent() {
enableCustomToolbar={true} enableCustomToolbar={true}
CustomToolbar={TableToolbar} CustomToolbar={TableToolbar}
enableLastUpdate={true} enableLastUpdate={true}
sorting={[{ sorting={[
id: 'id', desc: false {
}]} id: "id",
desc: false,
},
]}
enablePinning={true} enablePinning={true}
enableDensityToggle={false} enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large) initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true} enableColumnFilters={true}
enableHiding={true} enableHiding={true}
enableFullScreenToggle={false} enableFullScreenToggle={false}

View File

@@ -4,15 +4,15 @@ import {useMemo, useState} from "react";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import { EXPORT_BANK_MANAGEMENT } from "@/core/data/apiRoutes"; import { EXPORT_BANK_MANAGEMENT } from "@/core/data/apiRoutes";
import moment from "jalali-moment"; import moment from "jalali-moment";
import FileSaver from 'file-saver'; import FileSaver from "file-saver";
import DescriptionIcon from '@mui/icons-material/Description'; import DescriptionIcon from "@mui/icons-material/Description";
const PrintExcel = ({ table }) => { const PrintExcel = ({ table }) => {
const t = useTranslations(); const t = useTranslations();
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false);
const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}}) const requestServer = useRequest({ auth: true, pending: false, success: { notification: { show: false } } });
const {columnFilters, columnFilterFns, sorting} = table.getState() const { columnFilters, columnFilterFns, sorting } = table.getState();
const columns = table.getAllColumns() const columns = table.getAllColumns();
const filterParams = useMemo(() => { const filterParams = useMemo(() => {
const params = new URLSearchParams(); const params = new URLSearchParams();
@@ -24,31 +24,33 @@ const PrintExcel = ({table}) => {
} }
} }
return { return {
...filter, fn: columnFilterFns[filter.id], datatype: datatype, ...filter,
fn: columnFilterFns[filter.id],
datatype: datatype,
}; };
}); });
params.set("start", '0'); params.set("start", "0");
params.set("filters", JSON.stringify(filters ?? [])); params.set("filters", JSON.stringify(filters ?? []));
params.set("sorting", JSON.stringify(sorting ?? [])); params.set("sorting", JSON.stringify(sorting ?? []));
return params; return params;
}, [columnFilters, columnFilterFns, sorting, columns,]); }, [columnFilters, columnFilterFns, sorting, columns]);
const clickHandler = () => { const clickHandler = () => {
setLoading(true) setLoading(true);
requestServer(`${EXPORT_BANK_MANAGEMENT}?${filterParams}`, 'get', { requestServer(`${EXPORT_BANK_MANAGEMENT}?${filterParams}`, "get", {
auth: true, auth: true,
notification: false, notification: false,
requestOptions: {responseType: 'blob'} requestOptions: { responseType: "blob" },
}).then((response) => {
const filename = `گزارش کارتابل نظارت بانک تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`;
FileSaver.saveAs(response.data, filename);
}).catch(() => {
}).finally(() => {
setLoading(false)
}) })
} .then((response) => {
const filename = `گزارش کارتابل نظارت بانک تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})
.finally(() => {
setLoading(false);
});
};
return ( return (
<Button <Button
@@ -62,7 +64,7 @@ const PrintExcel = ({table}) => {
> >
{t("BankManagement.excel_report")} {t("BankManagement.excel_report")}
</Button> </Button>
) );
} };
export default PrintExcel export default PrintExcel;

View File

@@ -1,6 +1,6 @@
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack,} from "@mui/material" import { Button, DialogActions, DialogContent, Stack } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { EDIT_APPROVED_AMOUNT } from "@/core/data/apiRoutes"; import { EDIT_APPROVED_AMOUNT } from "@/core/data/apiRoutes";
@@ -8,9 +8,9 @@ import * as Yup from "yup";
import PriceField from "@/core/components/PriceField"; import PriceField from "@/core/components/PriceField";
const vehicle_amount = { const vehicle_amount = {
"اتوبوس": 7000, "اتوبوس": parseInt(process.env.NEXT_PUBLIC_BUS_AMOUNT),
"مینی بوس": 2000, "مینی بوس": parseInt(process.env.NEXT_PUBLIC_MINIBUS_AMOUNT),
} };
const EditContent = ({ rowId, row, mutate, setOpenEditDialog, vehicle_type }) => { const EditContent = ({ rowId, row, mutate, setOpenEditDialog, vehicle_type }) => {
const t = useTranslations(); const t = useTranslations();
@@ -18,41 +18,63 @@ const EditContent = ({rowId, row, mutate, setOpenEditDialog, vehicle_type}) => {
const { update_notification } = useNotification(); const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
approved_amount: Yup.mixed().test( approved_amount: Yup.mixed()
"is-number", .test("is-number", `${t("EditDialog.approved_amount_number")}`, (value) => !isNaN(value))
`${t("EditDialog.approved_amount_number")}`, .test("max-amount", function (value) {
(value) => !isNaN(value) const maxAmount =
).test("max-amount", `${t("EditDialog.max_amount", {value: parseInt(vehicle_amount[vehicle_type]).toLocaleString('en')})}`, vehicle_type === "اتوبوس"
(value) => value <= vehicle_amount[vehicle_type]) ? value > parseInt(process.env.NEXT_PUBLIC_BUS_AMOUNT)
? parseInt(vehicle_amount[vehicle_type]) / 1000
: parseInt(vehicle_amount[vehicle_type])
: parseInt(vehicle_amount[vehicle_type]);
// Check the condition to set the message dynamically
const message =
vehicle_type === "اتوبوس"
? value > parseInt(process.env.NEXT_PUBLIC_BUS_AMOUNT) &&
`${t("EditDialog.max_amount", {
value: maxAmount.toLocaleString("en"),
amount: "میلیارد",
})}`
: value > parseInt(process.env.NEXT_PUBLIC_MINIBUS_AMOUNT) &&
`${t("EditDialog.max_amount", {
value: maxAmount.toLocaleString("en"),
amount: "میلیارد",
})}`;
// Return either `true` (pass the validation) or `this.createError` with the message
return value <= maxAmount || this.createError({ message });
})
.test("positive", `${t("EditDialog.approved_amount_positive")}`, (value) => value >= 0) .test("positive", `${t("EditDialog.approved_amount_positive")}`, (value) => value >= 0)
.required(t("EditDialog.edit_approved_amount_required")), .required(t("EditDialog.edit_approved_amount_required")),
}) });
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
approved_amount: String(row.original.approved_amount / 1000000) approved_amount: String(row.original.approved_amount / 1000000),
}, validationSchema,
onSubmit: (values, {setSubmitting}) => {
requestServer(`${EDIT_APPROVED_AMOUNT}/${rowId}`, 'post', {
data: {
approved_amount: values.approved_amount
}, },
notification: true validationSchema,
}).then(() => { onSubmit: (values, { setSubmitting }) => {
setOpenEditDialog(false) requestServer(`${EDIT_APPROVED_AMOUNT}/${rowId}`, "post", {
mutate() data: {
update_notification() approved_amount: values.approved_amount,
}).catch(() => { },
}).finally(() => { notification: true,
})
.then(() => {
setOpenEditDialog(false);
mutate();
update_notification();
})
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
}); });
const handleAmountChange = (event) => { const handleAmountChange = (event) => {
if (!isNaN(event.target.value)) { if (!isNaN(event.target.value)) {
formik.setFieldValue("approved_amount", event.target.value) formik.setFieldValue("approved_amount", event.target.value);
} else { } else {
formik.setFieldValue("approved_amount", formik.values.approved_amount) formik.setFieldValue("approved_amount", formik.values.approved_amount);
} }
}; };
return ( return (
@@ -62,8 +84,12 @@ const EditContent = ({rowId, row, mutate, setOpenEditDialog, vehicle_type}) => {
<Stack> <Stack>
<PriceField <PriceField
name="approved_amount" name="approved_amount"
label={<> label={
<span>{t("EditDialog.edit_approved_amount")}</span><small>{t("EditDialog.unit")}</small></>} <>
<span>{t("EditDialog.edit_approved_amount")}</span>
<small>{t("EditDialog.unit")}</small>
</>
}
type="text" type="text"
inputProps={{ inputProps={{
inputMode: "number", inputMode: "number",
@@ -74,13 +100,8 @@ const EditContent = ({rowId, row, mutate, setOpenEditDialog, vehicle_type}) => {
value={formik.values.approved_amount} value={formik.values.approved_amount}
onChange={handleAmountChange} onChange={handleAmountChange}
onBlur={formik.handleBlur("approved_amount")} onBlur={formik.handleBlur("approved_amount")}
error={ error={formik.touched.approved_amount && Boolean(formik.errors.approved_amount)}
formik.touched.approved_amount && helperText={formik.touched.approved_amount && formik.errors.approved_amount}
Boolean(formik.errors.approved_amount)
}
helperText={
formik.touched.approved_amount && formik.errors.approved_amount
}
sx={{ mt: 1 }} sx={{ mt: 1 }}
fullWidth fullWidth
/> />
@@ -88,18 +109,25 @@ const EditContent = ({rowId, row, mutate, setOpenEditDialog, vehicle_type}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenEditDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenEditDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("EditDialog.button-cancel")} {t("EditDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.isValid || !formik.dirty} disabled={formik.isSubmitting || !formik.isValid || !formik.dirty}
> >
{t("EditDialog.button-edit")} {t("EditDialog.button-edit")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
};
} export default EditContent;
export default EditContent

View File

@@ -1,7 +1,7 @@
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
import EditIcon from '@mui/icons-material/Edit'; import EditIcon from "@mui/icons-material/Edit";
import EditContent from "@/components/dashboard/bank-management/Form/Edit/EditContent"; import EditContent from "@/components/dashboard/bank-management/Form/Edit/EditContent";
const EditForm = ({ rowId, row, mutate, vehicle_type }) => { const EditForm = ({ rowId, row, mutate, vehicle_type }) => {
@@ -14,27 +14,33 @@ const EditForm = ({rowId, row, mutate, vehicle_type}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenEditDialog(true) setOpenEditDialog(true);
}} }}
> >
<EditIcon /> <EditIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openEditDialog} <Dialog
fullWidth
open={openEditDialog}
PaperProps={{ PaperProps={{
sx: { sx: {
transition: 'all .3s', transition: "all .3s",
boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px' boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
} },
}} maxWidth="sm"> }}
maxWidth="sm"
>
<DialogTitle>{t("EditDialog.edit_approved_amount")}</DialogTitle> <DialogTitle>{t("EditDialog.edit_approved_amount")}</DialogTitle>
<EditContent <EditContent
mutate={mutate} rowId={rowId} setOpenEditDialog={setOpenEditDialog} row={row} mutate={mutate}
rowId={rowId}
setOpenEditDialog={setOpenEditDialog}
row={row}
vehicle_type={vehicle_type} vehicle_type={vehicle_type}
/> />
</Dialog> </Dialog>
</> </>
) );
};
}
export default EditForm; export default EditForm;

View File

@@ -1,7 +1,7 @@
import UploadSystem from "@/core/components/UploadSystem" import UploadSystem from "@/core/components/UploadSystem";
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, FormHelperText, Stack, TextField, Typography} from "@mui/material" import { Button, DialogActions, DialogContent, FormHelperText, Stack, TextField, Typography } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
@@ -14,17 +14,18 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const [fileName, setfileName] = useState(null); const [fileName, setfileName] = useState(null);
const [showAddIcon, setShowAddIcon] = useState(true); const [showAddIcon, setShowAddIcon] = useState(true);
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
description: Yup.string().required(t("RejectDialog.description_error")), description: Yup.string().required(t("RejectDialog.description_error")),
reject_img: Yup.mixed().notRequired(t("RejectDialog.choose_file")) reject_img: Yup.mixed()
.test('fileSize', `${t("MachinaryOffice.upload_file_unit")}`, (value) => { .notRequired(t("RejectDialog.choose_file"))
.test("fileSize", `${t("MachinaryOffice.upload_file_unit")}`, (value) => {
return !value || (value.size && value.size <= 5 * 1024 * 1024); return !value || (value.size && value.size <= 5 * 1024 * 1024);
}) })
.test('fileType', `${t("MachinaryOffice.upload_file_format")}`, (value) => { .test("fileType", `${t("MachinaryOffice.upload_file_format")}`, (value) => {
const allowedTypes = ['image/jpg', 'image/jpeg', 'image/png', 'application/pdf']; // Define your allowed file types const allowedTypes = ["image/jpg", "image/jpeg", "image/png", "application/pdf"]; // Define your allowed file types
return !value || (value.type && allowedTypes.includes(value.type)); return !value || (value.type && allowedTypes.includes(value.type));
}), }),
}); });
@@ -32,7 +33,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
description: "", description: "",
reject_img: null reject_img: null,
}, },
validationSchema, validationSchema,
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
@@ -42,22 +43,24 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const attachments = [ const attachments = [
{ {
title: "فایل ضمیمه کارتابل نظارت بانک", title: "فایل ضمیمه کارتابل نظارت بانک",
file: values.reject_img file: values.reject_img,
} },
]; ];
attachments.forEach((attachment, index) => { attachments.forEach((attachment, index) => {
formData.append(`attachment[${index}][title]`, attachment.title); formData.append(`attachment[${index}][title]`, attachment.title);
formData.append(`attachment[${index}][file]`, attachment.file); formData.append(`attachment[${index}][file]`, attachment.file);
}); });
} }
requestServer(`${REJECT_BANK_MANAGEMENT}/${rowId}`, 'post', { requestServer(`${REJECT_BANK_MANAGEMENT}/${rowId}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenRejectDialog(false) .then((response) => {
mutate() setOpenRejectDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -73,7 +76,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
setfileName(fileName); setfileName(fileName);
formik.setFieldValue("reject_img", uploadedFile).then(() => { formik.setFieldValue("reject_img", uploadedFile).then(() => {
formik.setFieldTouched("reject_img", true); formik.setFieldTouched("reject_img", true);
}) });
setShowAddIcon(false); setShowAddIcon(false);
} }
}; };
@@ -90,9 +93,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
value={formik.values.description} value={formik.values.description}
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur("description")} onBlur={formik.handleBlur("description")}
error={ error={formik.touched.description && Boolean(formik.errors.description)}
formik.touched.description && Boolean(formik.errors.description)
}
helperText={formik.touched.description && formik.errors.description} helperText={formik.touched.description && formik.errors.description}
fullWidth fullWidth
variant="outlined" variant="outlined"
@@ -100,7 +101,10 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
/> />
</Stack> </Stack>
<Stack> <Stack>
<Typography>{t("UploadSystem.upload_file")}{t("UploadSystem.optional")}</Typography> <Typography>
{t("UploadSystem.upload_file")}
{t("UploadSystem.optional")}
</Typography>
<UploadSystem <UploadSystem
selectedImage={selectedImage} selectedImage={selectedImage}
handleUploadChange={handleUploadChange} // Pass the updated function directly handleUploadChange={handleUploadChange} // Pass the updated function directly
@@ -114,30 +118,34 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
setShowAddIcon={setShowAddIcon} setShowAddIcon={setShowAddIcon}
showAddIcon={showAddIcon} showAddIcon={showAddIcon}
onBlur={() => formik.handleBlur("reject_img")} onBlur={() => formik.handleBlur("reject_img")}
error={ error={formik.touched.reject_img && Boolean(formik.errors.reject_img)}
formik.touched.reject_img &&
Boolean(formik.errors.reject_img)
}
/> />
<FormHelperText <FormHelperText error={Boolean(formik.errors.reject_img)}>
error={Boolean(formik.errors.reject_img)}
>
{formik.touched.reject_img && formik.errors.reject_img} {formik.touched.reject_img && formik.errors.reject_img}
</FormHelperText> </FormHelperText>
</Stack> </Stack>
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenRejectDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenRejectDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("RejectDialog.button-cancel")} {t("RejectDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("RejectDialog.button-reject")} {t("RejectDialog.button-reject")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
} };
export default RejectContent export default RejectContent;

View File

@@ -1,4 +1,4 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material" import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
import RejectContent from "./RejectContent"; import RejectContent from "./RejectContent";
@@ -14,12 +14,19 @@ const RejectForm = ({rowId, mutate}) => {
<ThumbDownIcon /> <ThumbDownIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openRejectDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openRejectDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("RejectDialog.bank_management_reject")}</DialogTitle> <DialogTitle>{t("RejectDialog.bank_management_reject")}</DialogTitle>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} /> <RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} />
</Dialog> </Dialog>
</> </>
) );
} };
export default RejectForm export default RejectForm;

View File

@@ -8,9 +8,9 @@ import {
DialogTitle, DialogTitle,
IconButton, IconButton,
Tooltip, Tooltip,
Typography Typography,
} from "@mui/material"; } from "@mui/material";
import RefreshIcon from '@mui/icons-material/Refresh'; import RefreshIcon from "@mui/icons-material/Refresh";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import { RESEND_BANK_STATEMENT } from "@/core/data/apiRoutes"; import { RESEND_BANK_STATEMENT } from "@/core/data/apiRoutes";
@@ -18,20 +18,22 @@ import {RESEND_BANK_STATEMENT} from "@/core/data/apiRoutes";
const UpdateForm = ({ rowId, mutate }) => { const UpdateForm = ({ rowId, mutate }) => {
const t = useTranslations(); const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false); const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false) const [isSubmitting, setIsSubmitting] = useState(false);
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const handleSubmit = () => { const handleSubmit = () => {
setIsSubmitting(true) setIsSubmitting(true);
requestServer(`${RESEND_BANK_STATEMENT}/${rowId}`, 'post').then((response) => { requestServer(`${RESEND_BANK_STATEMENT}/${rowId}`, "post")
setOpenConfirmDialog(false) .then((response) => {
mutate() setOpenConfirmDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
setIsSubmitting(false) .catch(() => {})
.finally(() => {
setIsSubmitting(false);
}); });
} };
return ( return (
<> <>
@@ -39,25 +41,36 @@ const UpdateForm = ({rowId, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenConfirmDialog(true) setOpenConfirmDialog(true);
}} }}
> >
<RefreshIcon /> <RefreshIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog maxWidth="sm" open={openConfirmDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> maxWidth="sm"
open={openConfirmDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("UpdateDialog.resend")}</DialogTitle> <DialogTitle>{t("UpdateDialog.resend")}</DialogTitle>
<DialogContent> <DialogContent>
<Typography>{t("UpdateDialog.typography")}</Typography> <Typography>{t("UpdateDialog.typography")}</Typography>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary" <Button
disabled={isSubmitting} autoFocus> onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={isSubmitting}
autoFocus
>
{t("UpdateDialog.button-cancel")} {t("UpdateDialog.button-cancel")}
</Button> </Button>
<Button onClick={handleSubmit} variant="contained" color="primary" <Button onClick={handleSubmit} variant="contained" color="primary" disabled={isSubmitting}>
disabled={isSubmitting}>
{t("UpdateDialog.button-resend")} {t("UpdateDialog.button-resend")}
</Button> </Button>
</DialogActions> </DialogActions>

View File

@@ -7,29 +7,17 @@ const TableRow = ({row, mutate}) => {
return ( return (
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}> <Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
{(row.original.bank_status == 0 || (row.original.bank_status == 1 && row.original.bank_state == 8)) && ( {(row.original.bank_status == 0 || (row.original.bank_status == 1 && row.original.bank_state == 8)) && (
<UpdateForm <UpdateForm rowId={row.getValue("id")} mutate={mutate} />
rowId={row.getValue("id")}
mutate={mutate}
/>
)} )}
{ {row.original.bank_state == 8 && <RejectForm rowId={row.getValue("id")} mutate={mutate} />}
row.original.bank_state == 8 && ( {row.original.bank_state == 8 && (
<RejectForm
rowId={row.getValue("id")}
mutate={mutate}
/>
)
}
{
row.original.bank_state == 8 && (
<EditForm <EditForm
rowId={row.getValue("id")} rowId={row.getValue("id")}
mutate={mutate} mutate={mutate}
vehicle_type={row.original.vehicle_type} vehicle_type={row.original.vehicle_type}
row={row} row={row}
/> />
) )}
}
</Box> </Box>
); );
}; };

View File

@@ -2,12 +2,11 @@ import {Stack} from "@mui/material";
import PrintExcel from "@/components/dashboard/bank-management/Buttons/printExcel"; import PrintExcel from "@/components/dashboard/bank-management/Buttons/printExcel";
const TableToolbar = ({ table }) => { const TableToolbar = ({ table }) => {
return ( return (
<Stack direction={"row"} spacing={2}> <Stack direction={"row"} spacing={2}>
<PrintExcel table={table} /> <PrintExcel table={table} />
</Stack> </Stack>
) );
} };
export default TableToolbar export default TableToolbar;

View File

@@ -18,17 +18,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.navgan_id, accessorFn: (row) => row.navgan_id,
@@ -37,17 +28,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.name, accessorFn: (row) => row.name,
@@ -57,9 +39,7 @@ function DashboardBankManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_id, accessorFn: (row) => row.national_id,
@@ -68,17 +48,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_serial_number, accessorFn: (row) => row.national_serial_number,
@@ -87,17 +58,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_tracking_code, accessorFn: (row) => row.national_tracking_code,
@@ -106,14 +68,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "text", datatype: "text",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.birthday, accessorFn: (row) => row.birthday,
@@ -124,8 +80,9 @@ function DashboardBankManagementComponent() {
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({ renderedCellValue }) => ( Cell: ({ renderedCellValue }) => (
<Typography <Typography variant="body2">
variant="body2">{moment(renderedCellValue).locale("fa").format("yyyy/MM/DD")}</Typography> {moment(renderedCellValue).locale("fa").format("yyyy/MM/DD")}
</Typography>
), ),
}, },
{ {
@@ -135,11 +92,7 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "text", datatype: "text",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains"],
"equals",
"notEquals",
"contains",
],
Cell: ({ renderedCellValue }) => ( Cell: ({ renderedCellValue }) => (
<Typography variant="body2">{Number(renderedCellValue).toLocaleString()}</Typography> <Typography variant="body2">{Number(renderedCellValue).toLocaleString()}</Typography>
), ),
@@ -151,14 +104,7 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({ renderedCellValue }) => ( Cell: ({ renderedCellValue }) => (
<Typography variant="body2">{Number(renderedCellValue).toLocaleString()}</Typography> <Typography variant="body2">{Number(renderedCellValue).toLocaleString()}</Typography>
), ),
@@ -171,9 +117,7 @@ function DashboardBankManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.bank_state_name, accessorFn: (row) => row.bank_state_name,
@@ -182,14 +126,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "text", datatype: "text",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains"
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.bank_reason_description, accessorFn: (row) => row.bank_reason_description,
@@ -198,15 +136,9 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "text", datatype: "text",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals", },
"contains"
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}
], ],
[] []
); );
@@ -219,12 +151,15 @@ function DashboardBankManagementComponent() {
enableCustomToolbar={true} enableCustomToolbar={true}
CustomToolbar={TableToolbar} CustomToolbar={TableToolbar}
enableLastUpdate={true} enableLastUpdate={true}
sorting={[{ sorting={[
id: 'score', desc: false {
}]} id: "score",
desc: false,
},
]}
enablePinning={true} enablePinning={true}
enableDensityToggle={false} enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large) initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true} enableColumnFilters={true}
enableHiding={true} enableHiding={true}
enableFullScreenToggle={false} enableFullScreenToggle={false}

View File

@@ -9,19 +9,21 @@ import PasswordField from "@/core/components/PasswordField";
const ChangePasswordForm = ({ onSubmit }) => { const ChangePasswordForm = ({ onSubmit }) => {
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const handleSubmit = (values, { setSubmitting, resetForm }) => { const handleSubmit = (values, { setSubmitting, resetForm }) => {
requestServer(SET_USER_PASSWORD, 'post', { requestServer(SET_USER_PASSWORD, "post", {
data: { data: {
current_password: values.current_password, current_password: values.current_password,
new_password: values.new_password, new_password: values.new_password,
new_password_confirmation: values.new_password_confirmation, new_password_confirmation: values.new_password_confirmation,
}, },
}).then((response) => { })
.then((response) => {
resetForm(); resetForm();
}).catch(() => { })
}).finally(() => { .catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}; };
@@ -31,15 +33,10 @@ const ChangePasswordForm = ({onSubmit}) => {
new_password_confirmation: "", new_password_confirmation: "",
}; };
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
current_password: Yup.string().required( current_password: Yup.string().required(t("ChangePassword.error_message_current_password")),
t("ChangePassword.error_message_current_password")
),
new_password: Yup.string() new_password: Yup.string()
.required(t("ExpertMangement.error_message_new_password")) .required(t("ExpertMangement.error_message_new_password"))
.matches( .matches(/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/, t("ExpertMangement.error_message_new_password_regex")),
/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/,
t("ExpertMangement.error_message_new_password_regex")
),
new_password_confirmation: Yup.string() new_password_confirmation: Yup.string()
.required(t("ChangePassword.error_message_confirm_password")) .required(t("ChangePassword.error_message_confirm_password"))
.test( .test(
@@ -52,11 +49,7 @@ const ChangePasswordForm = ({onSubmit}) => {
}); });
return ( return (
<Formik <Formik initialValues={initialValues} onSubmit={handleSubmit} validationSchema={validationSchema}>
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => ( {(props) => (
<StyledForm <StyledForm
onSubmit={(e) => { onSubmit={(e) => {
@@ -74,30 +67,17 @@ const ChangePasswordForm = ({onSubmit}) => {
name="current_password" name="current_password"
label={t("ChangePassword.label_current_password")} label={t("ChangePassword.label_current_password")}
error={ error={
props.touched.current_password && props.touched.current_password && props.errors.current_password ? true : false
props.errors.current_password
? true
: false
}
helperText={
props.touched.current_password
? props.errors.current_password
: null
} }
helperText={props.touched.current_password ? props.errors.current_password : null}
/> />
</Stack> </Stack>
<Stack spacing={1} component="div"> <Stack spacing={1} component="div">
<PasswordField <PasswordField
name="new_password" name="new_password"
label={t("ChangePassword.label_new_password")} label={t("ChangePassword.label_new_password")}
error={ error={props.touched.new_password && props.errors.new_password ? true : false}
props.touched.new_password && props.errors.new_password helperText={props.touched.new_password ? props.errors.new_password : null}
? true
: false
}
helperText={
props.touched.new_password ? props.errors.new_password : null
}
/> />
</Stack> </Stack>
<Stack spacing={1} component="div"> <Stack spacing={1} component="div">

View File

@@ -1,7 +1,7 @@
import UploadSystem from "@/core/components/UploadSystem"; import UploadSystem from "@/core/components/UploadSystem";
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField, Typography} from "@mui/material" import { Button, DialogActions, DialogContent, Stack, TextField, Typography } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { CONFIRM_COMMERCIAL_CHIEF } from "@/core/data/apiRoutes"; import { CONFIRM_COMMERCIAL_CHIEF } from "@/core/data/apiRoutes";
@@ -14,34 +14,36 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
const [fileType, setfileType] = useState(null); const [fileType, setfileType] = useState(null);
const [fileName, setfileName] = useState(null); const [fileName, setfileName] = useState(null);
const [showAddIcon, setShowAddIcon] = useState(true); const [showAddIcon, setShowAddIcon] = useState(true);
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
description: "", description: "",
confirm_img: null confirm_img: null,
}, },
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
const formData = new FormData(); const formData = new FormData();
if (values.description != "") formData.append("description", values.description); if (values.description != "") formData.append("description", values.description);
if (values.confirm_img != null) formData.append("attachment", values.confirm_img); if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
requestServer(`${CONFIRM_COMMERCIAL_CHIEF}/${rowId}`, 'post', { requestServer(`${CONFIRM_COMMERCIAL_CHIEF}/${rowId}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenConfirmDialog(false) .then((response) => {
update_notification() setOpenConfirmDialog(false);
mutate() update_notification();
}).catch(() => { mutate();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
}); });
const handleDescriptionChange = (event) => { const handleDescriptionChange = (event) => {
formik.setFieldValue("description", event.target.value) formik.setFieldValue("description", event.target.value);
}; };
const handleUploadChange = (event) => { const handleUploadChange = (event) => {
@@ -73,8 +75,12 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
name="description" name="description"
multiline multiline
rows={8} rows={8}
label={<> label={
<span>{t("ConfirmDialog.description")}</span><small>{t("ConfirmDialog.optional")}</small></>} <>
<span>{t("ConfirmDialog.description")}</span>
<small>{t("ConfirmDialog.optional")}</small>
</>
}
value={formik.values.description} value={formik.values.description}
onChange={handleDescriptionChange} onChange={handleDescriptionChange}
fullWidth fullWidth
@@ -83,7 +89,10 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
/> />
</Stack> </Stack>
<Stack> <Stack>
<Typography>{t("UploadSystem.upload_file")}{t("UploadSystem.optional")}</Typography> <Typography>
{t("UploadSystem.upload_file")}
{t("UploadSystem.optional")}
</Typography>
<UploadSystem <UploadSystem
selectedImage={selectedImage} selectedImage={selectedImage}
handleUploadChange={handleUploadChange} // Pass the updated function directly handleUploadChange={handleUploadChange} // Pass the updated function directly
@@ -101,17 +110,25 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ConfirmDialog.button-cancel")} {t("ConfirmDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting}
>
{t("ConfirmDialog.button-confirm")} {t("ConfirmDialog.button-confirm")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
};
} export default ConfirmContent;
export default ConfirmContent

View File

@@ -13,19 +13,25 @@ const Confirm = ({rowId, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenConfirmDialog(true) setOpenConfirmDialog(true);
}} }}
> >
<ThumbUpAltIcon /> <ThumbUpAltIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openConfirmDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openConfirmDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle> <DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
<ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} /> <ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog> </Dialog>
</> </>
) );
};
}
export default Confirm; export default Confirm;

View File

@@ -1,7 +1,7 @@
import UploadSystem from "@/core/components/UploadSystem" import UploadSystem from "@/core/components/UploadSystem";
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField, Typography} from "@mui/material" import { Button, DialogActions, DialogContent, Stack, TextField, Typography } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
@@ -14,8 +14,8 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const [fileName, setfileName] = useState(null); const [fileName, setfileName] = useState(null);
const [showAddIcon, setShowAddIcon] = useState(true); const [showAddIcon, setShowAddIcon] = useState(true);
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
description: Yup.string().required(t("RejectDialog.description_error")), description: Yup.string().required(t("RejectDialog.description_error")),
@@ -24,7 +24,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
description: "", description: "",
reject_img: null reject_img: null,
}, },
validationSchema, validationSchema,
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
@@ -32,14 +32,16 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
formData.append("description", values.description); formData.append("description", values.description);
if (values.reject_img != null) formData.append("attachment", values.reject_img); if (values.reject_img != null) formData.append("attachment", values.reject_img);
requestServer(`${REJECT_COMMERCIAL_CHIEF}/${rowId}`, 'post', { requestServer(`${REJECT_COMMERCIAL_CHIEF}/${rowId}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenRejectDialog(false) .then((response) => {
mutate() setOpenRejectDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -80,9 +82,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
value={formik.values.description} value={formik.values.description}
onChange={handleDescriptionChange} onChange={handleDescriptionChange}
onBlur={formik.handleBlur("description")} onBlur={formik.handleBlur("description")}
error={ error={formik.touched.description && Boolean(formik.errors.description)}
formik.touched.description && Boolean(formik.errors.description)
}
helperText={formik.touched.description && formik.errors.description} helperText={formik.touched.description && formik.errors.description}
fullWidth fullWidth
variant="outlined" variant="outlined"
@@ -90,7 +90,10 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
/> />
</Stack> </Stack>
<Stack> <Stack>
<Typography>{t("UploadSystem.upload_file")}{t("UploadSystem.optional")}</Typography> <Typography>
{t("UploadSystem.upload_file")}
{t("UploadSystem.optional")}
</Typography>
<UploadSystem <UploadSystem
selectedImage={selectedImage} selectedImage={selectedImage}
handleUploadChange={handleUploadChange} // Pass the updated function directly handleUploadChange={handleUploadChange} // Pass the updated function directly
@@ -108,16 +111,25 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenRejectDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenRejectDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("RejectDialog.button-cancel")} {t("RejectDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("RejectDialog.button-reject")} {t("RejectDialog.button-reject")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
} };
export default RejectContent export default RejectContent;

View File

@@ -1,4 +1,4 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material" import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
import RejectContent from "./RejectContent"; import RejectContent from "./RejectContent";
@@ -14,12 +14,19 @@ const Reject = ({rowId, mutate}) => {
<ThumbDownIcon /> <ThumbDownIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openRejectDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openRejectDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle> <DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} /> <RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} />
</Dialog> </Dialog>
</> </>
) );
} };
export default Reject export default Reject;

View File

@@ -5,14 +5,8 @@ import Reject from "./Form/RejectForm";
const TableRow = ({ row, mutate }) => { const TableRow = ({ row, mutate }) => {
return ( return (
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}> <Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
<Confirm <Confirm rowId={row.getValue("id")} mutate={mutate} />
rowId={row.getValue("id")} <Reject rowId={row.getValue("id")} mutate={mutate} />
mutate={mutate}
/>
<Reject
rowId={row.getValue("id")}
mutate={mutate}
/>
</Box> </Box>
); );
}; };

View File

@@ -18,17 +18,8 @@ function DashboardCommercialChiefComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.name, accessorFn: (row) => row.name,
@@ -38,9 +29,7 @@ function DashboardCommercialChiefComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_id, accessorFn: (row) => row.national_id,
@@ -49,17 +38,8 @@ function DashboardCommercialChiefComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.phone_number, accessorFn: (row) => row.phone_number,
@@ -68,21 +48,11 @@ function DashboardCommercialChiefComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "created_at", id: "created_at",
header: t("CommercialChief.created_at"), header: t("CommercialChief.created_at"),
enableColumnFilter: true, enableColumnFilter: true,
@@ -94,21 +64,16 @@ function DashboardCommercialChiefComponent() {
}, },
Header: ({ column }) => <>{column.columnDef.header}</>, Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => { Filter: ({ column }) => {
return ( return <MuiDatePicker column={column} />;
<MuiDatePicker column={column}/>
);
}, },
}, },
{ {
accessorFn: (row) => accessorFn: (row) => moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "updated_at", id: "updated_at",
header: t("CommercialChief.updated_at"), header: t("CommercialChief.updated_at"),
enableColumnFilter: false, enableColumnFilter: false,
datatype: "numeric", datatype: "numeric",
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.state_name, accessorFn: (row) => row.state_name,
@@ -116,9 +81,7 @@ function DashboardCommercialChiefComponent() {
header: t("CommercialChief.state_name"), header: t("CommercialChief.state_name"),
enableColumnFilter: false, enableColumnFilter: false,
datatype: "numeric", datatype: "numeric",
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
], ],
[] []
@@ -132,12 +95,15 @@ function DashboardCommercialChiefComponent() {
selectableRow={false} selectableRow={false}
enableCustomToolbar={false} enableCustomToolbar={false}
enableLastUpdate={true} enableLastUpdate={true}
sorting={[{ sorting={[
id: 'id', desc: false {
}]} id: "id",
desc: false,
},
]}
enablePinning={true} enablePinning={true}
enableDensityToggle={false} enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large) initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true} enableColumnFilters={true}
enableHiding={true} enableHiding={true}
enableFullScreenToggle={false} enableFullScreenToggle={false}

View File

@@ -1,7 +1,7 @@
import UploadSystem from "@/core/components/UploadSystem"; import UploadSystem from "@/core/components/UploadSystem";
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField, Typography} from "@mui/material" import { Button, DialogActions, DialogContent, Stack, TextField, Typography } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { CONFIRM_DEVELOPMENT_ASSISTANT } from "@/core/data/apiRoutes"; import { CONFIRM_DEVELOPMENT_ASSISTANT } from "@/core/data/apiRoutes";
@@ -14,34 +14,36 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
const [fileType, setfileType] = useState(null); const [fileType, setfileType] = useState(null);
const [fileName, setfileName] = useState(null); const [fileName, setfileName] = useState(null);
const [showAddIcon, setShowAddIcon] = useState(true); const [showAddIcon, setShowAddIcon] = useState(true);
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
description: "", description: "",
confirm_img: null confirm_img: null,
}, },
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
const formData = new FormData(); const formData = new FormData();
if (values.description != "") formData.append("description", values.description); if (values.description != "") formData.append("description", values.description);
if (values.confirm_img != null) formData.append("attachment", values.confirm_img); if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
requestServer(`${CONFIRM_DEVELOPMENT_ASSISTANT}/${rowId}`, 'post', { requestServer(`${CONFIRM_DEVELOPMENT_ASSISTANT}/${rowId}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenConfirmDialog(false) .then((response) => {
mutate() setOpenConfirmDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
}); });
const handleDescriptionChange = (event) => { const handleDescriptionChange = (event) => {
formik.setFieldValue("description", event.target.value) formik.setFieldValue("description", event.target.value);
}; };
const handleUploadChange = (event) => { const handleUploadChange = (event) => {
@@ -73,8 +75,12 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
name="description" name="description"
multiline multiline
rows={8} rows={8}
label={<> label={
<span>{t("ConfirmDialog.description")}</span><small>{t("ConfirmDialog.optional")}</small></>} <>
<span>{t("ConfirmDialog.description")}</span>
<small>{t("ConfirmDialog.optional")}</small>
</>
}
value={formik.values.description} value={formik.values.description}
onChange={handleDescriptionChange} onChange={handleDescriptionChange}
fullWidth fullWidth
@@ -83,7 +89,10 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
/> />
</Stack> </Stack>
<Stack> <Stack>
<Typography>{t("UploadSystem.upload_file")}{t("UploadSystem.optional")}</Typography> <Typography>
{t("UploadSystem.upload_file")}
{t("UploadSystem.optional")}
</Typography>
<UploadSystem <UploadSystem
selectedImage={selectedImage} selectedImage={selectedImage}
handleUploadChange={handleUploadChange} // Pass the updated function directly handleUploadChange={handleUploadChange} // Pass the updated function directly
@@ -101,17 +110,25 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ConfirmDialog.button-cancel")} {t("ConfirmDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting}
>
{t("ConfirmDialog.button-confirm")} {t("ConfirmDialog.button-confirm")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
};
} export default ConfirmContent;
export default ConfirmContent

View File

@@ -13,19 +13,25 @@ const Confirm = ({rowId, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenConfirmDialog(true) setOpenConfirmDialog(true);
}} }}
> >
<ThumbUpAltIcon /> <ThumbUpAltIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openConfirmDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openConfirmDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle> <DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
<ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} /> <ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog> </Dialog>
</> </>
) );
};
}
export default Confirm; export default Confirm;

View File

@@ -1,7 +1,7 @@
import UploadSystem from "@/core/components/UploadSystem" import UploadSystem from "@/core/components/UploadSystem";
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField, Typography} from "@mui/material" import { Button, DialogActions, DialogContent, Stack, TextField, Typography } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
@@ -14,8 +14,8 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const [fileName, setfileName] = useState(null); const [fileName, setfileName] = useState(null);
const [showAddIcon, setShowAddIcon] = useState(true); const [showAddIcon, setShowAddIcon] = useState(true);
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
description: Yup.string().required(t("RejectDialog.description_error")), description: Yup.string().required(t("RejectDialog.description_error")),
@@ -24,7 +24,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
description: "", description: "",
reject_img: null reject_img: null,
}, },
validationSchema, validationSchema,
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
@@ -32,14 +32,16 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
formData.append("description", values.description); formData.append("description", values.description);
if (values.reject_img != null) formData.append("attachment", values.reject_img); if (values.reject_img != null) formData.append("attachment", values.reject_img);
requestServer(`${REJECT_DEVELOPMENT_ASSISTANT}/${rowId}`, 'post', { requestServer(`${REJECT_DEVELOPMENT_ASSISTANT}/${rowId}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenRejectDialog(false) .then((response) => {
mutate() setOpenRejectDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -80,9 +82,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
value={formik.values.description} value={formik.values.description}
onChange={handleDescriptionChange} onChange={handleDescriptionChange}
onBlur={formik.handleBlur("description")} onBlur={formik.handleBlur("description")}
error={ error={formik.touched.description && Boolean(formik.errors.description)}
formik.touched.description && Boolean(formik.errors.description)
}
helperText={formik.touched.description && formik.errors.description} helperText={formik.touched.description && formik.errors.description}
fullWidth fullWidth
variant="outlined" variant="outlined"
@@ -90,7 +90,10 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
/> />
</Stack> </Stack>
<Stack> <Stack>
<Typography>{t("UploadSystem.upload_file")}{t("UploadSystem.optional")}</Typography> <Typography>
{t("UploadSystem.upload_file")}
{t("UploadSystem.optional")}
</Typography>
<UploadSystem <UploadSystem
selectedImage={selectedImage} selectedImage={selectedImage}
handleUploadChange={handleUploadChange} // Pass the updated function directly handleUploadChange={handleUploadChange} // Pass the updated function directly
@@ -108,16 +111,25 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenRejectDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenRejectDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("RejectDialog.button-cancel")} {t("RejectDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("RejectDialog.button-reject")} {t("RejectDialog.button-reject")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
} };
export default RejectContent export default RejectContent;

View File

@@ -1,4 +1,4 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material" import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
import RejectContent from "./RejectContent"; import RejectContent from "./RejectContent";
@@ -14,12 +14,19 @@ const Reject = ({rowId, mutate}) => {
<ThumbDownIcon /> <ThumbDownIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openRejectDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openRejectDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle> <DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} /> <RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} />
</Dialog> </Dialog>
</> </>
) );
} };
export default Reject export default Reject;

View File

@@ -3,17 +3,10 @@ import Confirm from "./Form/ConfirmForm";
import Reject from "./Form/RejectForm"; import Reject from "./Form/RejectForm";
const TableRow = ({ row, mutate }) => { const TableRow = ({ row, mutate }) => {
return ( return (
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}> <Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
<Confirm <Confirm rowId={row.getValue("id")} mutate={mutate} />
rowId={row.getValue("id")} <Reject rowId={row.getValue("id")} mutate={mutate} />
mutate={mutate}
/>
<Reject
rowId={row.getValue("id")}
mutate={mutate}
/>
</Box> </Box>
); );
}; };

View File

@@ -19,17 +19,8 @@ function DashboardDevelopmentAssistantComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.name, accessorFn: (row) => row.name,
@@ -39,9 +30,7 @@ function DashboardDevelopmentAssistantComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_id, accessorFn: (row) => row.national_id,
@@ -50,17 +39,8 @@ function DashboardDevelopmentAssistantComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.phone_number, accessorFn: (row) => row.phone_number,
@@ -69,21 +49,11 @@ function DashboardDevelopmentAssistantComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "created_at", id: "created_at",
header: t("DevelopmentAssistant.created_at"), header: t("DevelopmentAssistant.created_at"),
enableColumnFilter: true, enableColumnFilter: true,
@@ -95,21 +65,16 @@ function DashboardDevelopmentAssistantComponent() {
}, },
Header: ({ column }) => <>{column.columnDef.header}</>, Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => { Filter: ({ column }) => {
return ( return <MuiDatePicker column={column} />;
<MuiDatePicker column={column}/>
);
}, },
}, },
{ {
accessorFn: (row) => accessorFn: (row) => moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "updated_at", id: "updated_at",
header: t("DevelopmentAssistant.updated_at"), header: t("DevelopmentAssistant.updated_at"),
enableColumnFilter: false, enableColumnFilter: false,
datatype: "numeric", datatype: "numeric",
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.state_name, accessorFn: (row) => row.state_name,
@@ -117,9 +82,7 @@ function DashboardDevelopmentAssistantComponent() {
header: t("DevelopmentAssistant.state_name"), header: t("DevelopmentAssistant.state_name"),
enableColumnFilter: false, enableColumnFilter: false,
datatype: "numeric", datatype: "numeric",
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
], ],
[] []
@@ -135,10 +98,13 @@ function DashboardDevelopmentAssistantComponent() {
enableLastUpdate={true} enableLastUpdate={true}
enablePinning={true} enablePinning={true}
enableDensityToggle={false} enableDensityToggle={false}
sorting={[{ sorting={[
id: 'id', desc: false {
}]} id: "id",
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large) desc: false,
},
]}
initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true} enableColumnFilters={true}
enableHiding={true} enableHiding={true}
enableFullScreenToggle={false} enableFullScreenToggle={false}

View File

@@ -1,7 +1,7 @@
import StyledForm from "@/core/components/StyledForm"; import StyledForm from "@/core/components/StyledForm";
import CenterLayout from "@/layouts/CenterLayout"; import CenterLayout from "@/layouts/CenterLayout";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import {Container, Grid, Paper, Stack, TextField, Typography,} from "@mui/material"; import { Container, Grid, Paper, Stack, TextField, Typography } from "@mui/material";
import * as Yup from "yup"; import * as Yup from "yup";
import { Field, Formik } from "formik"; import { Field, Formik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
@@ -10,10 +10,8 @@ import useDirection from "@/lib/app/hooks/useDirection";
const DashboardEditProfile = () => { const DashboardEditProfile = () => {
const t = useTranslations(); const t = useTranslations();
const { user, token, getUser, changeUser } = useUser(); const { user, token, getUser, changeUser } = useUser();
const {directionApp} = useDirection() const { directionApp } = useDirection();
const handleSubmit = (values, {setSubmitting}) => { const handleSubmit = (values, { setSubmitting }) => {};
};
const initialValues = { const initialValues = {
expert_avatar: null, expert_avatar: null,
username: user.username, username: user.username,
@@ -27,11 +25,7 @@ const DashboardEditProfile = () => {
return ( return (
<CenterLayout> <CenterLayout>
<Container maxWidth="sm"> <Container maxWidth="sm">
<Formik <Formik initialValues={initialValues} onSubmit={handleSubmit} validationSchema={validationSchema}>
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => ( {(props) => (
<StyledForm <StyledForm
onSubmit={(e) => { onSubmit={(e) => {
@@ -54,16 +48,8 @@ const DashboardEditProfile = () => {
margin="normal" margin="normal"
size="small" size="small"
disabled={true} disabled={true}
error={ error={props.touched.username && props.errors.username ? true : false}
props.touched.username && props.errors.username helperText={props.touched.username ? props.errors.username : null}
? true
: false
}
helperText={
props.touched.username
? props.errors.username
: null
}
sx={{ sx={{
width: "100%", width: "100%",
}} }}
@@ -78,14 +64,8 @@ const DashboardEditProfile = () => {
margin="normal" margin="normal"
size="small" size="small"
disabled={true} disabled={true}
error={ error={props.touched.name && props.errors.name ? true : false}
props.touched.name && props.errors.name helperText={props.touched.name ? props.errors.name : null}
? true
: false
}
helperText={
props.touched.name ? props.errors.name : null
}
sx={{ sx={{
width: "100%", width: "100%",
}} }}
@@ -100,14 +80,8 @@ const DashboardEditProfile = () => {
margin="normal" margin="normal"
size="small" size="small"
disabled={true} disabled={true}
error={ error={props.touched.email && props.errors.email ? true : false}
props.touched.email && props.errors.email helperText={props.touched.email ? props.errors.email : null}
? true
: false
}
helperText={
props.touched.email ? props.errors.email : null
}
sx={{ sx={{
width: "100%", width: "100%",
}} }}
@@ -124,15 +98,12 @@ const DashboardEditProfile = () => {
size="small" size="small"
disabled={true} disabled={true}
error={ error={
props.touched.province_name && props.touched.province_name && props.errors.province_name
props.errors.province_name
? true ? true
: false : false
} }
helperText={ helperText={
props.touched.province_name props.touched.province_name ? props.errors.province_name : null
? props.errors.province_name
: null
} }
sx={{ sx={{
width: "100%", width: "100%",
@@ -148,16 +119,8 @@ const DashboardEditProfile = () => {
margin="normal" margin="normal"
size="small" size="small"
disabled={true} disabled={true}
error={ error={props.touched.position && props.errors.position ? true : false}
props.touched.position && props.errors.position helperText={props.touched.position ? props.errors.position : null}
? true
: false
}
helperText={
props.touched.position
? props.errors.position
: null
}
sx={{ sx={{
width: "100%", width: "100%",
}} }}

View File

@@ -7,7 +7,6 @@ import {Visibility, VisibilityOff} from "@mui/icons-material";
import { useState } from "react"; import { useState } from "react";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
const ChnagePasswordContent = ({ rowId, mutate, setOpenChangePasswordDialog }) => { const ChnagePasswordContent = ({ rowId, mutate, setOpenChangePasswordDialog }) => {
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest(); const requestServer = useRequest();
@@ -20,10 +19,7 @@ const ChnagePasswordContent = ({rowId, mutate, setOpenChangePasswordDialog}) =>
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
new_password: Yup.string() new_password: Yup.string()
.required(t("ExpertMangement.error_message_new_password")) .required(t("ExpertMangement.error_message_new_password"))
.matches( .matches(/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/, t("ExpertMangement.error_message_new_password_regex")),
/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/,
t("ExpertMangement.error_message_new_password_regex")
),
}); });
const formik = useFormik({ const formik = useFormik({
@@ -35,15 +31,16 @@ const ChnagePasswordContent = ({rowId, mutate, setOpenChangePasswordDialog}) =>
const formData = new FormData(); const formData = new FormData();
formData.append("new_password", values.new_password); formData.append("new_password", values.new_password);
requestServer(`${CHANGE_PASSWORD_EXPERT_MANAGEMENT}/${rowId}`, 'post', { requestServer(`${CHANGE_PASSWORD_EXPERT_MANAGEMENT}/${rowId}`, "post", {
auth: true, auth: true,
data: formData data: formData,
}) })
.then((response) => { .then((response) => {
setOpenChangePasswordDialog(false) setOpenChangePasswordDialog(false);
mutate() mutate();
}).catch(() => { })
}).finally(() => { .catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -62,7 +59,9 @@ const ChnagePasswordContent = ({rowId, mutate, setOpenChangePasswordDialog}) =>
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
error={formik.touched.new_password && !!formik.errors.new_password} error={formik.touched.new_password && !!formik.errors.new_password}
helperText={formik.touched.new_password && formik.errors.new_password ? formik.errors.new_password : null} helperText={
formik.touched.new_password && formik.errors.new_password ? formik.errors.new_password : null
}
type={showPassword ? "text" : "password"} type={showPassword ? "text" : "password"}
InputProps={{ InputProps={{
endAdornment: ( endAdornment: (
@@ -77,12 +76,21 @@ const ChnagePasswordContent = ({rowId, mutate, setOpenChangePasswordDialog}) =>
/> />
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenChangePasswordDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenChangePasswordDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ExpertMangement.button-cancel")} {t("ExpertMangement.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("ExpertMangement.button-confirm")} {t("ExpertMangement.button-confirm")}
</Button> </Button>
</DialogActions> </DialogActions>

View File

@@ -1,10 +1,9 @@
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import KeyIcon from '@mui/icons-material/Key'; import KeyIcon from "@mui/icons-material/Key";
import { useState } from "react"; import { useState } from "react";
import ChangePasswordContent from "./ChangePasswordContent"; import ChangePasswordContent from "./ChangePasswordContent";
const ChangePassword = ({ rowId, mutate }) => { const ChangePassword = ({ rowId, mutate }) => {
const t = useTranslations(); const t = useTranslations();
const [openChnagePasswordDialog, setOpenChangePasswordDialog] = useState(false); const [openChnagePasswordDialog, setOpenChangePasswordDialog] = useState(false);
@@ -15,17 +14,28 @@ const ChangePassword = ({rowId, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenChangePasswordDialog(true) setOpenChangePasswordDialog(true);
}} }}
> >
<KeyIcon /> <KeyIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth maxWidth={'xs'} open={openChnagePasswordDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
maxWidth={"xs"}
open={openChnagePasswordDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("ExpertMangement.change_password")}</DialogTitle> <DialogTitle>{t("ExpertMangement.change_password")}</DialogTitle>
<ChangePasswordContent rowId={rowId} mutate={mutate} <ChangePasswordContent
setOpenChangePasswordDialog={setOpenChangePasswordDialog}/> rowId={rowId}
mutate={mutate}
setOpenChangePasswordDialog={setOpenChangePasswordDialog}
/>
</Dialog> </Dialog>
</> </>
); );

View File

@@ -27,7 +27,7 @@ import {Visibility, VisibilityOff} from "@mui/icons-material";
const CreateContent = ({ setOpenCreateDialog, mutate }) => { const CreateContent = ({ setOpenCreateDialog, mutate }) => {
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest() const requestServer = useRequest();
const [cityList, setCityList] = useState([]); const [cityList, setCityList] = useState([]);
const [cityTextField, setCityTextField] = useState(t("ExpertMangement.text_field_please_select_province")); const [cityTextField, setCityTextField] = useState(t("ExpertMangement.text_field_please_select_province"));
const { provinceList, isLoadingProvinceList, errorProvinceList } = useProvince(); const { provinceList, isLoadingProvinceList, errorProvinceList } = useProvince();
@@ -40,8 +40,8 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
function getCities(province_id) { function getCities(province_id) {
formik.setFieldTouched("city_id", false, false); formik.setFieldTouched("city_id", false, false);
formik.setFieldValue("city_id", "") formik.setFieldValue("city_id", "");
setCityTextField(t("ExpertMangement.text_field_loading_cities_list")) setCityTextField(t("ExpertMangement.text_field_loading_cities_list"));
requestServer(`${GET_CITY_LIST}?province_id=${province_id}`, "get", { auth: true, notification: false }) requestServer(`${GET_CITY_LIST}?province_id=${province_id}`, "get", { auth: true, notification: false })
.then(({ data }) => { .then(({ data }) => {
const result = data.data; const result = data.data;
@@ -51,13 +51,13 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
value: city.id, value: city.id,
})); }));
setCityList(formattedData); setCityList(formattedData);
setCityTextField(t("ExpertMangement.text_field_city_id")) setCityTextField(t("ExpertMangement.text_field_city_id"));
}).catch(() => { })
setCityTextField(t("ExpertMangement.text_field_error_fetching_cities")) .catch(() => {
setCityTextField(t("ExpertMangement.text_field_error_fetching_cities"));
}); });
} }
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
name: Yup.string().required(t("ExpertMangement.error_message_name")), name: Yup.string().required(t("ExpertMangement.error_message_name")),
username: Yup.string().required(t("ExpertMangement.error_message_username")), username: Yup.string().required(t("ExpertMangement.error_message_username")),
@@ -66,14 +66,11 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
national_id: Yup.string().required(t("ExpertMangement.error_message_national_id")), national_id: Yup.string().required(t("ExpertMangement.error_message_national_id")),
password: Yup.string() password: Yup.string()
.required(t("ExpertMangement.error_message_password")) .required(t("ExpertMangement.error_message_password"))
.matches( .matches(/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/, t("ExpertMangement.error_message_password_regex")),
/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/,
t("ExpertMangement.error_message_password_regex")
),
position: Yup.string().required(t("ExpertMangement.error_message_position")), position: Yup.string().required(t("ExpertMangement.error_message_position")),
province_id: Yup.string().required(t("ExpertMangement.error_message_province_id")), province_id: Yup.string().required(t("ExpertMangement.error_message_province_id")),
city_id: Yup.string(), city_id: Yup.string(),
role_id: Yup.string().required(t("ExpertMangement.error_message_role_id")) role_id: Yup.string().required(t("ExpertMangement.error_message_role_id")),
}); });
const formik = useFormik({ const formik = useFormik({
@@ -87,7 +84,7 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
position: "", position: "",
province_id: "", province_id: "",
city_id: "", city_id: "",
role_id: "" role_id: "",
}, },
validationSchema, validationSchema,
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
@@ -103,12 +100,13 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
formData.append("position", values.position); formData.append("position", values.position);
formData.append("role_id", values.role_id); formData.append("role_id", values.role_id);
requestServer(`${CREATE_EXPERT_MANAGEMENT}`, 'post', {auth: true, data: formData}) requestServer(`${CREATE_EXPERT_MANAGEMENT}`, "post", { auth: true, data: formData })
.then((response) => { .then((response) => {
setOpenCreateDialog(false) setOpenCreateDialog(false);
mutate() mutate();
}).catch(() => { })
}).finally(() => { .catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -119,9 +117,7 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
<DialogContent> <DialogContent>
<Box sx={{ my: 1 }}> <Box sx={{ my: 1 }}>
<Divider> <Divider>
<Chip <Chip label={t("ExpertMangement.personal_info")} />
label={t("ExpertMangement.personal_info")}
/>
</Divider> </Divider>
</Box> </Box>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}> <Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
@@ -151,7 +147,11 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
error={formik.touched.national_id && !!formik.errors.national_id} error={formik.touched.national_id && !!formik.errors.national_id}
helperText={formik.touched.national_id && formik.errors.national_id ? formik.errors.national_id : null} helperText={
formik.touched.national_id && formik.errors.national_id
? formik.errors.national_id
: null
}
sx={{ width: "100%" }} sx={{ width: "100%" }}
/> />
</Grid> </Grid>
@@ -166,7 +166,11 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
error={formik.touched.phone_number && !!formik.errors.phone_number} error={formik.touched.phone_number && !!formik.errors.phone_number}
helperText={formik.touched.phone_number && formik.errors.phone_number ? formik.errors.phone_number : null} helperText={
formik.touched.phone_number && formik.errors.phone_number
? formik.errors.phone_number
: null
}
sx={{ width: "100%" }} sx={{ width: "100%" }}
/> />
</Grid> </Grid>
@@ -188,9 +192,7 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
</Grid> </Grid>
<Box sx={{ my: 1 }}> <Box sx={{ my: 1 }}>
<Divider> <Divider>
<Chip <Chip label={t("ExpertMangement.user_info")} />
label={t("ExpertMangement.user_info")}
/>
</Divider> </Divider>
</Box> </Box>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}> <Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
@@ -205,7 +207,9 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
error={formik.touched.username && !!formik.errors.username} error={formik.touched.username && !!formik.errors.username}
helperText={formik.touched.username && formik.errors.username ? formik.errors.username : null} helperText={
formik.touched.username && formik.errors.username ? formik.errors.username : null
}
sx={{ width: "100%" }} sx={{ width: "100%" }}
/> />
</Grid> </Grid>
@@ -220,7 +224,9 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
error={formik.touched.password && !!formik.errors.password} error={formik.touched.password && !!formik.errors.password}
helperText={formik.touched.password && formik.errors.password ? formik.errors.password : null} helperText={
formik.touched.password && formik.errors.password ? formik.errors.password : null
}
type={showPassword ? "text" : "password"} type={showPassword ? "text" : "password"}
InputProps={{ InputProps={{
endAdornment: ( endAdornment: (
@@ -237,9 +243,7 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
</Grid> </Grid>
<Box sx={{ my: 1 }}> <Box sx={{ my: 1 }}>
<Divider> <Divider>
<Chip <Chip label={t("ExpertMangement.rest_info")} />
label={t("ExpertMangement.rest_info")}
/>
</Divider> </Divider>
</Box> </Box>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}> <Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
@@ -257,20 +261,16 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
value={formik.values.province_id} value={formik.values.province_id}
onChange={(e) => { onChange={(e) => {
formik.setFieldValue("province_id", e.target.value); formik.setFieldValue("province_id", e.target.value);
getCities(e.target.value) getCities(e.target.value);
}} }}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
fullWidth fullWidth
variant="outlined" variant="outlined"
> >
{isLoadingProvinceList ? ( {isLoadingProvinceList ? (
<MenuItem> <MenuItem>{t("ExpertMangement.text_field_loading_provinces_list")}</MenuItem>
{t("ExpertMangement.text_field_loading_provinces_list")}
</MenuItem>
) : errorProvinceList ? ( ) : errorProvinceList ? (
<MenuItem> <MenuItem>{t("ExpertMangement.text_field_error_fetching_provinces")}</MenuItem>
{t("ExpertMangement.text_field_error_fetching_provinces")}
</MenuItem>
) : ( ) : (
provinceList.map((item) => ( provinceList.map((item) => (
<MenuItem key={item.id} value={item.id}> <MenuItem key={item.id} value={item.id}>
@@ -280,7 +280,9 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
)} )}
</Select> </Select>
<FormHelperText> <FormHelperText>
{formik.touched.province_id && formik.errors.province_id ? formik.errors.province_id : ""} {formik.touched.province_id && formik.errors.province_id
? formik.errors.province_id
: ""}
</FormHelperText> </FormHelperText>
</FormControl> </FormControl>
</Grid> </Grid>
@@ -325,7 +327,9 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
error={formik.touched.position && !!formik.errors.position} error={formik.touched.position && !!formik.errors.position}
helperText={formik.touched.position && formik.errors.position ? formik.errors.position : null} helperText={
formik.touched.position && formik.errors.position ? formik.errors.position : null
}
sx={{ width: "100%" }} sx={{ width: "100%" }}
/> />
</Grid> </Grid>
@@ -346,13 +350,9 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
variant="outlined" variant="outlined"
> >
{isLoadingRoleList ? ( {isLoadingRoleList ? (
<MenuItem> <MenuItem>{t("ExpertMangement.text_field_loading_roles_list")}</MenuItem>
{t("ExpertMangement.text_field_loading_roles_list")}
</MenuItem>
) : errorRoleList ? ( ) : errorRoleList ? (
<MenuItem> <MenuItem>{t("ExpertMangement.text_field_error_fetching_roles")}</MenuItem>
{t("ExpertMangement.text_field_error_fetching_roles")}
</MenuItem>
) : ( ) : (
roleList.map((item) => ( roleList.map((item) => (
<MenuItem key={item.id} value={item.id}> <MenuItem key={item.id} value={item.id}>
@@ -369,12 +369,21 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
</Grid> </Grid>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenCreateDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenCreateDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ExpertMangement.button-cancel")} {t("ExpertMangement.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("ExpertMangement.button-confirm")} {t("ExpertMangement.button-confirm")}
</Button> </Button>
</DialogActions> </DialogActions>

View File

@@ -1,4 +1,4 @@
import {Button, Dialog, DialogTitle, Stack, Tooltip,} from "@mui/material"; import { Button, Dialog, DialogTitle, Stack, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn"; import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
import { useState } from "react"; import { useState } from "react";
@@ -19,16 +19,24 @@ const Create = ({mutate}) => {
sx={{ textTransform: "unset", alignSelf: "center" }} sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={<DataSaverOnIcon />} startIcon={<DataSaverOnIcon />}
onClick={() => { onClick={() => {
setOpenCreateDialog(true) setOpenCreateDialog(true);
}} }}
> >
{t("ExpertMangement.add")} {t("ExpertMangement.add")}
</Button> </Button>
</Tooltip> </Tooltip>
</Stack> </Stack>
<Dialog fullWidth maxWidth={'lg'} open={openCreateDialog} <Dialog
fullWidth
maxWidth={"lg"}
open={openCreateDialog}
TransitionProps={{ unmountOnExit: true }} TransitionProps={{ unmountOnExit: true }}
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("ExpertMangement.create")}</DialogTitle> <DialogTitle>{t("ExpertMangement.create")}</DialogTitle>
<CreateContent setOpenCreateDialog={setOpenCreateDialog} mutate={mutate} /> <CreateContent setOpenCreateDialog={setOpenCreateDialog} mutate={mutate} />
</Dialog> </Dialog>

View File

@@ -6,9 +6,9 @@ import {
DialogContentText, DialogContentText,
DialogTitle, DialogTitle,
IconButton, IconButton,
Tooltip Tooltip,
} from "@mui/material"; } from "@mui/material";
import DeleteIcon from '@mui/icons-material/Delete'; import DeleteIcon from "@mui/icons-material/Delete";
import { useState } from "react"; import { useState } from "react";
import { DELETE_EXPERT_MANAGEMENT } from "@/core/data/apiRoutes"; import { DELETE_EXPERT_MANAGEMENT } from "@/core/data/apiRoutes";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
@@ -21,15 +21,14 @@ const Delete = ({rowId, mutate}) => {
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
const handleDelete = () => { const handleDelete = () => {
setIsSubmitting(true) setIsSubmitting(true);
requestServer(`${DELETE_EXPERT_MANAGEMENT}/${rowId}`, 'post') requestServer(`${DELETE_EXPERT_MANAGEMENT}/${rowId}`, "post")
.then((response) => { .then((response) => {
mutate() mutate();
})
.catch(() => {
}) })
.catch(() => {})
.finally(() => { .finally(() => {
setIsSubmitting(false) setIsSubmitting(false);
setOpenDeleteDialog(false); setOpenDeleteDialog(false);
}); });
}; };
@@ -50,8 +49,8 @@ const Delete = ({rowId, mutate}) => {
open={openDeleteDialog} open={openDeleteDialog}
PaperProps={{ PaperProps={{
sx: { sx: {
boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px' boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
} },
}} }}
> >
<DialogTitle>{t("ExpertMangement.delete_expert")}</DialogTitle> <DialogTitle>{t("ExpertMangement.delete_expert")}</DialogTitle>

View File

@@ -12,7 +12,7 @@ import {
InputLabel, InputLabel,
MenuItem, MenuItem,
Select, Select,
TextField TextField,
} from "@mui/material"; } from "@mui/material";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useFormik } from "formik"; import { useFormik } from "formik";
@@ -33,8 +33,8 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
function getCities(province_id) { function getCities(province_id) {
formik.setFieldTouched("city_id", false, false); formik.setFieldTouched("city_id", false, false);
citiesExist && formik.setFieldValue("city_id", "") citiesExist && formik.setFieldValue("city_id", "");
setCityTextField(t("ExpertMangement.text_field_loading_cities_list")) setCityTextField(t("ExpertMangement.text_field_loading_cities_list"));
requestServer(`${GET_CITY_LIST}?province_id=${province_id}`, "get", { auth: true, notification: false }) requestServer(`${GET_CITY_LIST}?province_id=${province_id}`, "get", { auth: true, notification: false })
.then(({ data }) => { .then(({ data }) => {
const result = data.data; const result = data.data;
@@ -45,9 +45,10 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
})); }));
setCitiesExist(true); setCitiesExist(true);
setCityList(formattedData); setCityList(formattedData);
setCityTextField(t("ExpertMangement.text_field_city_id")) setCityTextField(t("ExpertMangement.text_field_city_id"));
}).catch(() => { })
setCityTextField(t("ExpertMangement.text_field_error_fetching_cities")) .catch(() => {
setCityTextField(t("ExpertMangement.text_field_error_fetching_cities"));
}); });
} }
@@ -60,7 +61,7 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
position: Yup.string().required(t("ExpertMangement.error_message_position")), position: Yup.string().required(t("ExpertMangement.error_message_position")),
province_id: Yup.string().required(t("ExpertMangement.error_message_province_id")), province_id: Yup.string().required(t("ExpertMangement.error_message_province_id")),
city_id: Yup.string(), city_id: Yup.string(),
role_id: Yup.string().required(t("ExpertMangement.error_message_role_id")) role_id: Yup.string().required(t("ExpertMangement.error_message_role_id")),
}); });
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
@@ -72,7 +73,7 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
position: row.original.position, position: row.original.position,
province_id: row.original.province_id, province_id: row.original.province_id,
city_id: row.original.city_id, city_id: row.original.city_id,
role_id: row.original.roles[0].id role_id: row.original.roles[0].id,
}, },
validationSchema, validationSchema,
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
@@ -87,12 +88,13 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
formData.append("position", values.position); formData.append("position", values.position);
formData.append("role_id", values.role_id); formData.append("role_id", values.role_id);
requestServer(`${UPDATE_EXPERT_MANAGEMENT}/${row.original.id}`, 'post', {auth: true, data: formData}) requestServer(`${UPDATE_EXPERT_MANAGEMENT}/${row.original.id}`, "post", { auth: true, data: formData })
.then((response) => { .then((response) => {
setOpenUpdateDialog(false); setOpenUpdateDialog(false);
mutate() mutate();
}).catch(() => { })
}).finally(() => { .catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -107,9 +109,7 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
<DialogContent> <DialogContent>
<Box sx={{ my: 1 }}> <Box sx={{ my: 1 }}>
<Divider> <Divider>
<Chip <Chip label={t("ExpertMangement.personal_info")} />
label={t("ExpertMangement.personal_info")}
/>
</Divider> </Divider>
</Box> </Box>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}> <Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
@@ -139,7 +139,11 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
error={formik.touched.national_id && !!formik.errors.national_id} error={formik.touched.national_id && !!formik.errors.national_id}
helperText={formik.touched.national_id && formik.errors.national_id ? formik.errors.national_id : null} helperText={
formik.touched.national_id && formik.errors.national_id
? formik.errors.national_id
: null
}
sx={{ width: "100%" }} sx={{ width: "100%" }}
/> />
</Grid> </Grid>
@@ -154,7 +158,11 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
error={formik.touched.phone_number && !!formik.errors.phone_number} error={formik.touched.phone_number && !!formik.errors.phone_number}
helperText={formik.touched.phone_number && formik.errors.phone_number ? formik.errors.phone_number : null} helperText={
formik.touched.phone_number && formik.errors.phone_number
? formik.errors.phone_number
: null
}
sx={{ width: "100%" }} sx={{ width: "100%" }}
/> />
</Grid> </Grid>
@@ -176,9 +184,7 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
</Grid> </Grid>
<Box sx={{ my: 1 }}> <Box sx={{ my: 1 }}>
<Divider> <Divider>
<Chip <Chip label={t("ExpertMangement.user_info")} />
label={t("ExpertMangement.user_info")}
/>
</Divider> </Divider>
</Box> </Box>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}> <Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
@@ -193,16 +199,16 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
error={formik.touched.username && !!formik.errors.username} error={formik.touched.username && !!formik.errors.username}
helperText={formik.touched.username && formik.errors.username ? formik.errors.username : null} helperText={
formik.touched.username && formik.errors.username ? formik.errors.username : null
}
sx={{ width: "100%" }} sx={{ width: "100%" }}
/> />
</Grid> </Grid>
</Grid> </Grid>
<Box sx={{ my: 1 }}> <Box sx={{ my: 1 }}>
<Divider> <Divider>
<Chip <Chip label={t("ExpertMangement.rest_info")} />
label={t("ExpertMangement.rest_info")}
/>
</Divider> </Divider>
</Box> </Box>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}> <Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
@@ -223,13 +229,9 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
variant="outlined" variant="outlined"
> >
{isLoadingProvinceList ? ( {isLoadingProvinceList ? (
<MenuItem> <MenuItem>{t("ExpertMangement.text_field_loading_provinces_list")}</MenuItem>
{t("ExpertMangement.text_field_loading_provinces_list")}
</MenuItem>
) : errorProvinceList ? ( ) : errorProvinceList ? (
<MenuItem> <MenuItem>{t("ExpertMangement.text_field_error_fetching_provinces")}</MenuItem>
{t("ExpertMangement.text_field_error_fetching_provinces")}
</MenuItem>
) : ( ) : (
provinceList.map((item) => ( provinceList.map((item) => (
<MenuItem key={item.id} value={item.id}> <MenuItem key={item.id} value={item.id}>
@@ -239,7 +241,9 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
)} )}
</Select> </Select>
<FormHelperText> <FormHelperText>
{formik.touched.province_id && formik.errors.province_id ? formik.errors.province_id : ""} {formik.touched.province_id && formik.errors.province_id
? formik.errors.province_id
: ""}
</FormHelperText> </FormHelperText>
</FormControl> </FormControl>
</Grid> </Grid>
@@ -284,7 +288,9 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
error={formik.touched.position && !!formik.errors.position} error={formik.touched.position && !!formik.errors.position}
helperText={formik.touched.position && formik.errors.position ? formik.errors.position : null} helperText={
formik.touched.position && formik.errors.position ? formik.errors.position : null
}
sx={{ width: "100%" }} sx={{ width: "100%" }}
/> />
</Grid> </Grid>
@@ -305,13 +311,9 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
variant="outlined" variant="outlined"
> >
{isLoadingRoleList ? ( {isLoadingRoleList ? (
<MenuItem> <MenuItem>{t("ExpertMangement.text_field_loading_roles_list")}</MenuItem>
{t("ExpertMangement.text_field_loading_roles_list")}
</MenuItem>
) : errorRoleList ? ( ) : errorRoleList ? (
<MenuItem> <MenuItem>{t("ExpertMangement.text_field_error_fetching_roles")}</MenuItem>
{t("ExpertMangement.text_field_error_fetching_roles")}
</MenuItem>
) : ( ) : (
roleList.map((item) => ( roleList.map((item) => (
<MenuItem key={item.id} value={item.id}> <MenuItem key={item.id} value={item.id}>
@@ -328,12 +330,21 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
</Grid> </Grid>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenUpdateDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenUpdateDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ExpertMangement.button-cancel")} {t("ExpertMangement.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("ExpertMangement.button-confirm")} {t("ExpertMangement.button-confirm")}
</Button> </Button>
</DialogActions> </DialogActions>

View File

@@ -1,10 +1,9 @@
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import EditIcon from '@mui/icons-material/Edit'; import EditIcon from "@mui/icons-material/Edit";
import { useState } from "react"; import { useState } from "react";
import UpdateContent from "./UpdateContent"; import UpdateContent from "./UpdateContent";
const Update = ({ row, mutate }) => { const Update = ({ row, mutate }) => {
const t = useTranslations(); const t = useTranslations();
const [openUpdateDialog, setOpenUpdateDialog] = useState(false); const [openUpdateDialog, setOpenUpdateDialog] = useState(false);
@@ -15,14 +14,22 @@ const Update = ({row, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenUpdateDialog(true) setOpenUpdateDialog(true);
}} }}
> >
<EditIcon /> <EditIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth maxWidth={'lg'} open={openUpdateDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
maxWidth={"lg"}
open={openUpdateDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("ExpertMangement.update")}</DialogTitle> <DialogTitle>{t("ExpertMangement.update")}</DialogTitle>
<UpdateContent row={row} mutate={mutate} setOpenUpdateDialog={setOpenUpdateDialog} /> <UpdateContent row={row} mutate={mutate} setOpenUpdateDialog={setOpenUpdateDialog} />
</Dialog> </Dialog>

View File

@@ -1,24 +1,14 @@
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import Update from "./Form/UpdateForm" import Update from "./Form/UpdateForm";
import Delete from "./Form/DeleteForm"; import Delete from "./Form/DeleteForm";
import ChangePassword from "./Form/ChangePassword"; import ChangePassword from "./Form/ChangePassword";
const TableRowActions = ({ row, mutate }) => { const TableRowActions = ({ row, mutate }) => {
return ( return (
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}> <Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
<Update <Update row={row} mutate={mutate} />
row={row} <ChangePassword rowId={row.getValue("id")} mutate={mutate} />
mutate={mutate} <Delete rowId={row.getValue("id")} mutate={mutate} />
/>
<ChangePassword
rowId={row.getValue("id")}
mutate={mutate}
/>
<Delete
rowId={row.getValue("id")}
mutate={mutate}
/>
</Box> </Box>
); );
}; };

View File

@@ -19,17 +19,8 @@ function DashboardExpertManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.name, accessorFn: (row) => row.name,
@@ -39,9 +30,7 @@ function DashboardExpertManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.username, accessorFn: (row) => row.username,
@@ -51,9 +40,7 @@ function DashboardExpertManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.phone_number, accessorFn: (row) => row.phone_number,
@@ -63,9 +50,7 @@ function DashboardExpertManagementComponent() {
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_id, accessorFn: (row) => row.national_id,
@@ -75,9 +60,7 @@ function DashboardExpertManagementComponent() {
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.position, accessorFn: (row) => row.position,
@@ -87,9 +70,7 @@ function DashboardExpertManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.province_name, accessorFn: (row) => row.province_name,
@@ -99,9 +80,7 @@ function DashboardExpertManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.roles[0].name_fa, accessorFn: (row) => row.roles[0].name_fa,
@@ -111,13 +90,10 @@ function DashboardExpertManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => accessorFn: (row) => moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "updated_at", id: "updated_at",
header: t("ExpertMangement.updated_at"), header: t("ExpertMangement.updated_at"),
enableColumnFilter: true, enableColumnFilter: true,
@@ -129,9 +105,7 @@ function DashboardExpertManagementComponent() {
}, },
Header: ({ column }) => <>{column.columnDef.header}</>, Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => { Filter: ({ column }) => {
return ( return <MuiDatePicker column={column} />;
<MuiDatePicker column={column}/>
);
}, },
}, },
], ],
@@ -145,14 +119,17 @@ function DashboardExpertManagementComponent() {
columns={columns} columns={columns}
selectableRow={false} selectableRow={false}
CustomToolbar={TableToolbar} CustomToolbar={TableToolbar}
sorting={[{ sorting={[
id: 'id', desc: true {
}]} id: "id",
desc: true,
},
]}
enableCustomToolbar={true} enableCustomToolbar={true}
enableLastUpdate={true} enableLastUpdate={true}
enablePinning={true} enablePinning={true}
enableDensityToggle={false} enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large) initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true} enableColumnFilters={true}
enableHiding={true} enableHiding={true}
enableFullScreenToggle={false} enableFullScreenToggle={false}

View File

@@ -11,13 +11,10 @@ const DashboardFirstComponent = () => {
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({ auth: true, notification: false }); const requestServer = useRequest({ auth: true, notification: false });
const [data, setData] = useState(null); const [data, setData] = useState(null);
const isXL = useMediaQuery(theme.breakpoints.up('xl')); const isXL = useMediaQuery(theme.breakpoints.up("xl"));
useEffect(() => { useEffect(() => {
requestServer( requestServer(`${GET_LOAN_STATISTICS}`, "get")
`${GET_LOAN_STATISTICS}`,
"get"
)
.then((res) => { .then((res) => {
setData(res.data.data); setData(res.data.data);
}) })
@@ -30,210 +27,330 @@ const DashboardFirstComponent = () => {
<> <>
<FullPageLayout> <FullPageLayout>
<CenterLayout> <CenterLayout>
<Stack sx={{ display: 'flex', justifyContent: 'center', gap: '20px' ,width: '100%' , flexDirection: "row",padding: 3, alignItems: 'flex-end',}}> <Stack
<Card sx={{height:"200px" , width: '20%', boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px", borderRadius: '5px' }}> sx={{
display: "flex",
justifyContent: "center",
gap: "20px",
width: "100%",
flexDirection: "row",
padding: 3,
alignItems: "flex-end",
}}
>
<Card
sx={{
height: "200px",
width: "20%",
boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px",
borderRadius: "5px",
}}
>
<CardHeader <CardHeader
sx={{ sx={{
height: '50px', height: "50px",
backgroundColor: 'rgba(8, 64, 112, 0.08)', backgroundColor: "rgba(8, 64, 112, 0.08)",
color: 'primary.main', color: "primary.main",
textAlign:'center', textAlign: "center",
}} }}
titleTypographyProps={{ titleTypographyProps={{
variant: 'body1', variant: "body1",
sx: { sx: {
textAlign: 'center', textAlign: "center",
fontWeight: 'bold', fontWeight: "bold",
[theme.breakpoints.down('xl')]: { [theme.breakpoints.down("xl")]: {
fontSize: '12px', fontSize: "12px",
},
}, },
}
}} }}
title={t("Dashboard.total_number_loan_offers")} title={t("Dashboard.total_number_loan_offers")}
/> />
<CardContent sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent:'center', height: 'calc(100% - 50px)', padding: "0 !important"}}> <CardContent
<Box
sx={{ sx={{
borderBottom: '6px solid', display: "flex",
borderColor: 'primary.main', flexDirection: "column",
borderRadius: '6px 6px 6px 6px', alignItems: "center",
width: '90%', justifyContent: "center",
textAlign:'center', height: "calc(100% - 50px)",
padding: "0 !important",
}} }}
> >
<Typography variant={isXL ? 'h5' : 'h6'} sx={{lineHeight: 1.5 , fontWeight:'bold'}}> <Box
sx={{
borderBottom: "6px solid",
borderColor: "primary.main",
borderRadius: "6px 6px 6px 6px",
width: "90%",
textAlign: "center",
}}
>
<Typography
variant={isXL ? "h5" : "h6"}
sx={{ lineHeight: 1.5, fontWeight: "bold" }}
>
{Number(data.proposedCount).toLocaleString("en")} {Number(data.proposedCount).toLocaleString("en")}
</Typography> </Typography>
</Box> </Box>
<Box component={'img'} sx={{width: '40px', height: '40px', mt:2}} <Box
src={'/images/pie-chart.png'}/> component={"img"}
sx={{ width: "40px", height: "40px", mt: 2 }}
src={"/images/pie-chart.png"}
/>
</CardContent> </CardContent>
</Card> </Card>
<Card sx={{height:"250px" , width: '20%', boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px", borderRadius: '5px' }}> <Card
sx={{
height: "250px",
width: "20%",
boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px",
borderRadius: "5px",
}}
>
<CardHeader <CardHeader
sx={{ sx={{
height: '50px', height: "50px",
backgroundColor: 'rgba(8, 64, 112, 0.08)', backgroundColor: "rgba(8, 64, 112, 0.08)",
color: 'primary.main', color: "primary.main",
textAlign:'center', textAlign: "center",
fontSize: '14px', fontSize: "14px",
fontWeight: 'bold', fontWeight: "bold",
}} }}
titleTypographyProps={{ titleTypographyProps={{
variant: 'body1', variant: "body1",
sx: { sx: {
textAlign: 'center', textAlign: "center",
fontWeight: 'bold', fontWeight: "bold",
[theme.breakpoints.down('xl')]: { [theme.breakpoints.down("xl")]: {
fontSize: '12px', fontSize: "12px",
},
}, },
}
}} }}
title={t("Dashboard.total_amount_proposed_loan")} title={t("Dashboard.total_amount_proposed_loan")}
/> />
<CardContent sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent:'center', height: 'calc(100% - 50px)', padding: "0 !important"}}> <CardContent
<Box
sx={{ sx={{
borderBottom: '6px solid', display: "flex",
borderColor: 'primary.main', flexDirection: "column",
borderRadius: '6px 6px 6px 6px', alignItems: "center",
width: '90%', justifyContent: "center",
textAlign:'center', height: "calc(100% - 50px)",
padding: "0 !important",
}} }}
> >
<Typography variant={isXL ? 'h5' : 'h6'} sx={{ lineHeight: 1.5, fontWeight: 'bold' }}> <Box
sx={{
borderBottom: "6px solid",
borderColor: "primary.main",
borderRadius: "6px 6px 6px 6px",
width: "90%",
textAlign: "center",
}}
>
<Typography
variant={isXL ? "h5" : "h6"}
sx={{ lineHeight: 1.5, fontWeight: "bold" }}
>
{(Number(data.totalProposedAmount) / 1000000).toLocaleString("en")} {(Number(data.totalProposedAmount) / 1000000).toLocaleString("en")}
<Box component="span" sx={{ fontSize: '9px' , paddingLeft: '3px'}}> <Box component="span" sx={{ fontSize: "9px", paddingLeft: "3px" }}>
{t("million_rial")} {t("million_rial")}
</Box> </Box>
</Typography> </Typography>
</Box> </Box>
<Box component={'img'} sx={{width: '40px', height: '40px' , mt:2}} <Box
src={'/images/rial.png'}/> component={"img"}
sx={{ width: "40px", height: "40px", mt: 2 }}
src={"/images/rial.png"}
/>
</CardContent> </CardContent>
</Card> </Card>
<Card sx={{height:"300px", width: '20%', boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px", borderRadius: '5px' }}> <Card
sx={{
height: "300px",
width: "20%",
boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px",
borderRadius: "5px",
}}
>
<CardHeader <CardHeader
sx={{ sx={{
height: '50px', height: "50px",
backgroundColor: 'rgba(8, 64, 112, 0.08)', backgroundColor: "rgba(8, 64, 112, 0.08)",
color: 'primary.main', color: "primary.main",
textAlign:'center', textAlign: "center",
fontSize: '14px', fontSize: "14px",
fontWeight: 'bold', fontWeight: "bold",
}} }}
titleTypographyProps={{ titleTypographyProps={{
variant: 'body1', variant: "body1",
sx: { sx: {
textAlign: 'center', textAlign: "center",
fontWeight: 'bold', fontWeight: "bold",
[theme.breakpoints.down('xl')]: { [theme.breakpoints.down("xl")]: {
fontSize: '12px', fontSize: "12px",
},
}, },
}
}} }}
title={t("Dashboard.total_number_requests")} title={t("Dashboard.total_number_requests")}
/> />
<CardContent sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent:'center', height: 'calc(100% - 50px)', padding: "0 !important"}}> <CardContent
<Box
sx={{ sx={{
borderBottom: '6px solid', display: "flex",
borderColor: 'primary.main', flexDirection: "column",
borderRadius: '6px 6px 6px 6px', alignItems: "center",
width: '90%', justifyContent: "center",
textAlign:'center', height: "calc(100% - 50px)",
padding: "0 !important",
}} }}
> >
<Typography variant={isXL ? 'h5' : 'h6'} sx={{lineHeight: 1.5 , fontWeight:'bold'}}> <Box
sx={{
borderBottom: "6px solid",
borderColor: "primary.main",
borderRadius: "6px 6px 6px 6px",
width: "90%",
textAlign: "center",
}}
>
<Typography
variant={isXL ? "h5" : "h6"}
sx={{ lineHeight: 1.5, fontWeight: "bold" }}
>
{Number(data.totalApprovedLoans).toLocaleString("en")} {Number(data.totalApprovedLoans).toLocaleString("en")}
</Typography> </Typography>
</Box> </Box>
<Box component={'img'} sx={{width: '40px', height: '40px' , mt:2}} <Box
src={'/images/pie-chart.png'}/> component={"img"}
sx={{ width: "40px", height: "40px", mt: 2 }}
src={"/images/pie-chart.png"}
/>
</CardContent> </CardContent>
</Card> </Card>
<Card sx={{height:"250px", width: '20%', boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px", borderRadius: '5px' }}> <Card
sx={{
height: "250px",
width: "20%",
boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px",
borderRadius: "5px",
}}
>
<CardHeader <CardHeader
sx={{ sx={{
height: '50px', height: "50px",
backgroundColor: 'rgba(8, 64, 112, 0.08)', backgroundColor: "rgba(8, 64, 112, 0.08)",
color: 'primary.main', color: "primary.main",
textAlign:'center', textAlign: "center",
fontSize: '14px', fontSize: "14px",
fontWeight: 'bold', fontWeight: "bold",
}} }}
titleTypographyProps={{ titleTypographyProps={{
variant: 'body1', variant: "body1",
sx: { sx: {
textAlign: 'center', textAlign: "center",
fontWeight: 'bold', fontWeight: "bold",
[theme.breakpoints.down('xl')]: { [theme.breakpoints.down("xl")]: {
fontSize: '12px', fontSize: "12px",
},
}, },
}
}} }}
title={t("Dashboard.total_amount_approved_loans")} title={t("Dashboard.total_amount_approved_loans")}
/> />
<CardContent sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent:'center', height: 'calc(100% - 50px)', padding: "0 !important"}}> <CardContent
<Box
sx={{ sx={{
borderBottom: '6px solid', display: "flex",
borderColor: 'primary.main', flexDirection: "column",
borderRadius: '6px 6px 6px 6px', alignItems: "center",
width: '90%', justifyContent: "center",
textAlign:'center', height: "calc(100% - 50px)",
padding: "0 !important",
}} }}
> >
<Typography variant={isXL ? 'h5' : 'h6'} sx={{ lineHeight: 1.5, fontWeight: 'bold' }}> <Box
sx={{
borderBottom: "6px solid",
borderColor: "primary.main",
borderRadius: "6px 6px 6px 6px",
width: "90%",
textAlign: "center",
}}
>
<Typography
variant={isXL ? "h5" : "h6"}
sx={{ lineHeight: 1.5, fontWeight: "bold" }}
>
{(Number(data.totalApprovedAmount) / 1000000).toLocaleString("en")} {(Number(data.totalApprovedAmount) / 1000000).toLocaleString("en")}
<Box component="span" sx={{ fontSize: '9px' , paddingLeft: '3px' }}> <Box component="span" sx={{ fontSize: "9px", paddingLeft: "3px" }}>
{t("million_rial")} {t("million_rial")}
</Box> </Box>
</Typography> </Typography>
</Box> </Box>
<Box component={'img'} sx={{width: '40px', height: '40px' , mt:2}} <Box
src={'/images/rial.png'}/> component={"img"}
sx={{ width: "40px", height: "40px", mt: 2 }}
src={"/images/rial.png"}
/>
</CardContent> </CardContent>
</Card> </Card>
<Card sx={{height:"200px", width: '20%', boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px", borderRadius: '5px' }}> <Card
sx={{
height: "200px",
width: "20%",
boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px",
borderRadius: "5px",
}}
>
<CardHeader <CardHeader
sx={{ sx={{
height: '50px', height: "50px",
backgroundColor: 'rgba(8, 64, 112, 0.08)', backgroundColor: "rgba(8, 64, 112, 0.08)",
color: 'primary.main', color: "primary.main",
textAlign:'center', textAlign: "center",
fontSize: '14px', fontSize: "14px",
fontWeight: 'bold', fontWeight: "bold",
}} }}
titleTypographyProps={{ titleTypographyProps={{
variant: 'body1', variant: "body1",
sx: { sx: {
textAlign: 'center', textAlign: "center",
fontWeight: 'bold', fontWeight: "bold",
[theme.breakpoints.down('xl')]: { [theme.breakpoints.down("xl")]: {
fontSize: '12px', fontSize: "12px",
},
}, },
}
}} }}
title={t("Dashboard.number_approved_loans")} title={t("Dashboard.number_approved_loans")}
/> />
<CardContent sx={{display: 'flex', flexDirection: 'column', alignItems: 'center' , justifyContent:'center', height: 'calc(100% - 50px)' , padding: "0 !important"}}> <CardContent
<Box
sx={{ sx={{
borderBottom: '6px solid', display: "flex",
borderColor: 'primary.main', flexDirection: "column",
borderRadius: '6px 6px 6px 6px', alignItems: "center",
width: '90%', justifyContent: "center",
textAlign:'center', height: "calc(100% - 50px)",
alignSelf: 'center', padding: "0 !important",
}} }}
> >
<Typography variant={isXL ? 'h5' : 'h6'} sx={{lineHeight: 1.5 , fontWeight:'bold'}}> <Box
sx={{
borderBottom: "6px solid",
borderColor: "primary.main",
borderRadius: "6px 6px 6px 6px",
width: "90%",
textAlign: "center",
alignSelf: "center",
}}
>
<Typography
variant={isXL ? "h5" : "h6"}
sx={{ lineHeight: 1.5, fontWeight: "bold" }}
>
{Number(data.approvedCount).toLocaleString("en")} {Number(data.approvedCount).toLocaleString("en")}
</Typography> </Typography>
</Box> </Box>
<Box component={'img'} sx={{width: '40px', height: '40px' , mt:2}} <Box
src={'/images/pie-chart.png'}/> component={"img"}
sx={{ width: "40px", height: "40px", mt: 2 }}
src={"/images/pie-chart.png"}
/>
</CardContent> </CardContent>
</Card> </Card>
</Stack> </Stack>

View File

@@ -1,7 +1,7 @@
import UploadSystem from "@/core/components/UploadSystem"; import UploadSystem from "@/core/components/UploadSystem";
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField, Typography} from "@mui/material" import { Button, DialogActions, DialogContent, Stack, TextField, Typography } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { CONFIRM_INSPECTOR_EXPERT } from "@/core/data/apiRoutes"; import { CONFIRM_INSPECTOR_EXPERT } from "@/core/data/apiRoutes";
@@ -14,34 +14,36 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
const [fileType, setfileType] = useState(null); const [fileType, setfileType] = useState(null);
const [fileName, setfileName] = useState(null); const [fileName, setfileName] = useState(null);
const [showAddIcon, setShowAddIcon] = useState(true); const [showAddIcon, setShowAddIcon] = useState(true);
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
description: "", description: "",
confirm_img: null confirm_img: null,
}, },
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
const formData = new FormData(); const formData = new FormData();
if (values.description != "") formData.append("description", values.description); if (values.description != "") formData.append("description", values.description);
if (values.confirm_img != null) formData.append("attachment", values.confirm_img); if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
requestServer(`${CONFIRM_INSPECTOR_EXPERT}/${rowId}`, 'post', { requestServer(`${CONFIRM_INSPECTOR_EXPERT}/${rowId}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenConfirmDialog(false) .then((response) => {
mutate() setOpenConfirmDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
}); });
const handleDescriptionChange = (event) => { const handleDescriptionChange = (event) => {
formik.setFieldValue("description", event.target.value) formik.setFieldValue("description", event.target.value);
}; };
const handleUploadChange = (event) => { const handleUploadChange = (event) => {
@@ -73,8 +75,12 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
name="description" name="description"
multiline multiline
rows={8} rows={8}
label={<> label={
<span>{t("ConfirmDialog.description")}</span><small>{t("ConfirmDialog.optional")}</small></>} <>
<span>{t("ConfirmDialog.description")}</span>
<small>{t("ConfirmDialog.optional")}</small>
</>
}
value={formik.values.description} value={formik.values.description}
onChange={handleDescriptionChange} onChange={handleDescriptionChange}
fullWidth fullWidth
@@ -83,7 +89,10 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
/> />
</Stack> </Stack>
<Stack> <Stack>
<Typography>{t("UploadSystem.upload_file")}{t("UploadSystem.optional")}</Typography> <Typography>
{t("UploadSystem.upload_file")}
{t("UploadSystem.optional")}
</Typography>
<UploadSystem <UploadSystem
selectedImage={selectedImage} selectedImage={selectedImage}
handleUploadChange={handleUploadChange} // Pass the updated function directly handleUploadChange={handleUploadChange} // Pass the updated function directly
@@ -101,17 +110,25 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ConfirmDialog.button-cancel")} {t("ConfirmDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting}
>
{t("ConfirmDialog.button-confirm")} {t("ConfirmDialog.button-confirm")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
};
} export default ConfirmContent;
export default ConfirmContent

View File

@@ -13,19 +13,25 @@ const Confirm = ({rowId, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenConfirmDialog(true) setOpenConfirmDialog(true);
}} }}
> >
<ThumbUpAltIcon /> <ThumbUpAltIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openConfirmDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openConfirmDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle> <DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
<ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} /> <ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog> </Dialog>
</> </>
) );
};
}
export default Confirm; export default Confirm;

View File

@@ -1,7 +1,7 @@
import UploadSystem from "@/core/components/UploadSystem" import UploadSystem from "@/core/components/UploadSystem";
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField, Typography} from "@mui/material" import { Button, DialogActions, DialogContent, Stack, TextField, Typography } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
@@ -14,8 +14,8 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const [fileName, setfileName] = useState(null); const [fileName, setfileName] = useState(null);
const [showAddIcon, setShowAddIcon] = useState(true); const [showAddIcon, setShowAddIcon] = useState(true);
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
description: Yup.string().required(t("RejectDialog.description_error")), description: Yup.string().required(t("RejectDialog.description_error")),
@@ -24,7 +24,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
description: "", description: "",
reject_img: null reject_img: null,
}, },
validationSchema, validationSchema,
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
@@ -32,14 +32,16 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
formData.append("description", values.description); formData.append("description", values.description);
if (values.reject_img != null) formData.append("attachment", values.reject_img); if (values.reject_img != null) formData.append("attachment", values.reject_img);
requestServer(`${REJECT_INSPECTOR_EXPERT}/${rowId}`, 'post', { requestServer(`${REJECT_INSPECTOR_EXPERT}/${rowId}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenRejectDialog(false) .then((response) => {
mutate() setOpenRejectDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -80,9 +82,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
value={formik.values.description} value={formik.values.description}
onChange={handleDescriptionChange} onChange={handleDescriptionChange}
onBlur={formik.handleBlur("description")} onBlur={formik.handleBlur("description")}
error={ error={formik.touched.description && Boolean(formik.errors.description)}
formik.touched.description && Boolean(formik.errors.description)
}
helperText={formik.touched.description && formik.errors.description} helperText={formik.touched.description && formik.errors.description}
fullWidth fullWidth
variant="outlined" variant="outlined"
@@ -90,7 +90,10 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
/> />
</Stack> </Stack>
<Stack> <Stack>
<Typography>{t("UploadSystem.upload_file")}{t("UploadSystem.optional")}</Typography> <Typography>
{t("UploadSystem.upload_file")}
{t("UploadSystem.optional")}
</Typography>
<UploadSystem <UploadSystem
selectedImage={selectedImage} selectedImage={selectedImage}
handleUploadChange={handleUploadChange} // Pass the updated function directly handleUploadChange={handleUploadChange} // Pass the updated function directly
@@ -108,16 +111,25 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenRejectDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenRejectDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("RejectDialog.button-cancel")} {t("RejectDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("RejectDialog.button-reject")} {t("RejectDialog.button-reject")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
} };
export default RejectContent export default RejectContent;

View File

@@ -1,4 +1,4 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material" import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
import RejectContent from "./RejectContent"; import RejectContent from "./RejectContent";
@@ -14,12 +14,19 @@ const Reject = ({rowId, mutate}) => {
<ThumbDownIcon /> <ThumbDownIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openRejectDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openRejectDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle> <DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} /> <RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} />
</Dialog> </Dialog>
</> </>
) );
} };
export default Reject export default Reject;

View File

@@ -1,6 +1,6 @@
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField} from "@mui/material" import { Button, DialogActions, DialogContent, Stack, TextField } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import * as Yup from "yup"; import * as Yup from "yup";
@@ -8,8 +8,8 @@ import {REVISE_INSPECTOR_EXPERT} from "@/core/data/apiRoutes";
const ReviseContent = ({ rowId, mutate, setOpenReviseDialog }) => { const ReviseContent = ({ rowId, mutate, setOpenReviseDialog }) => {
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
description: Yup.string().required(t("ReviseDialog.description_error")), description: Yup.string().required(t("ReviseDialog.description_error")),
@@ -24,14 +24,16 @@ const ReviseContent = ({rowId, mutate, setOpenReviseDialog}) => {
const formData = new FormData(); const formData = new FormData();
formData.append("description", values.description); formData.append("description", values.description);
requestServer(`${REVISE_INSPECTOR_EXPERT}/${rowId}`, 'post', { requestServer(`${REVISE_INSPECTOR_EXPERT}/${rowId}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenReviseDialog(false) .then((response) => {
mutate() setOpenReviseDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -54,9 +56,7 @@ const ReviseContent = ({rowId, mutate, setOpenReviseDialog}) => {
value={formik.values.description} value={formik.values.description}
onChange={handleDescriptionChange} onChange={handleDescriptionChange}
onBlur={formik.handleBlur("description")} onBlur={formik.handleBlur("description")}
error={ error={formik.touched.description && Boolean(formik.errors.description)}
formik.touched.description && Boolean(formik.errors.description)
}
helperText={formik.touched.description && formik.errors.description} helperText={formik.touched.description && formik.errors.description}
fullWidth fullWidth
variant="outlined" variant="outlined"
@@ -66,16 +66,25 @@ const ReviseContent = ({rowId, mutate, setOpenReviseDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenReviseDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenReviseDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ReviseDialog.button-cancel")} {t("ReviseDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("ReviseDialog.button-revise")} {t("ReviseDialog.button-revise")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
} };
export default ReviseContent export default ReviseContent;

View File

@@ -1,6 +1,6 @@
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import ReplyIcon from '@mui/icons-material/Reply'; import ReplyIcon from "@mui/icons-material/Reply";
import { useState } from "react"; import { useState } from "react";
import ReviseContent from "./ReviseContent"; import ReviseContent from "./ReviseContent";
@@ -13,19 +13,25 @@ const Revise = ({rowId, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenReviseDialog(true) setOpenReviseDialog(true);
}} }}
> >
<ReplyIcon /> <ReplyIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openReviseDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openReviseDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("ReviseDialog.revise")}</DialogTitle> <DialogTitle>{t("ReviseDialog.revise")}</DialogTitle>
<ReviseContent mutate={mutate} rowId={rowId} setOpenReviseDialog={setOpenReviseDialog} /> <ReviseContent mutate={mutate} rowId={rowId} setOpenReviseDialog={setOpenReviseDialog} />
</Dialog> </Dialog>
</> </>
) );
};
}
export default Revise; export default Revise;

View File

@@ -4,21 +4,11 @@ import Reject from "./Form/RejectForm";
import Revise from "./Form/ReviseForm"; import Revise from "./Form/ReviseForm";
const TableRow = ({ row, mutate }) => { const TableRow = ({ row, mutate }) => {
return ( return (
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}> <Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
<Confirm <Confirm rowId={row.getValue("id")} mutate={mutate} />
rowId={row.getValue("id")} <Reject rowId={row.getValue("id")} mutate={mutate} />
mutate={mutate} <Revise rowId={row.getValue("id")} mutate={mutate} />
/>
<Reject
rowId={row.getValue("id")}
mutate={mutate}
/>
<Revise
rowId={row.getValue("id")}
mutate={mutate}
/>
</Box> </Box>
); );
}; };

View File

@@ -18,17 +18,8 @@ function DashboardInspectorExpertComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.name, accessorFn: (row) => row.name,
@@ -38,9 +29,7 @@ function DashboardInspectorExpertComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_id, accessorFn: (row) => row.national_id,
@@ -49,17 +38,8 @@ function DashboardInspectorExpertComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.phone_number, accessorFn: (row) => row.phone_number,
@@ -68,21 +48,11 @@ function DashboardInspectorExpertComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "created_at", id: "created_at",
header: t("InspectorExpert.created_at"), header: t("InspectorExpert.created_at"),
enableColumnFilter: true, enableColumnFilter: true,
@@ -94,21 +64,16 @@ function DashboardInspectorExpertComponent() {
}, },
Header: ({ column }) => <>{column.columnDef.header}</>, Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => { Filter: ({ column }) => {
return ( return <MuiDatePicker column={column} />;
<MuiDatePicker column={column}/>
);
}, },
}, },
{ {
accessorFn: (row) => accessorFn: (row) => moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "updated_at", id: "updated_at",
header: t("InspectorExpert.updated_at"), header: t("InspectorExpert.updated_at"),
enableColumnFilter: false, enableColumnFilter: false,
datatype: "numeric", datatype: "numeric",
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.state_name, accessorFn: (row) => row.state_name,
@@ -116,9 +81,7 @@ function DashboardInspectorExpertComponent() {
header: t("InspectorExpert.state_name"), header: t("InspectorExpert.state_name"),
enableColumnFilter: false, enableColumnFilter: false,
datatype: "numeric", datatype: "numeric",
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
], ],
[] []
@@ -133,11 +96,14 @@ function DashboardInspectorExpertComponent() {
enableCustomToolbar={false} enableCustomToolbar={false}
enableLastUpdate={true} enableLastUpdate={true}
enablePinning={true} enablePinning={true}
sorting={[{ sorting={[
id: 'id', desc: false {
}]} id: "id",
desc: false,
},
]}
enableDensityToggle={false} enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large) initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true} enableColumnFilters={true}
enableHiding={true} enableHiding={true}
enableFullScreenToggle={false} enableFullScreenToggle={false}

View File

@@ -0,0 +1,133 @@
import {
Box, LinearProgress,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow, Typography,
IconButton,
Collapse, Button, Stack
} from "@mui/material";
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import { useTranslations } from "next-intl";
import moment from "jalali-moment";
import useRequest from "@/lib/app/hooks/useRequest";
import { useEffect, useState } from "react";
import { GET_HISTORY_COUNCIL } from "@/core/data/apiRoutes";
const CouncilConfirm = {
1: "تایید",
2: "عدم تایید",
};
const PlanningCouncilTable = ({ rowId }) => {
const t = useTranslations();
const requestServer = useRequest({ auth: true, notification: false });
const [CouncilDetails, setCouncilDetails] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(false);
const [isCommentExpanded, setIsCommentExpanded] = useState(false);
useEffect(() => {
requestServer(`${GET_HISTORY_COUNCIL}/${rowId}`, "get")
.then((response) => {
setIsLoading(false);
setCouncilDetails(response.data.data);
})
.catch(() => {
setError(true);
});
}, []);
const handleToggleComment = () => {
setIsCommentExpanded((prev) => !prev);
};
return (
<Box>
{error ? (
<Typography
sx={{
padding: 2,
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
{t("LoanHistory.Table_history_error")}
</Typography>
) : isLoading ? (
<LinearProgress sx={{ width: "100%" }} />
) : (
<Paper
elevation={0}
sx={{
width: "100%",
overflow: "hidden",
"*::-webkit-scrollbar": {
width: "0.5em",
},
"*::-webkit-scrollbar-thumb": {
backgroundColor: "primary.main",
},
}}
>
<TableContainer sx={{ maxHeight: 600 }}>
<Table stickyHeader sx={{ minWidth: 800 }}>
<TableHead>
<TableRow>
<TableCell>{t("CouncilHistory.Table_head_id")}</TableCell>
<TableCell>{t("CouncilHistory.Table_head_council_confirm")}</TableCell>
<TableCell>{t("CouncilHistory.Table_head_council_comment")}</TableCell>
<TableCell>{t("CouncilHistory.Table_head_planning_council_loan")}</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow sx={{ "&:last-child td, &:last-child th": { border: 0 } }}>
<TableCell> {CouncilDetails.id}</TableCell>
<TableCell>
{CouncilConfirm[CouncilDetails.council_confirm]}
</TableCell>
<TableCell>
<Box display="flex" alignItems="center">
<Typography fontWeight={CouncilDetails.council_comment && "bold"}>
{CouncilDetails.council_reason_name}
</Typography>
{CouncilDetails.council_comment && (
<IconButton onClick={handleToggleComment} size="small">
{isCommentExpanded
? <Button variant="text" endIcon={<KeyboardArrowUpIcon />}>{t("CouncilHistory.close")}</Button>
: <Button variant="text" endIcon={<KeyboardArrowDownIcon />}>{t("CouncilHistory.more")}</Button>
}
</IconButton>
)}
</Box>
<Collapse in={isCommentExpanded} timeout="auto" unmountOnExit>
<Stack spacing={2} sx={{ border: "1px solid", borderColor: "primary.light", p: 2, mt: 1, borderRadius: "8px" }}>
<Typography variant="body1">{t("CouncilHistory.council_opinion")}</Typography>
<Typography variant="body2">
{CouncilDetails.council_comment}
</Typography>
</Stack>
</Collapse>
</TableCell>
<TableCell>
{
CouncilDetails.planning_council_loan ?
moment(CouncilDetails.planning_council_loan.date_confirm).locale("fa").format("HH:mm | yyyy/MM/DD") :
null
}
</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Paper>
)}
</Box>
);
};
export default PlanningCouncilTable;

View File

@@ -0,0 +1,43 @@
import { Button, Dialog, DialogActions, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import Diversity3Icon from '@mui/icons-material/Diversity3';
import PlanningCouncilTable from "./PlanningCouncilTable";
const PlanningCouncilForm = ({ rowId }) => {
const t = useTranslations();
const [openPlanningCouncilDialog, setOpenPlanningCouncilDialog] = useState(false);
return (
<>
<Tooltip title={t("CouncilHistory.council_history")}>
<IconButton color="primary" onClick={() => setOpenPlanningCouncilDialog(true)}>
<Diversity3Icon />
</IconButton>
</Tooltip>
<Dialog
maxWidth={"xl"}
fullWidth
open={openPlanningCouncilDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("CouncilHistory.council_history_detail")}</DialogTitle>
<PlanningCouncilTable rowId={rowId} setOpenPlanningCouncilDialog={setOpenPlanningCouncilDialog} />
<DialogActions>
<Button
onClick={() => setOpenPlanningCouncilDialog(false)}
variant="outlined"
color="secondary"
autoFocus
>
{t("CouncilHistory.button-cancel")}
</Button>
</DialogActions>
</Dialog>
</>
);
};
export default PlanningCouncilForm;

View File

@@ -1,6 +1,6 @@
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField} from "@mui/material" import { Button, DialogActions, DialogContent, Stack, TextField } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import * as Yup from "yup"; import * as Yup from "yup";
@@ -8,8 +8,8 @@ import {REFER_LOAN_FOLLOWUP_PASSENGERBOSS} from "@/core/data/apiRoutes";
const ReferPassengerBossContent = ({ rowId, mutate, setOpenReferDialog }) => { const ReferPassengerBossContent = ({ rowId, mutate, setOpenReferDialog }) => {
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
description: Yup.string().required(t("ReferDialog.description_error")), description: Yup.string().required(t("ReferDialog.description_error")),
@@ -23,14 +23,16 @@ const ReferPassengerBossContent = ({rowId, mutate, setOpenReferDialog}) => {
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
const formData = new FormData(); const formData = new FormData();
formData.append("expert_description", values.description); formData.append("expert_description", values.description);
requestServer(`${REFER_LOAN_FOLLOWUP_PASSENGERBOSS}/${rowId}`, 'post', { requestServer(`${REFER_LOAN_FOLLOWUP_PASSENGERBOSS}/${rowId}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenReferDialog(false) .then((response) => {
mutate() setOpenReferDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -53,9 +55,7 @@ const ReferPassengerBossContent = ({rowId, mutate, setOpenReferDialog}) => {
value={formik.values.description} value={formik.values.description}
onChange={handleDescriptionChange} onChange={handleDescriptionChange}
onBlur={formik.handleBlur("description")} onBlur={formik.handleBlur("description")}
error={ error={formik.touched.description && Boolean(formik.errors.description)}
formik.touched.description && Boolean(formik.errors.description)
}
helperText={formik.touched.description && formik.errors.description} helperText={formik.touched.description && formik.errors.description}
fullWidth fullWidth
variant="outlined" variant="outlined"
@@ -65,16 +65,25 @@ const ReferPassengerBossContent = ({rowId, mutate, setOpenReferDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenReferDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenReferDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ReferDialog.button-cancel")} {t("ReferDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("ReferDialog.button-refer")} {t("ReferDialog.button-refer")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
} };
export default ReferPassengerBossContent export default ReferPassengerBossContent;

View File

@@ -1,7 +1,7 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material" import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
import UTurnRightIcon from '@mui/icons-material/UTurnRight'; import UTurnRightIcon from "@mui/icons-material/UTurnRight";
import ReferPassengerBossContent from "./ReferPassengerBossContent"; import ReferPassengerBossContent from "./ReferPassengerBossContent";
const ReferPassengerBoss = ({ rowId, mutate }) => { const ReferPassengerBoss = ({ rowId, mutate }) => {
@@ -14,12 +14,19 @@ const ReferPassengerBoss = ({rowId, mutate}) => {
<UTurnRightIcon /> <UTurnRightIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openReferDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openReferDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("ReferDialog.refer-passenger-boss")}</DialogTitle> <DialogTitle>{t("ReferDialog.refer-passenger-boss")}</DialogTitle>
<ReferPassengerBossContent mutate={mutate} rowId={rowId} setOpenReferDialog={setOpenReferDialog} /> <ReferPassengerBossContent mutate={mutate} rowId={rowId} setOpenReferDialog={setOpenReferDialog} />
</Dialog> </Dialog>
</> </>
) );
} };
export default ReferPassengerBoss export default ReferPassengerBoss;

View File

@@ -0,0 +1,397 @@
import { Chip, DialogContent, DialogTitle, Divider, Grid, Stack, Typography } from "@mui/material";
import { useTranslations } from "next-intl";
import moment from "jalali-moment";
const LegalTableContent = ({ rowId, row }) => {
const t = useTranslations();
return (
<>
<DialogTitle>{t("UserInfoDialog.user_info")}</DialogTitle>
<DialogContent>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.is_legal_person")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">{t("UserInfoDialog.legal_person")}</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">{row.original.id || t("UserInfoDialog.no_info")}</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_plan_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.project_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.activity_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.activity_category_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.first_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.first_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.last_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.last_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.father_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.father_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.gender")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.gender ? t("UserInfoDialog.female") : t("UserInfoDialog.male")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.national_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.national_id || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip
label={
row.original.national_serial_number
? t("UserInfoDialog.national_serial_number")
: t("UserInfoDialog.national_tracking_code")
}
sx={{ mr: 1 }}
/>
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.national_serial_number ||
row.original.national_tracking_code ||
t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.education_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.education_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.occupation_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.occupation_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.phone_number")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.phone_number || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.birthday")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.birthday
? moment(row.original.birthday).locale("fa").format("YYYY/MM/DD")
: t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.province_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.province_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.city_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.city_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.shenase_meli")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.shenase_meli || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.postal_code")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.postal_code || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.company_register_date")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.company_register_date
? moment(row.original.company_register_date).locale("fa").format("YYYY/MM/DD")
: t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.register_number")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.register_number || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.navgan_id || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.navgan_type || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.company_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.company_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.tel_number")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.telephone_number || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.vehicle_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.vehicle_type || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.investment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.investment_amount / 1000000) >= 1000
? t("UserInfoDialog.milyard", { value: (row.original.investment_amount / 1000000000) })
: t("UserInfoDialog.toman", { value: (row.original.investment_amount / 1000000) })
}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.requested_facilities")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.requested_facility_amount / 1000000) >= 1000
? t("UserInfoDialog.milyard", {value : (row.original.requested_facility_amount / 1000000000)})
:t("UserInfoDialog.toman", {value : (row.original.requested_facility_amount / 1000000)})
}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.applicant_payment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.person_share / 1000000) >= 1000
? t("UserInfoDialog.milyard", {value : (row.original.person_share / 1000000000)})
:t("UserInfoDialog.toman", {value : (row.original.person_share / 1000000)})
}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.user_committed_employment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.user_committed_employment || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.user_existing_employment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.user_existing_employment || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={12}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.plate")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Stack sx={{ border: 1, borderColor: "divider", borderRadius: 1 }} direction={"row"}>
<Stack
sx={{
borderRight: 1,
borderColor: "divider",
textAlign: "center",
width: "100%",
px: 1,
}}
>
{row.original.plate_number.split("-")[3] || t("UserInfoDialog.no_info")}
</Stack>
<Stack spacing={1} direction={"row"} sx={{ width: "100%" }}>
<Stack
sx={{
textAlign: "center",
width: "100%",
pl: 1,
}}
>
{row.original.plate_number.split("-")[2] || t("UserInfoDialog.no_info")}
</Stack>
<Stack
sx={{
textAlign: "center",
width: "100%",
pl: 1,
}}
>
{row.original.plate_number.split("-")[1] || t("UserInfoDialog.no_info")}
</Stack>
<Stack
sx={{
textAlign: "center",
width: "100%",
px: 1,
}}
>
{row.original.plate_number.split("-")[0] || t("UserInfoDialog.no_info")}
</Stack>
</Stack>
</Stack>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={12}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.address")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.address || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
</DialogContent>
</>
);
};
export default LegalTableContent;

View File

@@ -0,0 +1,353 @@
import { Chip, DialogContent, DialogTitle, Divider, Grid, Stack, Typography } from "@mui/material";
import { useTranslations } from "next-intl";
import moment from "jalali-moment";
const RealTableContent = ({ rowId, row }) => {
const t = useTranslations();
return (
<>
<DialogTitle>{t("UserInfoDialog.user_info")}</DialogTitle>
<DialogContent>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.is_legal_person")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">{t("UserInfoDialog.real_person")}</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">{row.original.id || t("UserInfoDialog.no_info")}</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_plan_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.project_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.activity_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.activity_category_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.first_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.first_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.last_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.last_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.national_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.national_id || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip
label={
row.original.national_serial_number
? t("UserInfoDialog.national_serial_number")
: t("UserInfoDialog.national_tracking_code")
}
sx={{ mr: 1 }}
/>
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.national_serial_number ||
row.original.national_tracking_code ||
t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.education_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.education_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.occupation_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.occupation_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.phone_number")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.phone_number || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.tel_number")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.telephone_number || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.birthday")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.birthday
? moment(row.original.birthday).locale("fa").format("YYYY/MM/DD")
: t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.postal_code")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.postal_code || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.father_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.father_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.gender")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.gender ? t("UserInfoDialog.female") : t("UserInfoDialog.male")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.province_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.province_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.city_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">{row.original.city_name}</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.navgan_id || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.navgan_type || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.user_committed_employment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.user_committed_employment || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.user_existing_employment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.user_existing_employment || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.vehicle_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.vehicle_type || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.investment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.investment_amount / 1000000) >= 1000
? t("UserInfoDialog.milyard", { value: (row.original.investment_amount / 1000000000) })
: t("UserInfoDialog.toman", { value: (row.original.investment_amount / 1000000) })
}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.requested_facilities")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.requested_facility_amount / 1000000) >= 1000
? t("UserInfoDialog.milyard", {value : (row.original.requested_facility_amount / 1000000000)})
:t("UserInfoDialog.toman", {value : (row.original.requested_facility_amount / 1000000)})
}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.applicant_payment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.person_share / 1000000) >= 1000
? t("UserInfoDialog.milyard", {value : (row.original.person_share / 1000000000)})
:t("UserInfoDialog.toman", {value : (row.original.person_share / 1000000)})
}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={12}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.plate")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Stack sx={{ border: 1, borderColor: "divider", borderRadius: 1 }} direction={"row"}>
<Stack
sx={{
borderRight: 1,
borderColor: "divider",
textAlign: "center",
width: "100%",
px: 1,
}}
>
{row.original.plate_number.split("-")[3] || t("UserInfoDialog.no_info")}
</Stack>
<Stack spacing={1} direction={"row"} sx={{ width: "100%" }}>
<Stack
sx={{
textAlign: "center",
width: "100%",
pl: 1,
}}
>
{row.original.plate_number.split("-")[2] || t("UserInfoDialog.no_info")}
</Stack>
<Stack
sx={{
textAlign: "center",
width: "100%",
pl: 1,
}}
>
{row.original.plate_number.split("-")[1] || t("UserInfoDialog.no_info")}
</Stack>
<Stack
sx={{
textAlign: "center",
width: "100%",
px: 1,
}}
>
{row.original.plate_number.split("-")[0] || t("UserInfoDialog.no_info")}
</Stack>
</Stack>
</Stack>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={12}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.address")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.address || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
</DialogContent>
</>
);
};
export default RealTableContent;

View File

@@ -0,0 +1,47 @@
import { Button, Dialog, DialogActions, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import ContactPageIcon from "@mui/icons-material/ContactPage";
import LegalTableContent from "./LegalTableContent";
import RealTableContent from "./RealTableContent";
const UserInfoForm = ({ rowId, row }) => {
const t = useTranslations();
const [openUserInfoDialog, setOpenUserInfoDialog] = useState(false);
return (
<>
<Tooltip title={t("UserInfoDialog.user_info_tooltip")}>
<IconButton
color="primary"
onClick={() => {
setOpenUserInfoDialog(true);
}}
>
<ContactPageIcon />
</IconButton>
</Tooltip>
<Dialog
open={openUserInfoDialog}
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",
},
}}
fullWidth
maxWidth="lg"
>
{row.original.is_legal_person === 1 ? (
<LegalTableContent rowId={rowId} row={row} />
) : (
<RealTableContent rowId={rowId} row={row} />
)}
<DialogActions>
<Button onClick={() => setOpenUserInfoDialog(false)} variant="outlined" color="secondary" autoFocus>
{t("UserInfoDialog.button-cancel")}
</Button>
</DialogActions>
</Dialog>
</>
);
};
export default UserInfoForm;

View File

@@ -1,17 +1,16 @@
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import ReferPassengerBoss from "@/components/dashboard/loan-followup/Form/ReferPassengerBoss"; import ReferPassengerBoss from "@/components/dashboard/loan-followup/Form/ReferPassengerBoss";
import UserInfoForm from "./Form/UserInfoForm";
import PlanningCouncilForm from "@/components/dashboard/loan-followup/Form/PlanningCouncilForm";
const TableRow = ({ row, mutate }) => { const TableRow = ({ row, mutate }) => {
return ( return (
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}> <Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
{ <UserInfoForm rowId={row.getValue("id")} row={row} />
row.original.state_id === 11 || row.original.state_id === 16 ? ( <PlanningCouncilForm rowId={row.getValue("id")} />
<ReferPassengerBoss {row.original.state_id === 11 || row.original.state_id === 16 ? (
rowId={row.getValue("id")} <ReferPassengerBoss rowId={row.getValue("id")} mutate={mutate} />
mutate={mutate} ) : null}
/>
) : null
}
</Box> </Box>
); );
}; };

View File

@@ -1,10 +1,7 @@
import { Stack } from "@mui/material"; import { Stack } from "@mui/material";
const TableToolbar = ({ table }) => { const TableToolbar = ({ table }) => {
return ( return <Stack direction={"row"} spacing={2}></Stack>;
<Stack direction={"row"} spacing={2}> };
</Stack>
)
}
export default TableToolbar export default TableToolbar;

View File

@@ -19,17 +19,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.navgan_id, accessorFn: (row) => row.navgan_id,
@@ -38,17 +29,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.name, accessorFn: (row) => row.name,
@@ -58,9 +40,7 @@ function DashboardLoanFollowUpComponent () {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_id, accessorFn: (row) => row.national_id,
@@ -69,17 +49,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.shenase_meli, accessorFn: (row) => row.shenase_meli,
@@ -88,17 +59,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_serial_number, accessorFn: (row) => row.national_serial_number,
@@ -107,17 +69,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_tracking_code, accessorFn: (row) => row.national_tracking_code,
@@ -126,14 +79,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "text", datatype: "text",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.birthday, accessorFn: (row) => row.birthday,
@@ -144,8 +91,9 @@ function DashboardLoanFollowUpComponent () {
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({ renderedCellValue }) => ( Cell: ({ renderedCellValue }) => (
<Typography <Typography variant="body2">
variant="body2">{moment(renderedCellValue).locale("fa").format("yyyy/MM/DD")}</Typography> {moment(renderedCellValue).locale("fa").format("yyyy/MM/DD")}
</Typography>
), ),
}, },
{ {
@@ -155,11 +103,7 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "text", datatype: "text",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains"],
"equals",
"notEquals",
"contains",
],
Cell: ({ renderedCellValue }) => ( Cell: ({ renderedCellValue }) => (
<Typography variant="body2">{Number(renderedCellValue).toLocaleString()}</Typography> <Typography variant="body2">{Number(renderedCellValue).toLocaleString()}</Typography>
), ),
@@ -172,9 +116,7 @@ function DashboardLoanFollowUpComponent () {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.province_name, accessorFn: (row) => row.province_name,
@@ -184,9 +126,7 @@ function DashboardLoanFollowUpComponent () {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.city_name, accessorFn: (row) => row.city_name,
@@ -196,13 +136,10 @@ function DashboardLoanFollowUpComponent () {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "created_at", id: "created_at",
header: t("LoanFollowUp.created_at"), header: t("LoanFollowUp.created_at"),
enableColumnFilter: true, enableColumnFilter: true,
@@ -214,9 +151,7 @@ function DashboardLoanFollowUpComponent () {
}, },
Header: ({ column }) => <>{column.columnDef.header}</>, Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => { Filter: ({ column }) => {
return ( return <MuiDatePicker column={column} />;
<MuiDatePicker column={column}/>
);
}, },
}, },
{ {
@@ -226,17 +161,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.state_name, accessorFn: (row) => row.state_name,
@@ -244,9 +170,7 @@ function DashboardLoanFollowUpComponent () {
header: t("LoanFollowUp.state_name"), header: t("LoanFollowUp.state_name"),
enableColumnFilter: false, enableColumnFilter: false,
datatype: "numeric", datatype: "numeric",
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
], ],
[] []
@@ -262,7 +186,7 @@ function DashboardLoanFollowUpComponent () {
enableLastUpdate={true} enableLastUpdate={true}
enablePinning={true} enablePinning={true}
enableDensityToggle={false} enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large) initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true} enableColumnFilters={true}
enableHiding={true} enableHiding={true}
enableFullScreenToggle={false} enableFullScreenToggle={false}
@@ -274,4 +198,4 @@ function DashboardLoanFollowUpComponent () {
</Box> </Box>
); );
} }
export default DashboardLoanFollowUpComponent export default DashboardLoanFollowUpComponent;

View File

@@ -4,15 +4,15 @@ import {useMemo, useState} from "react";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import { EXPORT_LOAN_HISTORY } from "@/core/data/apiRoutes"; import { EXPORT_LOAN_HISTORY } from "@/core/data/apiRoutes";
import moment from "jalali-moment"; import moment from "jalali-moment";
import FileSaver from 'file-saver'; import FileSaver from "file-saver";
import DescriptionIcon from '@mui/icons-material/Description'; import DescriptionIcon from "@mui/icons-material/Description";
const PrintExcel = ({ table }) => { const PrintExcel = ({ table }) => {
const t = useTranslations(); const t = useTranslations();
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false);
const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}}) const requestServer = useRequest({ auth: true, pending: false, success: { notification: { show: false } } });
const {columnFilters, columnFilterFns, sorting} = table.getState() const { columnFilters, columnFilterFns, sorting } = table.getState();
const columns = table.getAllColumns() const columns = table.getAllColumns();
const filterParams = useMemo(() => { const filterParams = useMemo(() => {
const params = new URLSearchParams(); const params = new URLSearchParams();
@@ -24,30 +24,32 @@ const PrintExcel = ({table}) => {
} }
} }
return { return {
...filter, fn: columnFilterFns[filter.id], datatype: datatype, ...filter,
fn: columnFilterFns[filter.id],
datatype: datatype,
}; };
}); });
params.set("start", '0'); params.set("start", "0");
params.set("filters", JSON.stringify(filters ?? [])); params.set("filters", JSON.stringify(filters ?? []));
params.set("sorting", JSON.stringify(sorting ?? [])); params.set("sorting", JSON.stringify(sorting ?? []));
return params; return params;
}, [columnFilters, columnFilterFns, sorting, columns,]); }, [columnFilters, columnFilterFns, sorting, columns]);
const clickHandler = () => { const clickHandler = () => {
setLoading(true) setLoading(true);
requestServer(`${EXPORT_LOAN_HISTORY}?${filterParams}`, 'get', { requestServer(`${EXPORT_LOAN_HISTORY}?${filterParams}`, "get", {
auth: true, auth: true,
requestOptions: {responseType: 'blob'} requestOptions: { responseType: "blob" },
}).then((response) => {
const filename = `خروجی کارتابل نظارت تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`;
FileSaver.saveAs(response.data, filename);
}).catch(() => {
}).finally(() => {
setLoading(false)
}) })
} .then((response) => {
const filename = `خروجی کارتابل نظارت تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})
.finally(() => {
setLoading(false);
});
};
return ( return (
<Button <Button
@@ -61,7 +63,7 @@ const PrintExcel = ({table}) => {
> >
{t("LoanHistory.excel_report")} {t("LoanHistory.excel_report")}
</Button> </Button>
) );
} };
export default PrintExcel export default PrintExcel;

View File

@@ -1,4 +1,4 @@
import {Button, DialogActions, DialogContent,} from "@mui/material" import { Button, DialogActions, DialogContent } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useFormik } from "formik"; import { useFormik } from "formik";
import TableContent from "@/components/dashboard/loan-history/Form/HistoryForm/TableContent"; import TableContent from "@/components/dashboard/loan-history/Form/HistoryForm/TableContent";
@@ -14,13 +14,17 @@ const HistoryContent = ({mutate, setOpenConfirmDialog, rowId}) => {
<TableContent rowId={rowId} /> <TableContent rowId={rowId} />
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ConfirmDialog.button-cancel")} {t("ConfirmDialog.button-cancel")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
};
} export default HistoryContent;
export default HistoryContent

View File

@@ -2,7 +2,7 @@ import {Button, CircularProgress} from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import DescriptionIcon from '@mui/icons-material/Description'; import DescriptionIcon from "@mui/icons-material/Description";
import Link from "next/link"; import Link from "next/link";
const PrintHistory = ({ attachment }) => { const PrintHistory = ({ attachment }) => {
@@ -20,6 +20,6 @@ const PrintHistory = ({attachment}) => {
{attachment.title} {attachment.title}
</Button> </Button>
); );
} };
export default PrintHistory export default PrintHistory;

View File

@@ -8,7 +8,7 @@ import {
TableContainer, TableContainer,
TableHead, TableHead,
TableRow, TableRow,
Typography Typography,
} from "@mui/material"; } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { GET_HISTORY_DETAIL } from "@/core/data/apiRoutes"; import { GET_HISTORY_DETAIL } from "@/core/data/apiRoutes";
@@ -18,43 +18,71 @@ import useRequest from "@/lib/app/hooks/useRequest";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
const action_name = { const action_name = {
"confirm" : "تایید", confirm: "تایید",
"reject":"عدم تایید", reject: "عدم تایید",
"refer":"ارجاع", refer: "ارجاع",
"reserve" : "رزرو" reserve: "رزرو",
} };
const TableContent = ({ rowId }) => { const TableContent = ({ rowId }) => {
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true, notification: false}) const requestServer = useRequest({ auth: true, notification: false });
const [historyDetails, setHistoryDetails] = useState([]); const [historyDetails, setHistoryDetails] = useState([]);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(false); const [error, setError] = useState(false);
useEffect(() => { useEffect(() => {
requestServer(`${GET_HISTORY_DETAIL}/${rowId}`, 'get').then((response) => { requestServer(`${GET_HISTORY_DETAIL}/${rowId}`, "get")
.then((response) => {
setIsLoading(false); setIsLoading(false);
setHistoryDetails(response.data.data); setHistoryDetails(response.data.data);
}).catch(() => {
setError(true);
}) })
.catch(() => {
setError(true);
});
}, []); }, []);
return (<Box> return (
{error ? (<Typography sx={{ <Box>
padding: 2, display: "flex", alignItems: "center", justifyContent: "center" {error ? (
}}>{t("LoanHistory.Table_history_error")}</Typography>) : (isLoading ? ( <Typography
<LinearProgress sx={{width: "100%"}}/>) : (historyDetails.latest_histories.length === 0 ? (<Typography
sx={{ sx={{
padding: 2, display: "flex", alignItems: "center", justifyContent: "center" padding: 2,
display: "flex",
alignItems: "center",
justifyContent: "center",
}} }}
variant={'h6'}>{t("LoanHistory.empty_history_detail")}</Typography>) : (<Paper elevation={0} sx={{ >
width: '100%', overflow: 'hidden', '*::-webkit-scrollbar': { {t("LoanHistory.Table_history_error")}
width: '0.5em' </Typography>
}, '*::-webkit-scrollbar-thumb': { ) : isLoading ? (
backgroundColor: 'primary.main', <LinearProgress sx={{ width: "100%" }} />
} ) : historyDetails.latest_histories.length === 0 ? (
}}> <Typography
sx={{
padding: 2,
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
variant={"h6"}
>
{t("LoanHistory.empty_history_detail")}
</Typography>
) : (
<Paper
elevation={0}
sx={{
width: "100%",
overflow: "hidden",
"*::-webkit-scrollbar": {
width: "0.5em",
},
"*::-webkit-scrollbar-thumb": {
backgroundColor: "primary.main",
},
}}
>
<TableContainer sx={{ maxHeight: 600 }}> <TableContainer sx={{ maxHeight: 600 }}>
<Table stickyHeader sx={{ minWidth: 800 }}> <Table stickyHeader sx={{ minWidth: 800 }}>
<TableHead> <TableHead>
@@ -70,30 +98,37 @@ const TableContent = ({rowId}) => {
</TableHead> </TableHead>
<TableBody> <TableBody>
{historyDetails.latest_histories.map((latest_history, index) => { {historyDetails.latest_histories.map((latest_history, index) => {
return (<TableRow return (
<TableRow
key={index} key={index}
sx={{ sx={{
'&:last-child td, &:last-child th': {border: 0} "&:last-child td, &:last-child th": { border: 0 },
}} }}
> >
<TableCell> {latest_history.expert.name}</TableCell> <TableCell> {latest_history.expert.name}</TableCell>
<TableCell>{moment(latest_history.created_at).locale("fa").format("HH:mm | yyyy/MM/DD")}</TableCell> <TableCell>
{moment(latest_history.created_at)
.locale("fa")
.format("HH:mm | yyyy/MM/DD")}
</TableCell>
<TableCell>{latest_history.expert.position}</TableCell> <TableCell>{latest_history.expert.position}</TableCell>
<TableCell>{latest_history.previous_state_name}</TableCell> <TableCell>{latest_history.previous_state_name}</TableCell>
<TableCell>{action_name[latest_history.action]}</TableCell> <TableCell>{action_name[latest_history.action]}</TableCell>
<TableCell>{latest_history.expert_description}</TableCell> <TableCell>{latest_history.expert_description}</TableCell>
<TableCell> <TableCell>
{latest_history.attachments.map((attachment, index) => <PrintHistory key={index} {latest_history.attachments.map((attachment, index) => (
attachment={attachment}/>)} <PrintHistory key={index} attachment={attachment} />
))}
</TableCell> </TableCell>
</TableRow>) </TableRow>
);
})} })}
</TableBody> </TableBody>
</Table> </Table>
</TableContainer> </TableContainer>
</Paper>)))} </Paper>
)}
</Box> </Box>
);
) };
} export default TableContent;
export default TableContent

View File

@@ -1,7 +1,7 @@
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
import HistoryIcon from '@mui/icons-material/History'; import HistoryIcon from "@mui/icons-material/History";
import HistoryContent from "@/components/dashboard/loan-history/Form/HistoryForm/HistoryContent"; import HistoryContent from "@/components/dashboard/loan-history/Form/HistoryForm/HistoryContent";
const History = ({ rowId, mutate }) => { const History = ({ rowId, mutate }) => {
@@ -13,19 +13,27 @@ const History = ({rowId, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenConfirmDialog(true) setOpenConfirmDialog(true);
}} }}
> >
<HistoryIcon /> <HistoryIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog scroll={'paper'} fullWidth maxWidth="xl" open={openConfirmDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> scroll={"paper"}
fullWidth
maxWidth="xl"
open={openConfirmDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("LoanHistory.history")}</DialogTitle> <DialogTitle>{t("LoanHistory.history")}</DialogTitle>
<HistoryContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} /> <HistoryContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog> </Dialog>
</> </>
) );
};
}
export default History; export default History;

View File

@@ -4,11 +4,7 @@ import History from "@/components/dashboard/loan-history/Form/HistoryForm";
const TableRow = ({ row, mutate }) => { const TableRow = ({ row, mutate }) => {
return ( return (
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}> <Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
<History <History rowId={row.getValue("id")} vehicle_type={row.original.vehicle_type} mutate={mutate} />
rowId={row.getValue("id")}
vehicle_type={row.original.vehicle_type}
mutate={mutate}
/>
</Box> </Box>
); );
}; };

View File

@@ -6,7 +6,7 @@ const TableToolbar = ({table}) => {
<Stack direction={"row"} spacing={2}> <Stack direction={"row"} spacing={2}>
<PrintExcel table={table} /> <PrintExcel table={table} />
</Stack> </Stack>
) );
} };
export default TableToolbar export default TableToolbar;

View File

@@ -19,17 +19,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.is_legal_person, accessorFn: (row) => row.is_legal_person,
@@ -40,8 +31,9 @@ function DashboardLoanHistoryComponent() {
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: ["equals"], columnFilterModeOptions: ["equals"],
Cell: ({ renderedCellValue }) => ( Cell: ({ renderedCellValue }) => (
<Typography <Typography variant="body2">
variant="body2">{renderedCellValue === 1 ? `${t("LoanHistory.hoghoghi")}` : `${t("LoanHistory.haghighi")}`}</Typography> {renderedCellValue === 1 ? `${t("LoanHistory.hoghoghi")}` : `${t("LoanHistory.haghighi")}`}
</Typography>
), ),
}, },
{ {
@@ -51,17 +43,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.name, accessorFn: (row) => row.name,
@@ -71,9 +54,7 @@ function DashboardLoanHistoryComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_id, accessorFn: (row) => row.national_id,
@@ -82,17 +63,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.shenase_meli, accessorFn: (row) => row.shenase_meli,
@@ -101,17 +73,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.province_name, accessorFn: (row) => row.province_name,
@@ -121,9 +84,7 @@ function DashboardLoanHistoryComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.city_name, accessorFn: (row) => row.city_name,
@@ -133,9 +94,7 @@ function DashboardLoanHistoryComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.postal_code, accessorFn: (row) => row.postal_code,
@@ -144,18 +103,11 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "created_at", id: "created_at",
header: t("LoanHistory.created_at"), header: t("LoanHistory.created_at"),
enableColumnFilter: true, enableColumnFilter: true,
@@ -167,9 +119,7 @@ function DashboardLoanHistoryComponent() {
}, },
Header: ({ column }) => <>{column.columnDef.header}</>, Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => { Filter: ({ column }) => {
return ( return <MuiDatePicker column={column} />;
<MuiDatePicker column={column}/>
);
}, },
}, },
{ {
@@ -179,17 +129,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.statement_count, accessorFn: (row) => row.statement_count,
@@ -198,12 +139,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.navgan_capacity, accessorFn: (row) => row.navgan_capacity,
@@ -212,17 +149,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.manufacture_date, accessorFn: (row) => row.manufacture_date,
@@ -231,17 +159,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.vehicle_type, accessorFn: (row) => row.vehicle_type,
@@ -251,9 +170,7 @@ function DashboardLoanHistoryComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.plate_number, accessorFn: (row) => row.plate_number,
@@ -264,23 +181,35 @@ function DashboardLoanHistoryComponent() {
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({ renderedCellValue }) => ( Cell: ({ renderedCellValue }) => (
<Stack sx={{border: 1, borderColor: "divider", borderRadius: 1}} direction={'row'}> <Stack sx={{ border: 1, borderColor: "divider", borderRadius: 1 }} direction={"row"}>
<Stack sx={{borderRight: 1, borderColor: "divider", textAlign: 'center', width: "40%"}}> <Stack sx={{ borderRight: 1, borderColor: "divider", textAlign: "center", width: "40%" }}>
{renderedCellValue.split('-')[3]} {renderedCellValue.split("-")[3]}
</Stack> </Stack>
<Stack direction={'row'} sx={{width: "100%", px: 0.5}}> <Stack direction={"row"} sx={{ width: "100%", px: 0.5 }}>
<Stack sx={{ <Stack
sx={{
textAlign: "center", textAlign: "center",
width: "100%" width: "100%",
}}>{renderedCellValue.split('-')[2]}</Stack> }}
<Stack sx={{ >
{renderedCellValue.split("-")[2]}
</Stack>
<Stack
sx={{
textAlign: "center", textAlign: "center",
width: "100%" width: "100%",
}}>{renderedCellValue.split('-')[1]}</Stack> }}
<Stack sx={{ >
{renderedCellValue.split("-")[1]}
</Stack>
<Stack
sx={{
textAlign: "center", textAlign: "center",
width: "100%" width: "100%",
}}>{renderedCellValue.split('-')[0]}</Stack> }}
>
{renderedCellValue.split("-")[0]}
</Stack>
</Stack> </Stack>
</Stack> </Stack>
), ),
@@ -292,17 +221,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.facility_bank, accessorFn: (row) => row.facility_bank,
@@ -311,17 +231,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.facility_gov, accessorFn: (row) => row.facility_gov,
@@ -330,17 +241,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.facility_person, accessorFn: (row) => row.facility_person,
@@ -349,17 +251,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.physical_progress, accessorFn: (row) => row.physical_progress,
@@ -368,17 +261,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.repayment_period, accessorFn: (row) => row.repayment_period,
@@ -387,17 +271,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.sakht_period, accessorFn: (row) => row.sakht_period,
@@ -406,12 +281,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals"],
"equals" Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.tanafos_period, accessorFn: (row) => row.tanafos_period,
@@ -420,12 +291,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals"],
"equals" Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.committed_employment, accessorFn: (row) => row.committed_employment,
@@ -434,17 +301,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.existing_employment, accessorFn: (row) => row.existing_employment,
@@ -453,17 +311,8 @@ function DashboardLoanHistoryComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.state_name, accessorFn: (row) => row.state_name,
@@ -473,9 +322,7 @@ function DashboardLoanHistoryComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
], ],
[] []
@@ -489,12 +336,15 @@ function DashboardLoanHistoryComponent() {
enableCustomToolbar={true} enableCustomToolbar={true}
CustomToolbar={TableToolbar} CustomToolbar={TableToolbar}
enableLastUpdate={true} enableLastUpdate={true}
sorting={[{ sorting={[
id: 'statement_count', desc: true {
}]} id: "statement_count",
desc: true,
},
]}
enablePinning={true} enablePinning={true}
enableDensityToggle={false} enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large) initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true} enableColumnFilters={true}
enableHiding={true} enableHiding={true}
enableFullScreenToggle={false} enableFullScreenToggle={false}

View File

@@ -4,15 +4,15 @@ import {useMemo, useState} from "react";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import { EXPORT_LOAN_MANAGEMENT_HISTORY } from "@/core/data/apiRoutes"; import { EXPORT_LOAN_MANAGEMENT_HISTORY } from "@/core/data/apiRoutes";
import moment from "jalali-moment"; import moment from "jalali-moment";
import FileSaver from 'file-saver'; import FileSaver from "file-saver";
import DescriptionIcon from '@mui/icons-material/Description'; import DescriptionIcon from "@mui/icons-material/Description";
const PrintExcel = ({ table }) => { const PrintExcel = ({ table }) => {
const t = useTranslations(); const t = useTranslations();
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false);
const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}}) const requestServer = useRequest({ auth: true, pending: false, success: { notification: { show: false } } });
const {columnFilters, columnFilterFns, sorting} = table.getState() const { columnFilters, columnFilterFns, sorting } = table.getState();
const columns = table.getAllColumns() const columns = table.getAllColumns();
const filterParams = useMemo(() => { const filterParams = useMemo(() => {
const params = new URLSearchParams(); const params = new URLSearchParams();
@@ -24,30 +24,32 @@ const PrintExcel = ({table}) => {
} }
} }
return { return {
...filter, fn: columnFilterFns[filter.id], datatype: datatype, ...filter,
fn: columnFilterFns[filter.id],
datatype: datatype,
}; };
}); });
params.set("start", '0'); params.set("start", "0");
params.set("filters", JSON.stringify(filters ?? [])); params.set("filters", JSON.stringify(filters ?? []));
params.set("sorting", JSON.stringify(sorting ?? [])); params.set("sorting", JSON.stringify(sorting ?? []));
return params; return params;
}, [columnFilters, columnFilterFns, sorting, columns,]); }, [columnFilters, columnFilterFns, sorting, columns]);
const clickHandler = () => { const clickHandler = () => {
setLoading(true) setLoading(true);
requestServer(`${EXPORT_LOAN_MANAGEMENT_HISTORY}?${filterParams}`, 'get', { requestServer(`${EXPORT_LOAN_MANAGEMENT_HISTORY}?${filterParams}`, "get", {
auth: true, auth: true,
requestOptions: {responseType: 'blob'} requestOptions: { responseType: "blob" },
}).then((response) => {
const filename = `خروجی کارتابل مدیریت وام ها تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`;
FileSaver.saveAs(response.data, filename);
}).catch(() => {
}).finally(() => {
setLoading(false)
}) })
} .then((response) => {
const filename = `خروجی کارتابل مدیریت وام ها تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})
.finally(() => {
setLoading(false);
});
};
return ( return (
<Button <Button
@@ -61,7 +63,7 @@ const PrintExcel = ({table}) => {
> >
{t("NavganLoanManagement.excel_report")} {t("NavganLoanManagement.excel_report")}
</Button> </Button>
) );
} };
export default PrintExcel export default PrintExcel;

View File

@@ -12,27 +12,27 @@ import {
MenuItem, MenuItem,
Select, Select,
Stack, Stack,
TextField TextField,
} from "@mui/material" } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import * as Yup from "yup"; import * as Yup from "yup";
const UpdateContent = ({ rowId, mutate, setOpenConfirmDialog }) => { const UpdateContent = ({ rowId, mutate, setOpenConfirmDialog }) => {
const t = useTranslations(); const t = useTranslations();
const {loan_state_navgan} = useLoanStateNavgan() const { loan_state_navgan } = useLoanStateNavgan();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
description: Yup.string().required(t("UpdateDialog.description_error")), description: Yup.string().required(t("UpdateDialog.description_error")),
next_state_id: Yup.number().required(t("UpdateDialog.next-state-id-error")) next_state_id: Yup.number().required(t("UpdateDialog.next-state-id-error")),
}); });
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
description: "", description: "",
next_state_id: "" next_state_id: "",
}, },
validationSchema, validationSchema,
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
@@ -40,24 +40,26 @@ const UpdateContent = ({rowId, mutate, setOpenConfirmDialog}) => {
formData.append("expert_description", values.description); formData.append("expert_description", values.description);
formData.append("next_state_id", values.next_state_id); formData.append("next_state_id", values.next_state_id);
requestServer(`${UPDATE_LOAN_MANAGEMENT_NAVGAN}/${rowId}`, 'post', { requestServer(`${UPDATE_LOAN_MANAGEMENT_NAVGAN}/${rowId}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenConfirmDialog(false) .then((response) => {
mutate() setOpenConfirmDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
}); });
const handleDescriptionChange = (event) => { const handleDescriptionChange = (event) => {
formik.setFieldValue("description", event.target.value) formik.setFieldValue("description", event.target.value);
}; };
const handleNextStateIDChange = (event) => { const handleNextStateIDChange = (event) => {
formik.setFieldValue("next_state_id", event.target.value) formik.setFieldValue("next_state_id", event.target.value);
}; };
return ( return (
<> <>
@@ -75,18 +77,15 @@ const UpdateContent = ({rowId, mutate, setOpenConfirmDialog}) => {
variant="outlined" variant="outlined"
sx={{ mt: 1 }} sx={{ mt: 1 }}
onBlur={formik.handleBlur("description")} onBlur={formik.handleBlur("description")}
error={ error={formik.touched.description && Boolean(formik.errors.description)}
formik.touched.description && Boolean(formik.errors.description)
}
helperText={formik.touched.description && formik.errors.description} helperText={formik.touched.description && formik.errors.description}
/> />
</Stack> </Stack>
<Stack> <Stack>
<FormControl <FormControl
error={ error={formik.touched.next_state_id && Boolean(formik.errors.next_state_id)}
formik.touched.next_state_id && fullWidth
Boolean(formik.errors.next_state_id) >
} fullWidth>
<InputLabel>{t("UpdateDialog.next-state-id")}</InputLabel> <InputLabel>{t("UpdateDialog.next-state-id")}</InputLabel>
<Select <Select
labelId="next_state_id" labelId="next_state_id"
@@ -96,11 +95,15 @@ const UpdateContent = ({rowId, mutate, setOpenConfirmDialog}) => {
onChange={handleNextStateIDChange} onChange={handleNextStateIDChange}
onBlur={formik.handleBlur("next_state_id")} onBlur={formik.handleBlur("next_state_id")}
> >
{loan_state_navgan ? (loan_state_navgan.map((item) => { {loan_state_navgan
? loan_state_navgan.map((item) => {
return ( return (
<MenuItem key={item.id} value={item.id}>{item.name}</MenuItem> <MenuItem key={item.id} value={item.id}>
) {item.name}
})) : null} </MenuItem>
);
})
: null}
</Select> </Select>
<FormHelperText> <FormHelperText>
{formik.touched.next_state_id && formik.errors.next_state_id} {formik.touched.next_state_id && formik.errors.next_state_id}
@@ -110,16 +113,25 @@ const UpdateContent = ({rowId, mutate, setOpenConfirmDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("UpdateDialog.button-cancel")} {t("UpdateDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("UpdateDialog.button-update")} {t("UpdateDialog.button-update")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
} };
export default UpdateContent export default UpdateContent;

View File

@@ -1,6 +1,6 @@
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import ChangeCircleIcon from '@mui/icons-material/ChangeCircle'; import ChangeCircleIcon from "@mui/icons-material/ChangeCircle";
import { useState } from "react"; import { useState } from "react";
import UpdateContent from "./UpdateContent"; import UpdateContent from "./UpdateContent";
@@ -13,18 +13,25 @@ const Update = ({rowId, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenConfirmDialog(true) setOpenConfirmDialog(true);
}} }}
> >
<ChangeCircleIcon /> <ChangeCircleIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openConfirmDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openConfirmDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("UpdateDialog.update")}</DialogTitle> <DialogTitle>{t("UpdateDialog.update")}</DialogTitle>
<UpdateContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} /> <UpdateContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog> </Dialog>
</> </>
) );
} };
export default Update export default Update;

View File

@@ -1,14 +1,10 @@
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import Update from "./Form/UpdateForm" import Update from "./Form/UpdateForm";
const TableRowActions = ({ row, mutate }) => { const TableRowActions = ({ row, mutate }) => {
return ( return (
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}> <Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
<Update <Update rowId={row.getValue("id")} mutate={mutate} />
rowId={row.getValue("id")}
mutate={mutate}
/>
</Box> </Box>
); );
}; };

View File

@@ -6,7 +6,7 @@ const TableToolbar = ({table}) => {
<Stack direction={"row"} spacing={2}> <Stack direction={"row"} spacing={2}>
<PrintExcel table={table} /> <PrintExcel table={table} />
</Stack> </Stack>
) );
} };
export default TableToolbar export default TableToolbar;

View File

@@ -20,17 +20,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.is_legal_person, accessorFn: (row) => row.is_legal_person,
@@ -41,8 +32,11 @@ function DashboardNavganLoanManagementComponent() {
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: ["equals"], columnFilterModeOptions: ["equals"],
Cell: ({ renderedCellValue }) => ( Cell: ({ renderedCellValue }) => (
<Typography <Typography variant="body2">
variant="body2">{renderedCellValue === 1 ? `${t("NavganLoanManagement.hoghoghi")}` : `${t("NavganLoanManagement.haghighi")}`}</Typography> {renderedCellValue === 1
? `${t("NavganLoanManagement.hoghoghi")}`
: `${t("NavganLoanManagement.haghighi")}`}
</Typography>
), ),
}, },
{ {
@@ -52,17 +46,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.name, accessorFn: (row) => row.name,
@@ -72,9 +57,7 @@ function DashboardNavganLoanManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_id, accessorFn: (row) => row.national_id,
@@ -83,17 +66,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.shenase_meli, accessorFn: (row) => row.shenase_meli,
@@ -102,17 +76,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.province_name, accessorFn: (row) => row.province_name,
@@ -122,9 +87,7 @@ function DashboardNavganLoanManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.city_name, accessorFn: (row) => row.city_name,
@@ -134,13 +97,10 @@ function DashboardNavganLoanManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "created_at", id: "created_at",
header: t("NavganLoanManagement.created_at"), header: t("NavganLoanManagement.created_at"),
enableColumnFilter: true, enableColumnFilter: true,
@@ -152,9 +112,7 @@ function DashboardNavganLoanManagementComponent() {
}, },
Header: ({ column }) => <>{column.columnDef.header}</>, Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => { Filter: ({ column }) => {
return ( return <MuiDatePicker column={column} />;
<MuiDatePicker column={column}/>
);
}, },
}, },
{ {
@@ -164,17 +122,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.statement_count, accessorFn: (row) => row.statement_count,
@@ -183,12 +132,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.navgan_capacity, accessorFn: (row) => row.navgan_capacity,
@@ -197,17 +142,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.manufacture_date, accessorFn: (row) => row.manufacture_date,
@@ -216,17 +152,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.vehicle_type, accessorFn: (row) => row.vehicle_type,
@@ -236,9 +163,7 @@ function DashboardNavganLoanManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.plate_number, accessorFn: (row) => row.plate_number,
@@ -249,23 +174,35 @@ function DashboardNavganLoanManagementComponent() {
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({ renderedCellValue }) => ( Cell: ({ renderedCellValue }) => (
<Stack sx={{border: 1, borderColor: "divider", borderRadius: 1}} direction={'row'}> <Stack sx={{ border: 1, borderColor: "divider", borderRadius: 1 }} direction={"row"}>
<Stack sx={{borderRight: 1, borderColor: "divider", textAlign: 'center', width: "40%"}}> <Stack sx={{ borderRight: 1, borderColor: "divider", textAlign: "center", width: "40%" }}>
{renderedCellValue.split('-')[3]} {renderedCellValue.split("-")[3]}
</Stack> </Stack>
<Stack direction={'row'} sx={{width: "100%", px: 0.5}}> <Stack direction={"row"} sx={{ width: "100%", px: 0.5 }}>
<Stack sx={{ <Stack
sx={{
textAlign: "center", textAlign: "center",
width: "100%" width: "100%",
}}>{renderedCellValue.split('-')[2]}</Stack> }}
<Stack sx={{ >
{renderedCellValue.split("-")[2]}
</Stack>
<Stack
sx={{
textAlign: "center", textAlign: "center",
width: "100%" width: "100%",
}}>{renderedCellValue.split('-')[1]}</Stack> }}
<Stack sx={{ >
{renderedCellValue.split("-")[1]}
</Stack>
<Stack
sx={{
textAlign: "center", textAlign: "center",
width: "100%" width: "100%",
}}>{renderedCellValue.split('-')[0]}</Stack> }}
>
{renderedCellValue.split("-")[0]}
</Stack>
</Stack> </Stack>
</Stack> </Stack>
), ),
@@ -277,17 +214,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.facility_bank, accessorFn: (row) => row.facility_bank,
@@ -296,17 +224,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.facility_gov, accessorFn: (row) => row.facility_gov,
@@ -315,17 +234,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.facility_person, accessorFn: (row) => row.facility_person,
@@ -334,17 +244,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.physical_progress, accessorFn: (row) => row.physical_progress,
@@ -353,17 +254,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.repayment_period, accessorFn: (row) => row.repayment_period,
@@ -372,17 +264,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.sakht_period, accessorFn: (row) => row.sakht_period,
@@ -391,12 +274,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals"],
"equals" Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.tanafos_period, accessorFn: (row) => row.tanafos_period,
@@ -405,12 +284,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals"],
"equals" Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.committed_employment, accessorFn: (row) => row.committed_employment,
@@ -419,17 +294,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.existing_employment, accessorFn: (row) => row.existing_employment,
@@ -438,17 +304,8 @@ function DashboardNavganLoanManagementComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.state_name, accessorFn: (row) => row.state_name,
@@ -458,9 +315,7 @@ function DashboardNavganLoanManagementComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
], ],
[] []
@@ -475,12 +330,15 @@ function DashboardNavganLoanManagementComponent() {
enableCustomToolbar={true} enableCustomToolbar={true}
CustomToolbar={TableToolbar} CustomToolbar={TableToolbar}
enableLastUpdate={true} enableLastUpdate={true}
sorting={[{ sorting={[
id: 'statement_count', desc: true {
}]} id: "statement_count",
desc: true,
},
]}
enablePinning={true} enablePinning={true}
enableDensityToggle={false} enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large) initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true} enableColumnFilters={true}
enableHiding={true} enableHiding={true}
enableFullScreenToggle={false} enableFullScreenToggle={false}

View File

@@ -4,15 +4,15 @@ import {useMemo, useState} from "react";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import { EXPORT_NAVGAN_PROVINCE_MANAGER } from "@/core/data/apiRoutes"; import { EXPORT_NAVGAN_PROVINCE_MANAGER } from "@/core/data/apiRoutes";
import moment from "jalali-moment"; import moment from "jalali-moment";
import FileSaver from 'file-saver'; import FileSaver from "file-saver";
import DescriptionIcon from '@mui/icons-material/Description'; import DescriptionIcon from "@mui/icons-material/Description";
const PrintExcel = ({ table }) => { const PrintExcel = ({ table }) => {
const t = useTranslations(); const t = useTranslations();
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false);
const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}}) const requestServer = useRequest({ auth: true, pending: false, success: { notification: { show: false } } });
const {columnFilters, columnFilterFns, sorting} = table.getState() const { columnFilters, columnFilterFns, sorting } = table.getState();
const columns = table.getAllColumns() const columns = table.getAllColumns();
const filterParams = useMemo(() => { const filterParams = useMemo(() => {
const params = new URLSearchParams(); const params = new URLSearchParams();
@@ -24,30 +24,32 @@ const PrintExcel = ({table}) => {
} }
} }
return { return {
...filter, fn: columnFilterFns[filter.id], datatype: datatype, ...filter,
fn: columnFilterFns[filter.id],
datatype: datatype,
}; };
}); });
params.set("start", '0'); params.set("start", "0");
params.set("filters", JSON.stringify(filters ?? [])); params.set("filters", JSON.stringify(filters ?? []));
params.set("sorting", JSON.stringify(sorting ?? [])); params.set("sorting", JSON.stringify(sorting ?? []));
return params; return params;
}, [columnFilters, columnFilterFns, sorting, columns,]); }, [columnFilters, columnFilterFns, sorting, columns]);
const clickHandler = () => { const clickHandler = () => {
setLoading(true) setLoading(true);
requestServer(`${EXPORT_NAVGAN_PROVINCE_MANAGER}?${filterParams}`, 'get', { requestServer(`${EXPORT_NAVGAN_PROVINCE_MANAGER}?${filterParams}`, "get", {
auth: true, auth: true,
requestOptions: {responseType: 'blob'} requestOptions: { responseType: "blob" },
}).then((response) => {
const filename = `خروجی کارتابل بررسی وام های تبصره 18 تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`;
FileSaver.saveAs(response.data, filename);
}).catch(() => {
}).finally(() => {
setLoading(false)
}) })
} .then((response) => {
const filename = `خروجی کارتابل بررسی وام های تبصره 18 تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})
.finally(() => {
setLoading(false);
});
};
return ( return (
<Button <Button
@@ -61,7 +63,7 @@ const PrintExcel = ({table}) => {
> >
{t("NavganProvinceManager.excel_report")} {t("NavganProvinceManager.excel_report")}
</Button> </Button>
) );
} };
export default PrintExcel export default PrintExcel;

View File

@@ -10,8 +10,8 @@ import {
LinearProgress, LinearProgress,
Stack, Stack,
TextField, TextField,
Typography Typography,
} from "@mui/material" } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { CONFIRM_NAVGAN_PROVINCE_MANAGER, CONFIRM_PROVINCE_MANAGER_DETAILS } from "@/core/data/apiRoutes"; import { CONFIRM_NAVGAN_PROVINCE_MANAGER, CONFIRM_PROVINCE_MANAGER_DETAILS } from "@/core/data/apiRoutes";
@@ -27,8 +27,8 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog, handleSizeChangeCl
const [fileType, setfileType] = useState(null); const [fileType, setfileType] = useState(null);
const [fileName, setfileName] = useState(null); const [fileName, setfileName] = useState(null);
const [showAddIcon, setShowAddIcon] = useState(true); const [showAddIcon, setShowAddIcon] = useState(true);
const requestServer = useRequest({auth: true, notification: false}) const requestServer = useRequest({ auth: true, notification: false });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const [attachmentsData, setAttachmentsData] = useState([]); const [attachmentsData, setAttachmentsData] = useState([]);
const [accordionStates, setAccordionStates] = useState([]); const [accordionStates, setAccordionStates] = useState([]);
const [hasImageShown, setHasImageShown] = useState(false); const [hasImageShown, setHasImageShown] = useState(false);
@@ -38,38 +38,39 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog, handleSizeChangeCl
const [isSkeleton, setIsSkeleton] = useState(false); const [isSkeleton, setIsSkeleton] = useState(false);
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
confirm_img: Yup.mixed().notRequired(t("ConfirmDialog.approved_amount_error")) confirm_img: Yup.mixed()
.test('fileSize', `${t("NavganProvinceManager.upload_file_unit")}`, (value) => { .notRequired(t("ConfirmDialog.approved_amount_error"))
if (!value) return true .test("fileSize", `${t("NavganProvinceManager.upload_file_unit")}`, (value) => {
if (!value) return true;
return value.size <= 5 * 1024 * 1024; return value.size <= 5 * 1024 * 1024;
}) })
.test('fileType', `${t("NavganProvinceManager.upload_file_format")}`, (value) => { .test("fileType", `${t("NavganProvinceManager.upload_file_format")}`, (value) => {
if (!value) return true if (!value) return true;
const allowedTypes = ['image/jpg', 'image/jpeg', 'image/png', 'application/pdf']; // Define your allowed file types const allowedTypes = ["image/jpg", "image/jpeg", "image/png", "application/pdf"]; // Define your allowed file types
return allowedTypes.includes(value.type); return allowedTypes.includes(value.type);
}) }),
}) });
useEffect(() => { useEffect(() => {
requestServer(`${CONFIRM_PROVINCE_MANAGER_DETAILS}/${rowId}`, 'get') requestServer(`${CONFIRM_PROVINCE_MANAGER_DETAILS}/${rowId}`, "get")
.then((response) => { .then((response) => {
if (response.data.data.latest_histories.length !== 0) { if (response.data.data.latest_histories.length !== 0) {
let latest_attachments = [] let latest_attachments = [];
let attachments = [] let attachments = [];
response.data.data.latest_histories.map((allAttachment) => { response.data.data.latest_histories.map((allAttachment) => {
if (allAttachment.previous_state_id === 4 || allAttachment.previous_state_id === 5) { if (allAttachment.previous_state_id === 4 || allAttachment.previous_state_id === 5) {
if (!latest_attachments.includes(allAttachment.previous_state_id)) { if (!latest_attachments.includes(allAttachment.previous_state_id)) {
attachments = [...attachments, ...allAttachment.attachments] attachments = [...attachments, ...allAttachment.attachments];
latest_attachments.push(allAttachment.previous_state_id) latest_attachments.push(allAttachment.previous_state_id);
} }
} }
setDetailsData(response.data); setDetailsData(response.data);
setAttachmentsData(attachments); setAttachmentsData(attachments);
}) });
} }
}) })
.catch(() => { .catch(() => {})
}).finally(() => { .finally(() => {
setLoading(false); setLoading(false);
}); });
}, []); }, []);
@@ -82,26 +83,27 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog, handleSizeChangeCl
}, [attachmentsData]); }, [attachmentsData]);
const handleAccordionChange = (index) => { const handleAccordionChange = (index) => {
const newAccordionStates = accordionStates.map((state, i) => i === index ? !state : false); const newAccordionStates = accordionStates.map((state, i) => (i === index ? !state : false));
setAccordionStates(newAccordionStates); setAccordionStates(newAccordionStates);
if (!newAccordionStates[index]) { if (!newAccordionStates[index]) {
handleSizeChangeClick('sm'); handleSizeChangeClick("sm");
setHasImageShown(false); setHasImageShown(false);
setIsSkeleton(false) setIsSkeleton(false);
} else { } else {
handleSizeChangeClick('xl'); handleSizeChangeClick("xl");
setHasImageShown(true); setHasImageShown(true);
setImageLink(attachmentsData[index]) setImageLink(attachmentsData[index]);
setIsSkeleton(true) setIsSkeleton(true);
} }
}; };
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
description: "", description: "",
confirm_img: null confirm_img: null,
}, validationSchema, },
validationSchema,
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
const formData = new FormData(); const formData = new FormData();
if (values.description !== "") formData.append("expert_description", values.description); if (values.description !== "") formData.append("expert_description", values.description);
@@ -109,30 +111,32 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog, handleSizeChangeCl
const attachments = [ const attachments = [
{ {
title: "فایل ضمیمه کارتابل بررسی وام های تبصره 18", title: "فایل ضمیمه کارتابل بررسی وام های تبصره 18",
file: values.confirm_img file: values.confirm_img,
} },
]; ];
attachments.forEach((attachment, index) => { attachments.forEach((attachment, index) => {
formData.append(`attachment[${index}][title]`, attachment.title); formData.append(`attachment[${index}][title]`, attachment.title);
formData.append(`attachment[${index}][file]`, attachment.file); formData.append(`attachment[${index}][file]`, attachment.file);
}); });
} }
requestServer(`${CONFIRM_NAVGAN_PROVINCE_MANAGER}/${rowId}`, 'post', { requestServer(`${CONFIRM_NAVGAN_PROVINCE_MANAGER}/${rowId}`, "post", {
data: formData, data: formData,
notification: true notification: true,
}).then((response) => { })
setOpenConfirmDialog(false) .then((response) => {
mutate() setOpenConfirmDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
}); });
const handleDescriptionChange = (event) => { const handleDescriptionChange = (event) => {
formik.setFieldValue("description", event.target.value) formik.setFieldValue("description", event.target.value);
}; };
const handleUploadChange = (event) => { const handleUploadChange = (event) => {
@@ -145,7 +149,7 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog, handleSizeChangeCl
setfileName(fileName); setfileName(fileName);
formik.setFieldValue("confirm_img", uploadedFile).then(() => { formik.setFieldValue("confirm_img", uploadedFile).then(() => {
formik.setFieldTouched("confirm_img", true); formik.setFieldTouched("confirm_img", true);
}) });
setShowAddIcon(false); setShowAddIcon(false);
} }
}; };
@@ -172,25 +176,27 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog, handleSizeChangeCl
<DialogContent> <DialogContent>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={hasImageShown ? 6 : 12}> <Grid item xs={hasImageShown ? 6 : 12}>
{loading ? <LinearProgress/> : {loading ? (
<LinearProgress />
) : (
<> <>
<NumberShowBox <NumberShowBox
showNumber={(detailsList?.data?.approved_amount) / 1000000} showNumber={detailsList?.data?.approved_amount / 1000000}
headerTitle={t("ConfirmDialog.approved_amount_title")} headerTitle={t("ConfirmDialog.approved_amount_title")}
unitTitle={t("ConfirmDialog.unit")} unitTitle={t("ConfirmDialog.unit")}
/> />
<NumberShowBox <NumberShowBox
showNumber={(detailsList?.data?.facility_bank) / 1000000} showNumber={detailsList?.data?.facility_bank / 1000000}
headerTitle={t("ConfirmDialog.facility_bank_title")} headerTitle={t("ConfirmDialog.facility_bank_title")}
unitTitle={t("ConfirmDialog.unit")} unitTitle={t("ConfirmDialog.unit")}
/> />
<NumberShowBox <NumberShowBox
showNumber={(detailsList?.data?.facility_gov) / 1000000} showNumber={detailsList?.data?.facility_gov / 1000000}
headerTitle={t("ConfirmDialog.facility_gov_title")} headerTitle={t("ConfirmDialog.facility_gov_title")}
unitTitle={t("ConfirmDialog.unit")} unitTitle={t("ConfirmDialog.unit")}
/> />
<NumberShowBox <NumberShowBox
showNumber={(detailsList?.data?.facility_person) / 1000000} showNumber={detailsList?.data?.facility_person / 1000000}
headerTitle={t("ConfirmDialog.facility_person_title")} headerTitle={t("ConfirmDialog.facility_person_title")}
unitTitle={t("ConfirmDialog.unit")} unitTitle={t("ConfirmDialog.unit")}
/> />
@@ -211,15 +217,19 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog, handleSizeChangeCl
/> />
{renderCustomAccordions()} {renderCustomAccordions()}
</> </>
} )}
<Stack spacing={2}> <Stack spacing={2}>
<Stack> <Stack>
<TextField <TextField
name="description" name="description"
multiline multiline
rows={8} rows={8}
label={<> label={
<span>{t("ConfirmDialog.description")}</span><small>{t("ConfirmDialog.optional")}</small></>} <>
<span>{t("ConfirmDialog.description")}</span>
<small>{t("ConfirmDialog.optional")}</small>
</>
}
value={formik.values.description} value={formik.values.description}
onChange={handleDescriptionChange} onChange={handleDescriptionChange}
fullWidth fullWidth
@@ -228,7 +238,10 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog, handleSizeChangeCl
/> />
</Stack> </Stack>
<Stack> <Stack>
<Typography>{t("UploadSystem.upload_file")}{t("UploadSystem.optional")}</Typography> <Typography>
{t("UploadSystem.upload_file")}
{t("UploadSystem.optional")}
</Typography>
<UploadSystem <UploadSystem
selectedImage={selectedImage} selectedImage={selectedImage}
handleUploadChange={handleUploadChange} // Pass the updated function directly handleUploadChange={handleUploadChange} // Pass the updated function directly
@@ -242,43 +255,48 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog, handleSizeChangeCl
setShowAddIcon={setShowAddIcon} setShowAddIcon={setShowAddIcon}
showAddIcon={showAddIcon} showAddIcon={showAddIcon}
onBlur={() => formik.handleBlur("confirm_img")} onBlur={() => formik.handleBlur("confirm_img")}
error={ error={formik.touched.confirm_img && Boolean(formik.errors.confirm_img)}
formik.touched.confirm_img &&
Boolean(formik.errors.confirm_img)
}
/> />
<FormHelperText <FormHelperText error={Boolean(formik.errors.confirm_img)}>
error={Boolean(formik.errors.confirm_img)}
>
{formik.touched.confirm_img && formik.errors.confirm_img} {formik.touched.confirm_img && formik.errors.confirm_img}
</FormHelperText> </FormHelperText>
</Stack> </Stack>
</Stack> </Stack>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Stack sx={{ <Stack
display: hasImageShown ? 'flex' : 'none', sx={{
alignItems: 'center', display: hasImageShown ? "flex" : "none",
alignItems: "center",
gap: 0.5, gap: 0.5,
justifyContent: 'center' justifyContent: "center",
}}> }}
>
<ImageContent imageLink={imageLink} isSkeleton={isSkeleton} setIsSkeleton={setIsSkeleton} /> <ImageContent imageLink={imageLink} isSkeleton={isSkeleton} setIsSkeleton={setIsSkeleton} />
</Stack> </Stack>
</Grid> </Grid>
</Grid> </Grid>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ConfirmDialog.button-cancel")} {t("ConfirmDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.isValid}
>
{t("ConfirmDialog.button-confirm")} {t("ConfirmDialog.button-confirm")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
};
} export default ConfirmContent;
export default ConfirmContent

View File

@@ -2,15 +2,15 @@ import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import ConfirmContent from "./ConfirmContent"; import ConfirmContent from "./ConfirmContent";
import CallMadeIcon from '@mui/icons-material/CallMade'; import CallMadeIcon from "@mui/icons-material/CallMade";
const Confirm = ({ rowId, mutate }) => { const Confirm = ({ rowId, mutate }) => {
const t = useTranslations(); const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false); const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
const [dialogSize, setDialogSize] = useState('sm'); const [dialogSize, setDialogSize] = useState("sm");
useEffect(() => { useEffect(() => {
if (!openConfirmDialog) { if (!openConfirmDialog) {
setDialogSize('sm'); setDialogSize("sm");
} }
}, [openConfirmDialog]); }, [openConfirmDialog]);
@@ -23,19 +23,32 @@ const Confirm = ({rowId, mutate}) => {
<IconButton <IconButton
color="primary" color="primary"
onClick={() => { onClick={() => {
setOpenConfirmDialog(true) setOpenConfirmDialog(true);
}} }}
> >
<CallMadeIcon /> <CallMadeIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openConfirmDialog} <Dialog
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}> fullWidth
open={openConfirmDialog}
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}
>
<DialogTitle>{t("NavganProvinceManager.confirm")}</DialogTitle> <DialogTitle>{t("NavganProvinceManager.confirm")}</DialogTitle>
<ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} handleSizeChangeClick={handleSizeChangeClick}/> <ConfirmContent
mutate={mutate}
rowId={rowId}
setOpenConfirmDialog={setOpenConfirmDialog}
handleSizeChangeClick={handleSizeChangeClick}
/>
</Dialog> </Dialog>
</> </>
) );
};
}
export default Confirm; export default Confirm;

View File

@@ -1,7 +1,7 @@
import UploadSystem from "@/core/components/UploadSystem" import UploadSystem from "@/core/components/UploadSystem";
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, FormHelperText, Stack, TextField, Typography} from "@mui/material" import { Button, DialogActions, DialogContent, FormHelperText, Stack, TextField, Typography } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
@@ -14,17 +14,18 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const [fileName, setfileName] = useState(null); const [fileName, setfileName] = useState(null);
const [showAddIcon, setShowAddIcon] = useState(true); const [showAddIcon, setShowAddIcon] = useState(true);
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
description: Yup.string().required(t("RejectDialog.description_error")), description: Yup.string().required(t("RejectDialog.description_error")),
reject_img: Yup.mixed().notRequired(t("RejectDialog.choose_file")) reject_img: Yup.mixed()
.test('fileSize', `${t("NavganProvinceManager.upload_file_unit")}`, (value) => { .notRequired(t("RejectDialog.choose_file"))
.test("fileSize", `${t("NavganProvinceManager.upload_file_unit")}`, (value) => {
return !value || (value.size && value.size <= 5 * 1024 * 1024); return !value || (value.size && value.size <= 5 * 1024 * 1024);
}) })
.test('fileType', `${t("NavganProvinceManager.upload_file_format")}`, (value) => { .test("fileType", `${t("NavganProvinceManager.upload_file_format")}`, (value) => {
const allowedTypes = ['image/jpg', 'image/jpeg', 'image/png', 'application/pdf']; // Define your allowed file types const allowedTypes = ["image/jpg", "image/jpeg", "image/png", "application/pdf"]; // Define your allowed file types
return !value || (value.type && allowedTypes.includes(value.type)); return !value || (value.type && allowedTypes.includes(value.type));
}), }),
}); });
@@ -32,7 +33,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
description: "", description: "",
reject_img: null reject_img: null,
}, },
validationSchema, validationSchema,
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
@@ -42,22 +43,24 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
const attachments = [ const attachments = [
{ {
title: "فایل ضمیمه کارتابل بررسی وام های تبصره 18", title: "فایل ضمیمه کارتابل بررسی وام های تبصره 18",
file: values.reject_img file: values.reject_img,
} },
]; ];
attachments.forEach((attachment, index) => { attachments.forEach((attachment, index) => {
formData.append(`attachment[${index}][title]`, attachment.title); formData.append(`attachment[${index}][title]`, attachment.title);
formData.append(`attachment[${index}][file]`, attachment.file); formData.append(`attachment[${index}][file]`, attachment.file);
}); });
} }
requestServer(`${REJECT_NAVGAN_PROVINCE_MANAGER}/${rowId}`, 'post', { requestServer(`${REJECT_NAVGAN_PROVINCE_MANAGER}/${rowId}`, "post", {
data: formData, data: formData,
}).then((response) => { })
setOpenRejectDialog(false) .then((response) => {
mutate() setOpenRejectDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -77,7 +80,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
setfileName(fileName); setfileName(fileName);
formik.setFieldValue("reject_img", uploadedFile).then(() => { formik.setFieldValue("reject_img", uploadedFile).then(() => {
formik.setFieldTouched("reject_img", true); formik.setFieldTouched("reject_img", true);
}) });
setShowAddIcon(false); setShowAddIcon(false);
} }
}; };
@@ -95,9 +98,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
value={formik.values.description} value={formik.values.description}
onChange={handleDescriptionChange} onChange={handleDescriptionChange}
onBlur={formik.handleBlur("description")} onBlur={formik.handleBlur("description")}
error={ error={formik.touched.description && Boolean(formik.errors.description)}
formik.touched.description && Boolean(formik.errors.description)
}
helperText={formik.touched.description && formik.errors.description} helperText={formik.touched.description && formik.errors.description}
fullWidth fullWidth
variant="outlined" variant="outlined"
@@ -105,7 +106,10 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
/> />
</Stack> </Stack>
<Stack> <Stack>
<Typography>{t("UploadSystem.upload_file")}{t("UploadSystem.optional")}</Typography> <Typography>
{t("UploadSystem.upload_file")}
{t("UploadSystem.optional")}
</Typography>
<UploadSystem <UploadSystem
selectedImage={selectedImage} selectedImage={selectedImage}
handleUploadChange={handleUploadChange} // Pass the updated function directly handleUploadChange={handleUploadChange} // Pass the updated function directly
@@ -119,30 +123,34 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
setShowAddIcon={setShowAddIcon} setShowAddIcon={setShowAddIcon}
showAddIcon={showAddIcon} showAddIcon={showAddIcon}
onBlur={() => formik.handleBlur("reject_img")} onBlur={() => formik.handleBlur("reject_img")}
error={ error={formik.touched.reject_img && Boolean(formik.errors.reject_img)}
formik.touched.reject_img &&
Boolean(formik.errors.reject_img)
}
/> />
<FormHelperText <FormHelperText error={Boolean(formik.errors.reject_img)}>
error={Boolean(formik.errors.reject_img)}
>
{formik.touched.reject_img && formik.errors.reject_img} {formik.touched.reject_img && formik.errors.reject_img}
</FormHelperText> </FormHelperText>
</Stack> </Stack>
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenRejectDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenRejectDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("RejectDialog.button-cancel")} {t("RejectDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("RejectDialog.button-reject")} {t("RejectDialog.button-reject")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
} };
export default RejectContent export default RejectContent;

View File

@@ -1,4 +1,4 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material" import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
import RejectContent from "./RejectContent"; import RejectContent from "./RejectContent";
@@ -14,12 +14,19 @@ const Reject = ({rowId, mutate}) => {
<ThumbDownIcon /> <ThumbDownIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openRejectDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openRejectDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle> <DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} /> <RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} />
</Dialog> </Dialog>
</> </>
) );
} };
export default Reject export default Reject;

View File

@@ -1,6 +1,6 @@
import useNotification from "@/lib/app/hooks/useNotification"; import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField} from "@mui/material" import { Button, DialogActions, DialogContent, Stack, TextField } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import * as Yup from "yup"; import * as Yup from "yup";
@@ -8,8 +8,8 @@ import {REFER_NAVGAN_PROVINCE_MANAGER} from "@/core/data/apiRoutes";
const RevertContent = ({ rowId, mutate, setOpenRevertDialog }) => { const RevertContent = ({ rowId, mutate, setOpenRevertDialog }) => {
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest({auth: true}) const requestServer = useRequest({ auth: true });
const {update_notification} = useNotification() const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
description: Yup.string().required(t("RevertDialog.description_error")), description: Yup.string().required(t("RevertDialog.description_error")),
@@ -21,16 +21,18 @@ const RevertContent = ({rowId, mutate, setOpenRevertDialog}) => {
}, },
validationSchema, validationSchema,
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
requestServer(`${REFER_NAVGAN_PROVINCE_MANAGER}/${rowId}`, 'post', { requestServer(`${REFER_NAVGAN_PROVINCE_MANAGER}/${rowId}`, "post", {
data: { data: {
expert_description: values.description expert_description: values.description,
}, },
}).then(() => { })
setOpenRevertDialog(false) .then(() => {
mutate() setOpenRevertDialog(false);
update_notification() mutate();
}).catch(() => { update_notification();
}).finally(() => { })
.catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -53,9 +55,7 @@ const RevertContent = ({rowId, mutate, setOpenRevertDialog}) => {
value={formik.values.description} value={formik.values.description}
onChange={handleDescriptionChange} onChange={handleDescriptionChange}
onBlur={formik.handleBlur("description")} onBlur={formik.handleBlur("description")}
error={ error={formik.touched.description && Boolean(formik.errors.description)}
formik.touched.description && Boolean(formik.errors.description)
}
helperText={formik.touched.description && formik.errors.description} helperText={formik.touched.description && formik.errors.description}
fullWidth fullWidth
variant="outlined" variant="outlined"
@@ -65,16 +65,25 @@ const RevertContent = ({rowId, mutate, setOpenRevertDialog}) => {
</Stack> </Stack>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setOpenRevertDialog(false)} variant="outlined" color="secondary" <Button
disabled={formik.isSubmitting} autoFocus> onClick={() => setOpenRevertDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("RevertDialog.button-cancel")} {t("RevertDialog.button-cancel")}
</Button> </Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary" <Button
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}> onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("RevertDialog.button-revert")} {t("RevertDialog.button-revert")}
</Button> </Button>
</DialogActions> </DialogActions>
</> </>
) );
} };
export default RevertContent export default RevertContent;

View File

@@ -1,7 +1,7 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material" import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useState } from "react";
import CallReceivedIcon from '@mui/icons-material/CallReceived'; import CallReceivedIcon from "@mui/icons-material/CallReceived";
import RevertContent from "@/components/dashboard/navgan-province-manager/Form/RevertForm/RevertContent"; import RevertContent from "@/components/dashboard/navgan-province-manager/Form/RevertForm/RevertContent";
const Revert = ({ rowId, mutate }) => { const Revert = ({ rowId, mutate }) => {
@@ -14,12 +14,19 @@ const Revert = ({rowId, mutate}) => {
<CallReceivedIcon /> <CallReceivedIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Dialog fullWidth open={openRevertDialog} <Dialog
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}> fullWidth
open={openRevertDialog}
PaperProps={{
sx: {
boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px",
},
}}
>
<DialogTitle>{t("NavganProvinceManager.revert")}</DialogTitle> <DialogTitle>{t("NavganProvinceManager.revert")}</DialogTitle>
<RevertContent mutate={mutate} rowId={rowId} setOpenRevertDialog={setOpenRevertDialog} /> <RevertContent mutate={mutate} rowId={rowId} setOpenRevertDialog={setOpenRevertDialog} />
</Dialog> </Dialog>
</> </>
) );
} };
export default Revert export default Revert;

View File

@@ -0,0 +1,397 @@
import { Chip, DialogContent, DialogTitle, Divider, Grid, Stack, Typography } from "@mui/material";
import { useTranslations } from "next-intl";
import moment from "jalali-moment";
const LegalTableContent = ({ rowId, row }) => {
const t = useTranslations();
return (
<>
<DialogTitle>{t("UserInfoDialog.user_info")}</DialogTitle>
<DialogContent>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.is_legal_person")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">{t("UserInfoDialog.legal_person")}</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">{row.original.id || t("UserInfoDialog.no_info")}</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_plan_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.project_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.activity_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.activity_category_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.first_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.first_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.last_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.last_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.father_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.father_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.gender")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.gender ? t("UserInfoDialog.female") : t("UserInfoDialog.male")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.national_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.national_id || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip
label={
row.original.national_serial_number
? t("UserInfoDialog.national_serial_number")
: t("UserInfoDialog.national_tracking_code")
}
sx={{ mr: 1 }}
/>
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.national_serial_number ||
row.original.national_tracking_code ||
t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.education_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.education_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.occupation_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.occupation_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.phone_number")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.phone_number || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.birthday")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.birthday
? moment(row.original.birthday).locale("fa").format("YYYY/MM/DD")
: t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.province_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.province_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.city_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.city_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.shenase_meli")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.shenase_meli || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.postal_code")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.postal_code || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.company_register_date")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.company_register_date
? moment(row.original.company_register_date).locale("fa").format("YYYY/MM/DD")
: t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.register_number")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.register_number || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.navgan_id || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.navgan_type || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.company_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.company_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.tel_number")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.telephone_number || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.vehicle_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.vehicle_type || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.investment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.investment_amount / 1000000) >= 1000
? t("UserInfoDialog.milyard", { value: (row.original.investment_amount / 1000000000) })
: t("UserInfoDialog.toman", { value: (row.original.investment_amount / 1000000) })
}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.requested_facilities")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.requested_facility_amount / 1000000) >= 1000
? t("UserInfoDialog.milyard", {value : (row.original.requested_facility_amount / 1000000000)})
:t("UserInfoDialog.toman", {value : (row.original.requested_facility_amount / 1000000)})
}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.applicant_payment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.person_share / 1000000) >= 1000
? t("UserInfoDialog.milyard", {value : (row.original.person_share / 1000000000)})
:t("UserInfoDialog.toman", {value : (row.original.person_share / 1000000)})
}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.user_committed_employment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.user_committed_employment || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.user_existing_employment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.user_existing_employment || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={12}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.plate")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Stack sx={{ border: 1, borderColor: "divider", borderRadius: 1 }} direction={"row"}>
<Stack
sx={{
borderRight: 1,
borderColor: "divider",
textAlign: "center",
width: "100%",
px: 1,
}}
>
{row.original.plate_number.split("-")[3] || t("UserInfoDialog.no_info")}
</Stack>
<Stack spacing={1} direction={"row"} sx={{ width: "100%" }}>
<Stack
sx={{
textAlign: "center",
width: "100%",
pl: 1,
}}
>
{row.original.plate_number.split("-")[2] || t("UserInfoDialog.no_info")}
</Stack>
<Stack
sx={{
textAlign: "center",
width: "100%",
pl: 1,
}}
>
{row.original.plate_number.split("-")[1] || t("UserInfoDialog.no_info")}
</Stack>
<Stack
sx={{
textAlign: "center",
width: "100%",
px: 1,
}}
>
{row.original.plate_number.split("-")[0] || t("UserInfoDialog.no_info")}
</Stack>
</Stack>
</Stack>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={12}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.address")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.address || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
</DialogContent>
</>
);
};
export default LegalTableContent;

View File

@@ -0,0 +1,353 @@
import { Chip, DialogContent, DialogTitle, Divider, Grid, Stack, Typography } from "@mui/material";
import { useTranslations } from "next-intl";
import moment from "jalali-moment";
const RealTableContent = ({ rowId, row }) => {
const t = useTranslations();
return (
<>
<DialogTitle>{t("UserInfoDialog.user_info")}</DialogTitle>
<DialogContent>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.is_legal_person")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">{t("UserInfoDialog.real_person")}</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">{row.original.id || t("UserInfoDialog.no_info")}</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_plan_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.project_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.activity_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.activity_category_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.first_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.first_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.last_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.last_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.national_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.national_id || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip
label={
row.original.national_serial_number
? t("UserInfoDialog.national_serial_number")
: t("UserInfoDialog.national_tracking_code")
}
sx={{ mr: 1 }}
/>
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.national_serial_number ||
row.original.national_tracking_code ||
t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.education_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.education_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.occupation_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.occupation_title || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.phone_number")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.phone_number || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.tel_number")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.telephone_number || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.birthday")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.birthday
? moment(row.original.birthday).locale("fa").format("YYYY/MM/DD")
: t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.postal_code")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.postal_code || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.father_name")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.father_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.gender")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.gender ? t("UserInfoDialog.female") : t("UserInfoDialog.male")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.province_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.province_name || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.city_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">{row.original.city_name}</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_id")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.navgan_id || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.navgan_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.navgan_type || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.user_committed_employment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.user_committed_employment || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.user_existing_employment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.user_existing_employment || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.vehicle_type")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.vehicle_type || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.investment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.investment_amount / 1000000) >= 1000
? t("UserInfoDialog.milyard", { value: (row.original.investment_amount / 1000000000) })
: t("UserInfoDialog.toman", { value: (row.original.investment_amount / 1000000) })
}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.requested_facilities")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.requested_facility_amount / 1000000) >= 1000
? t("UserInfoDialog.milyard", {value : (row.original.requested_facility_amount / 1000000000)})
:t("UserInfoDialog.toman", {value : (row.original.requested_facility_amount / 1000000)})
}
</Typography>
</Stack>
</Grid>
<Grid item xs={12} sm={6}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.applicant_payment")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{
(row.original.person_share / 1000000) >= 1000
? t("UserInfoDialog.milyard", {value : (row.original.person_share / 1000000000)})
:t("UserInfoDialog.toman", {value : (row.original.person_share / 1000000)})
}
</Typography>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={12}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.plate")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Stack sx={{ border: 1, borderColor: "divider", borderRadius: 1 }} direction={"row"}>
<Stack
sx={{
borderRight: 1,
borderColor: "divider",
textAlign: "center",
width: "100%",
px: 1,
}}
>
{row.original.plate_number.split("-")[3] || t("UserInfoDialog.no_info")}
</Stack>
<Stack spacing={1} direction={"row"} sx={{ width: "100%" }}>
<Stack
sx={{
textAlign: "center",
width: "100%",
pl: 1,
}}
>
{row.original.plate_number.split("-")[2] || t("UserInfoDialog.no_info")}
</Stack>
<Stack
sx={{
textAlign: "center",
width: "100%",
pl: 1,
}}
>
{row.original.plate_number.split("-")[1] || t("UserInfoDialog.no_info")}
</Stack>
<Stack
sx={{
textAlign: "center",
width: "100%",
px: 1,
}}
>
{row.original.plate_number.split("-")[0] || t("UserInfoDialog.no_info")}
</Stack>
</Stack>
</Stack>
</Stack>
</Grid>
</Grid>
<Grid container spacing={2} sx={{ my: 2 }}>
<Grid item xs={12} sm={12}>
<Stack direction="row" alignItems="center" sx={{ width: "100%" }}>
<Chip label={t("UserInfoDialog.address")} sx={{ mr: 1 }} />
<Divider sx={{ flexGrow: 1, mx: 1 }} />
<Typography variant="body1">
{row.original.address || t("UserInfoDialog.no_info")}
</Typography>
</Stack>
</Grid>
</Grid>
</DialogContent>
</>
);
};
export default RealTableContent;

View File

@@ -0,0 +1,47 @@
import { Button, Dialog, DialogActions, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import ContactPageIcon from "@mui/icons-material/ContactPage";
import LegalTableContent from "./LegalTableContent";
import RealTableContent from "./RealTableContent";
const UserInfoForm = ({ rowId, row }) => {
const t = useTranslations();
const [openUserInfoDialog, setOpenUserInfoDialog] = useState(false);
return (
<>
<Tooltip title={t("UserInfoDialog.user_info_tooltip")}>
<IconButton
color="primary"
onClick={() => {
setOpenUserInfoDialog(true);
}}
>
<ContactPageIcon />
</IconButton>
</Tooltip>
<Dialog
open={openUserInfoDialog}
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",
},
}}
fullWidth
maxWidth="lg"
>
{row.original.is_legal_person === 1 ? (
<LegalTableContent rowId={rowId} row={row} />
) : (
<RealTableContent rowId={rowId} row={row} />
)}
<DialogActions>
<Button onClick={() => setOpenUserInfoDialog(false)} variant="outlined" color="secondary" autoFocus>
{t("UserInfoDialog.button-cancel")}
</Button>
</DialogActions>
</Dialog>
</>
);
};
export default UserInfoForm;

View File

@@ -2,23 +2,15 @@ import {Box} from "@mui/material";
import Confirm from "./Form/ConfirmForm"; import Confirm from "./Form/ConfirmForm";
import Reject from "./Form/RejectForm"; import Reject from "./Form/RejectForm";
import Revert from "@/components/dashboard/navgan-province-manager/Form/RevertForm"; import Revert from "@/components/dashboard/navgan-province-manager/Form/RevertForm";
import UserInfoForm from "./Form/UserInfoForm";
const TableRow = ({ row, mutate }) => { const TableRow = ({ row, mutate }) => {
return ( return (
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}> <Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
<Confirm <UserInfoForm rowId={row.getValue("id")} row={row} />
rowId={row.getValue("id")} <Confirm rowId={row.getValue("id")} mutate={mutate} />
mutate={mutate} <Revert rowId={row.getValue("id")} mutate={mutate} />
/> <Reject rowId={row.getValue("id")} mutate={mutate} />
<Revert
rowId={row.getValue("id")}
mutate={mutate}
/>
<Reject
rowId={row.getValue("id")}
mutate={mutate}
/>
</Box> </Box>
); );
}; };

View File

@@ -2,12 +2,11 @@ import {Stack} from "@mui/material";
import PrintExcel from "@/components/dashboard/navgan-province-manager/Buttons/printExcel"; import PrintExcel from "@/components/dashboard/navgan-province-manager/Buttons/printExcel";
const TableToolbar = ({ table }) => { const TableToolbar = ({ table }) => {
return ( return (
<Stack direction={"row"} spacing={2}> <Stack direction={"row"} spacing={2}>
<PrintExcel table={table} /> <PrintExcel table={table} />
</Stack> </Stack>
) );
} };
export default TableToolbar export default TableToolbar;

View File

@@ -20,17 +20,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.is_legal_person, accessorFn: (row) => row.is_legal_person,
@@ -41,8 +32,11 @@ function DashboardNavganProvinceManagerComponent() {
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: ["equals"], columnFilterModeOptions: ["equals"],
Cell: ({ renderedCellValue }) => ( Cell: ({ renderedCellValue }) => (
<Typography <Typography variant="body2">
variant="body2">{renderedCellValue === 1 ? `${t("NavganProvinceManager.hoghoghi")}` : `${t("NavganProvinceManager.haghighi")}`}</Typography> {renderedCellValue === 1
? `${t("NavganProvinceManager.hoghoghi")}`
: `${t("NavganProvinceManager.haghighi")}`}
</Typography>
), ),
}, },
{ {
@@ -52,17 +46,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.name, accessorFn: (row) => row.name,
@@ -72,9 +57,7 @@ function DashboardNavganProvinceManagerComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.national_id, accessorFn: (row) => row.national_id,
@@ -83,17 +66,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.shenase_meli, accessorFn: (row) => row.shenase_meli,
@@ -102,17 +76,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.province_name, accessorFn: (row) => row.province_name,
@@ -122,9 +87,7 @@ function DashboardNavganProvinceManagerComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.city_name, accessorFn: (row) => row.city_name,
@@ -134,13 +97,10 @@ function DashboardNavganProvinceManagerComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "created_at", id: "created_at",
header: t("NavganProvinceManager.created_at"), header: t("NavganProvinceManager.created_at"),
enableColumnFilter: true, enableColumnFilter: true,
@@ -152,9 +112,7 @@ function DashboardNavganProvinceManagerComponent() {
}, },
Header: ({ column }) => <>{column.columnDef.header}</>, Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => { Filter: ({ column }) => {
return ( return <MuiDatePicker column={column} />;
<MuiDatePicker column={column}/>
);
}, },
}, },
{ {
@@ -164,17 +122,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.statement_count, accessorFn: (row) => row.statement_count,
@@ -183,12 +132,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.vehicle_type, accessorFn: (row) => row.vehicle_type,
@@ -198,9 +143,7 @@ function DashboardNavganProvinceManagerComponent() {
datatype: "text", datatype: "text",
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.plate_number, accessorFn: (row) => row.plate_number,
@@ -211,23 +154,35 @@ function DashboardNavganProvinceManagerComponent() {
filterFn: "contains", filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"], columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({ renderedCellValue }) => ( Cell: ({ renderedCellValue }) => (
<Stack sx={{border: 1, borderColor: "divider", borderRadius: 1}} direction={'row'}> <Stack sx={{ border: 1, borderColor: "divider", borderRadius: 1 }} direction={"row"}>
<Stack sx={{borderRight: 1, borderColor: "divider", textAlign: 'center', width: "40%"}}> <Stack sx={{ borderRight: 1, borderColor: "divider", textAlign: "center", width: "40%" }}>
{renderedCellValue.split('-')[3]} {renderedCellValue.split("-")[3]}
</Stack> </Stack>
<Stack direction={'row'} sx={{width: "100%", px: 0.5}}> <Stack direction={"row"} sx={{ width: "100%", px: 0.5 }}>
<Stack sx={{ <Stack
sx={{
textAlign: "center", textAlign: "center",
width: "100%" width: "100%",
}}>{renderedCellValue.split('-')[2]}</Stack> }}
<Stack sx={{ >
{renderedCellValue.split("-")[2]}
</Stack>
<Stack
sx={{
textAlign: "center", textAlign: "center",
width: "100%" width: "100%",
}}>{renderedCellValue.split('-')[1]}</Stack> }}
<Stack sx={{ >
{renderedCellValue.split("-")[1]}
</Stack>
<Stack
sx={{
textAlign: "center", textAlign: "center",
width: "100%" width: "100%",
}}>{renderedCellValue.split('-')[0]}</Stack> }}
>
{renderedCellValue.split("-")[0]}
</Stack>
</Stack> </Stack>
</Stack> </Stack>
), ),
@@ -239,17 +194,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.facility_bank, accessorFn: (row) => row.facility_bank,
@@ -258,17 +204,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.facility_gov, accessorFn: (row) => row.facility_gov,
@@ -277,17 +214,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.facility_person, accessorFn: (row) => row.facility_person,
@@ -296,17 +224,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue / 1000000}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue / 1000000}</Typography>
),
}, },
{ {
accessorFn: (row) => row.physical_progress, accessorFn: (row) => row.physical_progress,
@@ -315,17 +234,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.repayment_period, accessorFn: (row) => row.repayment_period,
@@ -334,17 +244,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.sakht_period, accessorFn: (row) => row.sakht_period,
@@ -353,12 +254,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals"],
"equals" Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.tanafos_period, accessorFn: (row) => row.tanafos_period,
@@ -367,12 +264,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals"],
"equals" Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.committed_employment, accessorFn: (row) => row.committed_employment,
@@ -381,17 +274,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.existing_employment, accessorFn: (row) => row.existing_employment,
@@ -400,17 +284,8 @@ function DashboardNavganProvinceManagerComponent() {
enableColumnFilter: true, enableColumnFilter: true,
datatype: "numeric", datatype: "numeric",
filterFn: "equals", filterFn: "equals",
columnFilterModeOptions: [ columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
"equals", Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
{ {
accessorFn: (row) => row.state_name, accessorFn: (row) => row.state_name,
@@ -418,9 +293,7 @@ function DashboardNavganProvinceManagerComponent() {
header: t("NavganProvinceManager.state_name"), header: t("NavganProvinceManager.state_name"),
enableColumnFilter: false, enableColumnFilter: false,
datatype: "numeric", datatype: "numeric",
Cell: ({renderedCellValue}) => ( Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
<Typography variant="body2">{renderedCellValue}</Typography>
),
}, },
], ],
[] []
@@ -435,12 +308,15 @@ function DashboardNavganProvinceManagerComponent() {
enableCustomToolbar={true} enableCustomToolbar={true}
CustomToolbar={TableToolbar} CustomToolbar={TableToolbar}
enableLastUpdate={true} enableLastUpdate={true}
sorting={[{ sorting={[
id: 'statement_count', desc: true {
}]} id: "statement_count",
desc: true,
},
]}
enablePinning={true} enablePinning={true}
enableDensityToggle={false} enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large) initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true} enableColumnFilters={true}
enableHiding={true} enableHiding={true}
enableFullScreenToggle={false} enableFullScreenToggle={false}

View File

@@ -6,11 +6,11 @@ import {
Button, Button,
CircularProgress, CircularProgress,
Stack, Stack,
Typography Typography,
} from "@mui/material"; } from "@mui/material";
import FileUploadIcon from '@mui/icons-material/FileUpload'; import FileUploadIcon from "@mui/icons-material/FileUpload";
import AssignmentIcon from '@mui/icons-material/Assignment'; import AssignmentIcon from "@mui/icons-material/Assignment";
import BackupIcon from '@mui/icons-material/Backup'; import BackupIcon from "@mui/icons-material/Backup";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import ProvinceFilter from "@/components/dashboard/old-reports/Filter/ProvinceFilter"; import ProvinceFilter from "@/components/dashboard/old-reports/Filter/ProvinceFilter";
import YearFilter from "@/components/dashboard/old-reports/Filter/YearFilter"; import YearFilter from "@/components/dashboard/old-reports/Filter/YearFilter";
@@ -18,16 +18,16 @@ import {useState} from "react";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { GET_EXPORT } from "@/core/data/apiRoutes"; import { GET_EXPORT } from "@/core/data/apiRoutes";
import moment from "jalali-moment"; import moment from "jalali-moment";
import FileSaver from 'file-saver'; import FileSaver from "file-saver";
import useRequest from "@/lib/app/hooks/useRequest"; import useRequest from "@/lib/app/hooks/useRequest";
import { periodOfYear } from "@/core/utils/yearPeriodFinder"; import { periodOfYear } from "@/core/utils/yearPeriodFinder";
const ExcelExport = () => { const ExcelExport = () => {
const t = useTranslations(); const t = useTranslations();
const requestServer = useRequest() const requestServer = useRequest();
const filterItem = [ const filterItem = [
{ type: "province", type_fa: "استان", multiple: false }, { type: "province", type_fa: "استان", multiple: false },
{type: "year", type_fa: "سال", multiple: false} { type: "year", type_fa: "سال", multiple: false },
]; ];
const filter_by_province = filterItem.find((item) => item.type === "province"); const filter_by_province = filterItem.find((item) => item.type === "province");
const filter_by_year = filterItem.find((item) => item.type === "year"); const filter_by_year = filterItem.find((item) => item.type === "year");
@@ -37,14 +37,15 @@ const ExcelExport = () => {
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
...(filter_by_year && { ...(filter_by_year && {
date: filter_by_year.multiple ? [] : `${moment().format('jYYYY')}` date: filter_by_year.multiple ? [] : `${moment().format("jYYYY")}`,
}), }),
...(filter_by_province && { ...(filter_by_province && {
province_id: filter_by_province.multiple ? [] : "" province_id: filter_by_province.multiple ? [] : "",
}), }),
from_date: periodOfYear(moment().format('jYYYY')).from, from_date: periodOfYear(moment().format("jYYYY")).from,
to_date: periodOfYear(moment().format('jYYYY')).to to_date: periodOfYear(moment().format("jYYYY")).to,
}, onSubmit: (values, {setSubmitting}) => { },
onSubmit: (values, { setSubmitting }) => {
const province = values.province_id; const province = values.province_id;
const fields = [ const fields = [
values.from_date ? { key: "from_date", value: values.from_date } : null, values.from_date ? { key: "from_date", value: values.from_date } : null,
@@ -55,23 +56,22 @@ const ExcelExport = () => {
: [] : []
: province : province
? [{ key: "province_id", value: province }] ? [{ key: "province_id", value: province }]
: [] : []),
),
].filter(Boolean); ].filter(Boolean);
const queryString = fields.length !== 0 const queryString =
? `?${fields.map((option) => `${option.key}=${option.value}`).join('&')}` fields.length !== 0 ? `?${fields.map((option) => `${option.key}=${option.value}`).join("&")}` : "";
: ''; setSubmitting(true);
setSubmitting(true) requestServer(`${GET_EXPORT}${queryString}`, "GET", {
requestServer(`${GET_EXPORT}${queryString}`, 'GET', {
auth: true, auth: true,
notification: false, notification: false,
requestOptions: {responseType: 'blob'} requestOptions: { responseType: "blob" },
}) })
.then((response) => { .then((response) => {
const filename = `گزارش درخواست های وام ناوگان تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`; const filename = `گزارش درخواست های وام ناوگان تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename); FileSaver.saveAs(response.data, filename);
}).catch(() => { })
}).finally(() => { .catch(() => {})
.finally(() => {
setSubmitting(false); setSubmitting(false);
}); });
}, },
@@ -79,13 +79,16 @@ const ExcelExport = () => {
return ( return (
<Stack sx={{ width: "95%", mx: "auto" }}> <Stack sx={{ width: "95%", mx: "auto" }}>
<Accordion elevation={0} sx={{ <Accordion
elevation={0}
sx={{
width: "100%", width: "100%",
mb: 2, mb: 2,
borderBottom: 2, borderBottom: 2,
borderBottomColor: "divider", borderBottomColor: "divider",
backgroundColor: "#f1f1f1" backgroundColor: "#f1f1f1",
}}> }}
>
<AccordionSummary> <AccordionSummary>
<Box sx={{ width: "100%", display: "flex", alignItems: "center", justifyContent: "space-between" }}> <Box sx={{ width: "100%", display: "flex", alignItems: "center", justifyContent: "space-between" }}>
<Box sx={{ display: "flex", alignItems: "center", gap: 0.5 }}> <Box sx={{ display: "flex", alignItems: "center", gap: 0.5 }}>
@@ -104,24 +107,37 @@ const ExcelExport = () => {
justifyContent: "space-between", justifyContent: "space-between",
alignItems: "center", alignItems: "center",
mx: "auto", mx: "auto",
}}> }}
<Stack sx={{flexDirection: {xs: "column", sm: "row"}, alignItems: "center", flexWrap: 'wrap'}}> >
{filter_by_province ? <Stack sx={{ flexDirection: { xs: "column", sm: "row" }, alignItems: "center", flexWrap: "wrap" }}>
<ProvinceFilter formik={formik} multiple={filter_by_province.multiple} {filter_by_province ? (
setFilteredText={setFilteredText}/> : "" <ProvinceFilter
} formik={formik}
{filter_by_year ? multiple={filter_by_province.multiple}
<YearFilter formik={formik} multiple={filter_by_year.multiple} setFilteredText={setFilteredText}
setFilteredText={setFilteredText}/> : "" />
} ) : (
""
)}
{filter_by_year ? (
<YearFilter
formik={formik}
multiple={filter_by_year.multiple}
setFilteredText={setFilteredText}
/>
) : (
""
)}
</Stack> </Stack>
<Stack> <Stack>
<Button onClick={formik.handleSubmit} variant="contained" <Button
onClick={formik.handleSubmit}
variant="contained"
disabled={formik.isSubmitting} disabled={formik.isSubmitting}
sx={{ backgroundColor: "success.main" }} sx={{ backgroundColor: "success.main" }}
startIcon={formik.isSubmitting ? startIcon={
<CircularProgress size={20} color="inherit"/> : formik.isSubmitting ? <CircularProgress size={20} color="inherit" /> : <BackupIcon />
<BackupIcon/>} }
> >
{t("filters.export")} {t("filters.export")}
</Button> </Button>
@@ -129,7 +145,7 @@ const ExcelExport = () => {
</AccordionDetails> </AccordionDetails>
</Accordion> </Accordion>
</Stack> </Stack>
) );
}; };
export default ExcelExport; export default ExcelExport;

View File

@@ -7,45 +7,46 @@ import {
MenuItem, MenuItem,
OutlinedInput, OutlinedInput,
Select, Select,
Typography Typography,
} from "@mui/material"; } from "@mui/material";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import useProvince from "@/lib/app/hooks/useProvince"; import useProvince from "@/lib/app/hooks/useProvince";
import ClearIcon from '@mui/icons-material/Clear'; import ClearIcon from "@mui/icons-material/Clear";
const provinceList = [ const provinceList = [
{ name: "قزوین", id: 1 }, { name: "قزوین", id: 1 },
{ name: "تبریز", id: 2 }, { name: "تبریز", id: 2 },
{name: "مشهد", id: 3} { name: "مشهد", id: 3 },
] ];
const ProvinceFilter = ({ formik, multiple, setFilteredText }) => { const ProvinceFilter = ({ formik, multiple, setFilteredText }) => {
const { errorProvinceList, isLoadingProvinceList, provinceList } = useProvince(); const { errorProvinceList, isLoadingProvinceList, provinceList } = useProvince();
const t = useTranslations(); const t = useTranslations();
const provinceChange = (event) => { const provinceChange = (event) => {
const {target: {value}} = event; const {
target: { value },
} = event;
formik.handleChange(event); formik.handleChange(event);
formik.setFieldValue('province_id', value); formik.setFieldValue("province_id", value);
if (Array.isArray(value)) { if (Array.isArray(value)) {
const province_names = [] const province_names = [];
value.map((item) => { value.map((item) => {
province_names.push(provinceList.find(province => province.id === item).name) province_names.push(provinceList.find((province) => province.id === item).name);
}) });
setFilteredText(prevState => ({ setFilteredText((prevState) => ({
...prevState, ...prevState,
province: province_names.length !== 0 ? `| ${t("filters.provinces")}: ${province_names.join(' , ')}` : "" province:
province_names.length !== 0 ? `| ${t("filters.provinces")}: ${province_names.join(" , ")}` : "",
})); }));
} else { } else {
const selectedProvince = provinceList.find(province => province.id === value); const selectedProvince = provinceList.find((province) => province.id === value);
setFilteredText(prevState => ({ setFilteredText((prevState) => ({
...prevState, ...prevState,
province: `| ${t("filters.province")}: ${selectedProvince.name}` province: `| ${t("filters.province")}: ${selectedProvince.name}`,
})); }));
} }
}; };
const needAdorment = multiple const needAdorment = multiple ? formik.values.province_id.length === 0 : formik.values.province_id === "";
? formik.values.province_id.length === 0 :
formik.values.province_id === "";
return ( return (
<FormControl sx={{ width: 300, mx: 1, my: { xs: 1, lg: 0 } }}> <FormControl sx={{ width: 300, mx: 1, my: { xs: 1, lg: 0 } }}>
<InputLabel size="small">{t("filters.choose_province")}</InputLabel> <InputLabel size="small">{t("filters.choose_province")}</InputLabel>
@@ -59,43 +60,51 @@ const ProvinceFilter = ({formik, multiple, setFilteredText}) => {
onBlur={formik.handleBlur("province_id")} onBlur={formik.handleBlur("province_id")}
input={<OutlinedInput label={t("filters.choose_province")} />} input={<OutlinedInput label={t("filters.choose_province")} />}
disabled={isLoadingProvinceList || errorProvinceList} disabled={isLoadingProvinceList || errorProvinceList}
renderValue={multiple ? (selected) => ( renderValue={
<Box sx={{ multiple
display: 'flex', gap: 0.7, overflow: "hidden", ? (selected) => (
width: '100%', pr: 4 <Box
}}> sx={{
display: "flex",
gap: 0.7,
overflow: "hidden",
width: "100%",
pr: 4,
}}
>
{selected.map((value) => { {selected.map((value) => {
const selectedProvince = provinceList.find(province => province.id === value); const selectedProvince = provinceList.find((province) => province.id === value);
return ( return (
<Typography key={value} variant="button"> <Typography key={value} variant="button">
{selectedProvince ? selectedProvince.name : ''} {selectedProvince ? selectedProvince.name : ""}
</Typography> </Typography>
); );
})} })}
</Box> </Box>
) : undefined} )
: undefined
}
endAdornment={ endAdornment={
!needAdorment ? !needAdorment ? (
<InputAdornment position="end" sx={{ mr: 2 }}> <InputAdornment position="end" sx={{ mr: 2 }}>
<IconButton <IconButton
onClick={() => multiple onClick={() =>
? formik.setFieldValue('province_id', []) multiple
: formik.setFieldValue('province_id', "") ? formik.setFieldValue("province_id", [])
: formik.setFieldValue("province_id", "")
} }
size="small"> size="small"
>
<ClearIcon /> <ClearIcon />
</IconButton> </IconButton>
</InputAdornment> : null </InputAdornment>
) : null
} }
> >
{isLoadingProvinceList ? ( {isLoadingProvinceList ? (
<MenuItem> <MenuItem>{t("filters.text_field_loading_provinces_list")}</MenuItem>
{t("filters.text_field_loading_provinces_list")}
</MenuItem>
) : errorProvinceList ? ( ) : errorProvinceList ? (
<MenuItem> <MenuItem>{t("filters.text_field_error_fetching_provinces")}</MenuItem>
{t("filters.text_field_error_fetching_provinces")}
</MenuItem>
) : ( ) : (
provinceList.map((item) => ( provinceList.map((item) => (
<MenuItem key={item.id} value={item.id}> <MenuItem key={item.id} value={item.id}>
@@ -105,7 +114,7 @@ const ProvinceFilter = ({formik, multiple, setFilteredText}) => {
)} )}
</Select> </Select>
</FormControl> </FormControl>
) );
}; };
export default ProvinceFilter; export default ProvinceFilter;

View File

@@ -3,27 +3,31 @@ import moment from "jalali-moment";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { periodOfYear } from "@/core/utils/yearPeriodFinder"; import { periodOfYear } from "@/core/utils/yearPeriodFinder";
const currentShamsiYear = moment().format('jYYYY'); const currentShamsiYear = moment().format("jYYYY");
const shamsiYearList = Array.from({length: currentShamsiYear - 1399}, (_, index) => (currentShamsiYear - index).toString()); const shamsiYearList = Array.from({ length: currentShamsiYear - 1399 }, (_, index) =>
(currentShamsiYear - index).toString()
);
const YearFilter = ({ formik, multiple, setFilteredText }) => { const YearFilter = ({ formik, multiple, setFilteredText }) => {
const t = useTranslations(); const t = useTranslations();
const yearChange = (event) => { const yearChange = (event) => {
const {target: {value}} = event; const {
target: { value },
} = event;
formik.handleChange(event); formik.handleChange(event);
formik.setFieldValue('date', value); formik.setFieldValue("date", value);
const { from, to } = periodOfYear(value); const { from, to } = periodOfYear(value);
formik.setFieldValue('from_date', from); formik.setFieldValue("from_date", from);
formik.setFieldValue('to_date', to); formik.setFieldValue("to_date", to);
if (Array.isArray(value)) { if (Array.isArray(value)) {
setFilteredText(prevState => ({ setFilteredText((prevState) => ({
...prevState, ...prevState,
year: `| ${t("filters.years")}: ${value.join(' , ')}` year: `| ${t("filters.years")}: ${value.join(" , ")}`,
})); }));
} else { } else {
setFilteredText(prevState => ({ setFilteredText((prevState) => ({
...prevState, ...prevState,
year: `| ${t("filters.year")}: ${value}` year: `| ${t("filters.year")}: ${value}`,
})); }));
} }
}; };
@@ -39,28 +43,30 @@ const YearFilter = ({formik, multiple, setFilteredText}) => {
onChange={yearChange} onChange={yearChange}
onBlur={formik.handleBlur("date")} onBlur={formik.handleBlur("date")}
input={<OutlinedInput label={t("filters.choose_year")} />} input={<OutlinedInput label={t("filters.choose_year")} />}
renderValue={multiple ? (selected) => ( renderValue={
<Box sx={{display: 'flex', flexWrap: 'wrap', gap: 0.5}}> multiple
? (selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => ( {selected.map((value) => (
<Chip key={value} label={value} <Chip
sx={{color: "#fff", backgroundColor: "primary.dark"}}/> key={value}
label={value}
sx={{ color: "#fff", backgroundColor: "primary.dark" }}
/>
))} ))}
</Box> </Box>
) : undefined} )
> : undefined
{ }
shamsiYearList.map((year) => (
<MenuItem
key={year}
value={year}
> >
{shamsiYearList.map((year) => (
<MenuItem key={year} value={year}>
{year} {year}
</MenuItem> </MenuItem>
)) ))}
}
</Select> </Select>
</FormControl> </FormControl>
) );
}; };
export default YearFilter; export default YearFilter;

View File

@@ -8,16 +8,16 @@ import {
IconButton, IconButton,
Stack, Stack,
Tooltip, Tooltip,
Typography Typography,
} from "@mui/material"; } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import ProvinceFilter from "../Filter/ProvinceFilter"; import ProvinceFilter from "../Filter/ProvinceFilter";
import YearFilter from "../Filter/YearFilter"; import YearFilter from "../Filter/YearFilter";
import FilterAltIcon from '@mui/icons-material/FilterAlt'; import FilterAltIcon from "@mui/icons-material/FilterAlt";
import EqualizerIcon from '@mui/icons-material/Equalizer'; import EqualizerIcon from "@mui/icons-material/Equalizer";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import TroubleshootIcon from '@mui/icons-material/Troubleshoot'; import TroubleshootIcon from "@mui/icons-material/Troubleshoot";
import CachedIcon from '@mui/icons-material/Cached'; import CachedIcon from "@mui/icons-material/Cached";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import moment from "jalali-moment"; import moment from "jalali-moment";
import { periodOfYear } from "@/core/utils/yearPeriodFinder"; import { periodOfYear } from "@/core/utils/yearPeriodFinder";
@@ -31,20 +31,20 @@ const Filter = ({title, filterItem, setFilterOption, isLoadingReportList, mutate
const [filteredText, setFilteredText] = useState({ province: "", year: "" }); const [filteredText, setFilteredText] = useState({ province: "", year: "" });
const [stepValue, setStepValue] = useState({ const [stepValue, setStepValue] = useState({
...(filter_by_year && { ...(filter_by_year && {
date: filter_by_year.multiple ? [] : `${moment().format('jYYYY')}` date: filter_by_year.multiple ? [] : `${moment().format("jYYYY")}`,
}), }),
...(filter_by_province && { ...(filter_by_province && {
province_id: filter_by_province.multiple ? [] : "" province_id: filter_by_province.multiple ? [] : "",
}), }),
from_date: periodOfYear(moment().format('jYYYY')).from, from_date: periodOfYear(moment().format("jYYYY")).from,
to_date: periodOfYear(moment().format('jYYYY')).to to_date: periodOfYear(moment().format("jYYYY")).to,
}) });
const formik = useFormik({ const formik = useFormik({
enableReinitialize: true, enableReinitialize: true,
initialValues: stepValue, onSubmit: (values, {setSubmitting}) => { initialValues: stepValue,
setStepValue(values) onSubmit: (values, { setSubmitting }) => {
setStepValue(values);
const province = values.province_id; const province = values.province_id;
const fields = [ const fields = [
values.from_date ? { key: "from_date", value: values.from_date } : null, values.from_date ? { key: "from_date", value: values.from_date } : null,
@@ -55,10 +55,9 @@ const Filter = ({title, filterItem, setFilterOption, isLoadingReportList, mutate
: [] : []
: province : province
? [{ key: "province_id", value: province }] ? [{ key: "province_id", value: province }]
: [] : []),
),
].filter(Boolean); ].filter(Boolean);
setFilterOption(fields) setFilterOption(fields);
}, },
}); });
@@ -73,20 +72,23 @@ const Filter = ({title, filterItem, setFilterOption, isLoadingReportList, mutate
: [] : []
: province : province
? [{ key: "province_id", value: province }] ? [{ key: "province_id", value: province }]
: [] : []),
),
].filter(Boolean); ].filter(Boolean);
setFilterOption(fields) setFilterOption(fields);
}, []); }, []);
return ( return (
<Accordion elevation={0} expanded={expanded} onChange={() => { <Accordion
}} sx={{ elevation={0}
expanded={expanded}
onChange={() => {}}
sx={{
mb: 2, mb: 2,
borderBottom: 2, borderBottom: 2,
borderBottomColor: "divider", borderBottomColor: "divider",
backgroundColor: "#f1f1f1", backgroundColor: "#f1f1f1",
}}> }}
>
<AccordionSummary sx={{ cursor: "unset !important" }}> <AccordionSummary sx={{ cursor: "unset !important" }}>
<Box sx={{ width: "100%", display: "flex", alignItems: "center", justifyContent: "space-between" }}> <Box sx={{ width: "100%", display: "flex", alignItems: "center", justifyContent: "space-between" }}>
<Box sx={{ display: "flex", alignItems: "center", gap: 0.5 }}> <Box sx={{ display: "flex", alignItems: "center", gap: 0.5 }}>
@@ -98,47 +100,61 @@ const Filter = ({title, filterItem, setFilterOption, isLoadingReportList, mutate
</Box> </Box>
<Box> <Box>
<Tooltip title={t("filters.update_again")} arrow> <Tooltip title={t("filters.update_again")} arrow>
<IconButton onClick={() => mutate()} <IconButton onClick={() => mutate()} size="small">
size="small">
<CachedIcon color="primary" /> <CachedIcon color="primary" />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Tooltip title={t("filters.filter_btn")} arrow> <Tooltip title={t("filters.filter_btn")} arrow>
<IconButton onClick={() => setExpanded((prevExpanded) => !prevExpanded)} <IconButton onClick={() => setExpanded((prevExpanded) => !prevExpanded)} size="small">
size="small">
<FilterAltIcon color="primary" /> <FilterAltIcon color="primary" />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
</Box> </Box>
</Box> </Box>
</AccordionSummary> </AccordionSummary>
<AccordionDetails sx={{ <AccordionDetails
sx={{
display: "flex", display: "flex",
flexDirection: { xs: "column", sm: "row" }, flexDirection: { xs: "column", sm: "row" },
justifyContent: "space-between", justifyContent: "space-between",
alignItems: "center" alignItems: "center",
}}> }}
<Stack sx={{flexDirection: {xs: "column", sm: "row"}, alignItems: "center", flexWrap: 'wrap'}}> >
{filter_by_province ? <Stack sx={{ flexDirection: { xs: "column", sm: "row" }, alignItems: "center", flexWrap: "wrap" }}>
<ProvinceFilter formik={formik} multiple={filter_by_province.multiple} {filter_by_province ? (
setFilteredText={setFilteredText}/> : "" <ProvinceFilter
} formik={formik}
{filter_by_year ? multiple={filter_by_province.multiple}
<YearFilter formik={formik} multiple={filter_by_year.multiple} setFilteredText={setFilteredText}
setFilteredText={setFilteredText}/> : "" />
} ) : (
""
)}
{filter_by_year ? (
<YearFilter
formik={formik}
multiple={filter_by_year.multiple}
setFilteredText={setFilteredText}
/>
) : (
""
)}
</Stack> </Stack>
<Stack> <Stack>
<Button onClick={formik.handleSubmit} variant="contained" <Button
onClick={formik.handleSubmit}
variant="contained"
disabled={isLoadingReportList || !formik.dirty} disabled={isLoadingReportList || !formik.dirty}
startIcon={isLoadingReportList ? startIcon={
<CircularProgress size={20} color="inherit"/> : isLoadingReportList ? <CircularProgress size={20} color="inherit" /> : <TroubleshootIcon />
<TroubleshootIcon/>} }
>{t("filters.filter")}</Button> >
{t("filters.filter")}
</Button>
</Stack> </Stack>
</AccordionDetails> </AccordionDetails>
</Accordion> </Accordion>
) );
}; };
export default Filter; export default Filter;

View File

@@ -12,36 +12,34 @@ const RadialBarChart = ({data}) => {
endAngle: 90, endAngle: 90,
track: { track: {
background: "#e7e7e7", background: "#e7e7e7",
strokeWidth: '90%', strokeWidth: "90%",
margin: 5, // margin is in pixels margin: 5, // margin is in pixels
dropShadow: { dropShadow: {
enabled: true, enabled: true,
top: 2, top: 2,
left: 0, left: 0,
color: '#999', color: "#999",
opacity: 1, opacity: 1,
blur: 2 blur: 2,
} },
}, },
dataLabels: { dataLabels: {
name: { name: {
show: false show: false,
}, },
value: { value: {
offsetY: -2, offsetY: -2,
fontSize: '22px' fontSize: "22px",
} },
} },
} },
}, },
fill: { fill: {
colors: calculateGradientColor(data) colors: calculateGradientColor(data),
}, },
}; };
const series = [data] const series = [data];
return ( return <Chart chartId="LoanProgressBar" type="radialBar" specialOption={specialOption} series={series} />;
<Chart chartId="LoanProgressBar" type="radialBar" specialOption={specialOption} series={series}/>
)
}; };
export default RadialBarChart; export default RadialBarChart;

View File

@@ -12,35 +12,33 @@ const RadialBarSemiCircularChart = ({data, label}) => {
endAngle: 110, endAngle: 110,
track: { track: {
background: "#e7e7e7", background: "#e7e7e7",
strokeWidth: '80%', strokeWidth: "80%",
}, },
dataLabels: { dataLabels: {
name: { name: {
fontSize: '20px', fontSize: "20px",
offsetY: 110, offsetY: 110,
color: "#8c8c8c" color: "#8c8c8c",
}, },
value: { value: {
offsetY: 50, offsetY: 50,
fontSize: '50px', fontSize: "50px",
fontWeight: 500, fontWeight: 500,
color: "#8c8c8c", color: "#8c8c8c",
formatter: function (val) { formatter: function (val) {
return val + "%"; return val + "%";
} },
} },
} },
} },
}, },
fill: { fill: {
colors: calculateGradientColor(data) colors: calculateGradientColor(data),
}, },
labels: [label], labels: [label],
}; };
const series = [data] const series = [data];
return ( return <Chart chartId="LoanProgressBar" type="radialBar" specialOption={specialOption} series={series} />;
<Chart chartId="LoanProgressBar" type="radialBar" specialOption={specialOption} series={series}/>
)
}; };
export default RadialBarSemiCircularChart; export default RadialBarSemiCircularChart;

View File

@@ -14,38 +14,36 @@ const RadialBarStrokedChart = ({data, label}) => {
endAngle: 110, endAngle: 110,
track: { track: {
background: "#e7e7e7", background: "#e7e7e7",
strokeWidth: '80%', strokeWidth: "80%",
}, },
dataLabels: { dataLabels: {
name: { name: {
fontSize: '20px', fontSize: "20px",
offsetY: 110, offsetY: 110,
color: "#8c8c8c" color: "#8c8c8c",
}, },
value: { value: {
offsetY: 50, offsetY: 50,
fontSize: '50px', fontSize: "50px",
fontWeight: 500, fontWeight: 500,
color: "#8c8c8c", color: "#8c8c8c",
formatter: function (val) { formatter: function (val) {
return val + "%"; return val + "%";
} },
} },
} },
} },
}, },
stroke: { stroke: {
dashArray: 4 dashArray: 4,
}, },
fill: { fill: {
colors: calculateGradientColor(data) colors: calculateGradientColor(data),
}, },
labels: [label], labels: [label],
}; };
const series = [data] const series = [data];
return ( return <Chart chartId="LoanProgressBar" type="radialBar" specialOption={specialOption} series={series} />;
<Chart chartId="LoanProgressBar" type="radialBar" specialOption={specialOption} series={series}/>
)
}; };
export default RadialBarStrokedChart; export default RadialBarStrokedChart;

View File

@@ -3,7 +3,6 @@ import {useTranslations} from "next-intl";
import RadialBarSemiCircularChart from "@/components/dashboard/old-reports/LoanDetails/RadialBarSemiCircularChart"; import RadialBarSemiCircularChart from "@/components/dashboard/old-reports/LoanDetails/RadialBarSemiCircularChart";
import RadialBarStrokedChart from "@/components/dashboard/old-reports/LoanDetails/RadialBarStrokedChart"; import RadialBarStrokedChart from "@/components/dashboard/old-reports/LoanDetails/RadialBarStrokedChart";
const LoanDetails = () => { const LoanDetails = () => {
const t = useTranslations(); const t = useTranslations();
return ( return (
@@ -31,7 +30,7 @@ const LoanDetails = () => {
</Grid> </Grid>
</Grid> </Grid>
</Paper> </Paper>
) );
}; };
export default LoanDetails; export default LoanDetails;

View File

@@ -2,10 +2,9 @@ import Chart from "@/core/components/Chart";
import { useTheme } from "@mui/material/styles"; import { useTheme } from "@mui/material/styles";
import { useMediaQuery } from "@mui/material"; import { useMediaQuery } from "@mui/material";
const Pie = ({ data }) => { const Pie = ({ data }) => {
const theme = useTheme(); const theme = useTheme();
const upperMd = useMediaQuery((theme.breakpoints.up("md"))) const upperMd = useMediaQuery(theme.breakpoints.up("md"));
const specialOption = { const specialOption = {
title: { title: {
text: undefined, text: undefined,
@@ -17,18 +16,16 @@ const Pie = ({data}) => {
dataLabels: { dataLabels: {
enabled: true, enabled: true,
style: { style: {
fontSize: '14px', fontSize: "14px",
fontWeight: 300, fontWeight: 300,
}, },
}, },
legend: { legend: {
show: upperMd show: upperMd,
} },
}; };
const series = data.map((item) => +item.percentage) const series = data.map((item) => +item.percentage);
return ( return <Chart chartId="LoanDistributionPie" type="pie" specialOption={specialOption} series={series} />;
<Chart chartId="LoanDistributionPie" type="pie" specialOption={specialOption} series={series}/>
)
}; };
export default Pie; export default Pie;

Some files were not shown because too many files have changed in this diff Show More