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_PERSON = 10
NEXT_PUBLIC_BUS_AMOUNT=10000
NEXT_PUBLIC_MINIBUS_AMOUNT=4000
NEXT_PUBLIC_BASE_URL = "https://loan-v2.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",
"publish-3002": "next start -p 3002",
"lint": "next lint",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,html,css,scss}\"",
"test": "jest",
"test:watch": "jest --watchAll",
"cypress:open": "cypress open",
@@ -41,6 +42,7 @@
"next-intl": "^2.13.1",
"next-useragent": "^2.8.0",
"nextjs-progressbar": "^0.0.16",
"prettier": "^3.3.3",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-apexcharts": "^1.4.1",

View File

@@ -267,7 +267,7 @@
"upload_expert_file_required": "وارد کردن گزارش کارشناسی الزامیست",
"upload_expert_file_unit": "فایل بارگذاری شده باید حداکثر 5Mb باشد",
"upload_expert_file_format": "فرمت قابل قبول : png,jpg,pdf",
"max_amount": "حداکثر مبلغ تصویب شده {value} میلیون ریال می باشد",
"max_amount": "حداکثر مبلغ تصویب شده {value} {amount} ریال می باشد",
"excel_report": "گزارش اکسل",
"first_form": "فرم الف را بارگذاری کنید",
"second_form": "فرم ب را بارگذاری کنید"
@@ -599,6 +599,7 @@
"participation_period_number": "دوره مشارکت باید عدد باشد",
"tanafos_period_number": "دوره تنفس باید عدد باشد",
"toman": "میلیون تومان",
"milyard_toman": "میلیارد تومان",
"facility_bank_max_amount": "جمع مبلغ سهم دولت و سهم بانک نباید از مبلغ تصویب شده بیشتر باشد .",
"facility_gov_max_amount": "جمع مبلغ سهم دولت و سهم بانک نباید از مبلغ تصویب شده بیشتر باشد .",
"tanafos_period_month": "ماه",
@@ -662,7 +663,7 @@
"unit": " (میلیون ریال)",
"button-revise": "ارسال",
"approved_amount_positive": "مبلغ مصوب باید مثبت باشد",
"max_amount": "حداکثر مبلغ مصوب {value} میلیون ریال می باشد",
"max_amount": "حداکثر مبلغ مصوب {value} {amount} ریال می باشد",
"approved_amount_number": "مبلغ مصوب باید عدد باشد",
"description": "توضیحات خود را وارد نمائید"
},
@@ -780,6 +781,60 @@
"typography": "آیا از حدف این مورد اطمینان دارید ؟",
"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": {
"refer-passenger-boss": "ارجاع به کارگروه",
"refer-user": "ارجاع به کاربر",
@@ -916,5 +971,61 @@
"Table_head_refer_reason": "علت ارجاع",
"Table_head_expert_description": "توضیحات",
"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

@@ -1,20 +1,17 @@
import {Button, DialogActions, DialogContent, Stack, TextField} from "@mui/material";
import {useTranslations} from "next-intl";
import { Button, DialogActions, DialogContent, Stack, TextField } from "@mui/material";
import { useTranslations } from "next-intl";
import useRequest from "@/lib/app/hooks/useRequest";
import * as Yup from "yup";
import {useFormik} from "formik";
import {ADD_ADMIN_SETTING} from "@/core/data/apiRoutes";
import { useFormik } from "formik";
import { ADD_ADMIN_SETTING } from "@/core/data/apiRoutes";
const CreateContent = ({mutate, setOpenConfirmDialog}) => {
const CreateContent = ({ mutate, setOpenConfirmDialog }) => {
const t = useTranslations();
const requestServer = useRequest({auth: true})
const requestServer = useRequest({ auth: true });
const validationSchema = Yup.object().shape({
name: Yup.string("AddDialog.name_string")
.required(t("AddDialog.setting_name_error")),
name_fa: Yup.string("AddDialog.name_fa_string")
.required(t("AddDialog.setting_name_fa_error")),
value: Yup.string("AddDialog.value_string")
.required(t("AddDialog.value_error")),
name: Yup.string("AddDialog.name_string").required(t("AddDialog.setting_name_error")),
name_fa: Yup.string("AddDialog.name_fa_string").required(t("AddDialog.setting_name_fa_error")),
value: Yup.string("AddDialog.value_string").required(t("AddDialog.value_error")),
});
const formik = useFormik({
@@ -22,20 +19,24 @@ const CreateContent = ({mutate, setOpenConfirmDialog}) => {
name: "",
name_fa: "",
value: "",
}, validationSchema, onSubmit: (values, {setSubmitting}) => {
},
validationSchema,
onSubmit: (values, { setSubmitting }) => {
const formData = new FormData();
formData.append("name", values.name);
formData.append("name_fa", values.name_fa);
formData.append("value", values.value);
requestServer(ADD_ADMIN_SETTING, 'post', {
requestServer(ADD_ADMIN_SETTING, "post", {
data: formData,
}).then((response) => {
setOpenConfirmDialog(false)
mutate()
update_notification()
}).catch(() => {
}).finally(() => {
})
.then((response) => {
setOpenConfirmDialog(false);
mutate();
update_notification();
})
.catch(() => {})
.finally(() => {
setSubmitting(false);
});
},
@@ -57,7 +58,7 @@ const CreateContent = ({mutate, setOpenConfirmDialog}) => {
onBlur={formik.handleBlur("name_fa")}
error={formik.touched.name_fa && Boolean(formik.errors.name_fa)}
helperText={formik.touched.name_fa && formik.errors.name_fa}
sx={{mt: 1}}
sx={{ mt: 1 }}
/>
</Stack>
<Stack>
@@ -72,7 +73,7 @@ const CreateContent = ({mutate, setOpenConfirmDialog}) => {
onBlur={formik.handleBlur("name")}
error={formik.touched.name && Boolean(formik.errors.name)}
helperText={formik.touched.name && formik.errors.name}
sx={{mt: 1}}
sx={{ mt: 1 }}
/>
</Stack>
<Stack>
@@ -86,22 +87,31 @@ const CreateContent = ({mutate, setOpenConfirmDialog}) => {
onBlur={formik.handleBlur("value")}
error={formik.touched.value && Boolean(formik.errors.value)}
helperText={formik.touched.value && formik.errors.value}
sx={{mt: 1}}
sx={{ mt: 1 }}
/>
</Stack>
</Stack>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary"
disabled={formik.isSubmitting} autoFocus>
<Button
onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("AddDialog.button-cancel")}
</Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}>
<Button
onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("AddDialog.button-add")}
</Button>
</DialogActions>
</>
)
}
export default CreateContent
);
};
export default CreateContent;

View File

@@ -1,10 +1,10 @@
import {Button, Dialog, DialogTitle, Stack, Tooltip} from "@mui/material";
import { Button, Dialog, DialogTitle, Stack, Tooltip } from "@mui/material";
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
import {useTranslations} from "next-intl";
import {useState} from "react";
import { useTranslations } from "next-intl";
import { useState } from "react";
import CreateContent from "@/components/dashboard/admin-setting/Form/CreateForm/CreateContent";
const CreateForm = ({mutate}) => {
const CreateForm = ({ mutate }) => {
const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
@@ -15,21 +15,28 @@ const CreateForm = ({mutate}) => {
color="primary"
variant="contained"
size="small"
sx={{textTransform: "unset", alignSelf: "center"}}
startIcon={<DataSaverOnIcon/>}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={<DataSaverOnIcon />}
onClick={() => {
setOpenConfirmDialog(true)
setOpenConfirmDialog(true);
}}
>
{t("AddDialog.add")}
</Button>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<CreateContent mutate={mutate} setOpenConfirmDialog={setOpenConfirmDialog}/>
<CreateContent mutate={mutate} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog>
</Stack>
)
}
export default CreateForm
);
};
export default CreateForm;

View File

@@ -1,5 +1,5 @@
import {useTranslations} from "next-intl";
import {useState} from "react";
import { useTranslations } from "next-intl";
import { useState } from "react";
import {
Button,
Dialog,
@@ -8,29 +8,31 @@ import {
DialogTitle,
IconButton,
Tooltip,
Typography
Typography,
} from "@mui/material";
import DeleteIcon from '@mui/icons-material/Delete';
import {DELETE_ADMIN_SETTING} from "@/core/data/apiRoutes";
import DeleteIcon from "@mui/icons-material/Delete";
import { DELETE_ADMIN_SETTING } from "@/core/data/apiRoutes";
import useRequest from "@/lib/app/hooks/useRequest";
import useNotification from "@/lib/app/hooks/useNotification";
const Delete = ({rowId, mutate}) => {
const Delete = ({ rowId, mutate }) => {
const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false)
const requestServer = useRequest({auth: true})
const {update_notification} = useNotification()
const [isSubmitting, setIsSubmitting] = useState(false);
const requestServer = useRequest({ auth: true });
const { update_notification } = useNotification();
const handleSubmit = () => {
setIsSubmitting(true)
requestServer(`${DELETE_ADMIN_SETTING}/${rowId}`, 'delete').then((response) => {
mutate()
update_notification()
}).catch(() => {
}).finally(() => {
setIsSubmitting(false)
setIsSubmitting(true);
requestServer(`${DELETE_ADMIN_SETTING}/${rowId}`, "delete")
.then((response) => {
mutate();
update_notification();
})
.catch(() => {})
.finally(() => {
setIsSubmitting(false);
});
}
};
return (
<>
@@ -38,25 +40,36 @@ const Delete = ({rowId, mutate}) => {
<IconButton
color="primary"
onClick={() => {
setOpenConfirmDialog(true)
setOpenConfirmDialog(true);
}}
>
<DeleteIcon/>
<DeleteIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<DialogContent>
<Typography>{t("DeleteDialog.typography")}</Typography>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary"
disabled={isSubmitting} autoFocus>
<Button
onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={isSubmitting}
autoFocus
>
{t("DeleteDialog.button-cancel")}
</Button>
<Button onClick={handleSubmit} variant="contained" color="primary"
disabled={isSubmitting}>
<Button onClick={handleSubmit} variant="contained" color="primary" disabled={isSubmitting}>
{t("DeleteDialog.button-delete")}
</Button>
</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 useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField} from "@mui/material"
import {useFormik} from "formik";
import {useTranslations} from "next-intl";
import { Button, DialogActions, DialogContent, Stack, TextField } from "@mui/material";
import { useFormik } from "formik";
import { useTranslations } from "next-intl";
import * as Yup from "yup";
const UpdateContent = ({row, mutate, setOpenConfirmDialog}) => {
const UpdateContent = ({ row, mutate, setOpenConfirmDialog }) => {
const t = useTranslations();
const requestServer = useRequest({auth: true})
const {update_notification} = useNotification()
const requestServer = useRequest({ auth: true });
const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({
name: Yup.string("UpdateDialog.name_string")
.required(t("UpdateDialog.setting_name_error")),
name_fa: Yup.string("UpdateDialog.name_fa_string")
.required(t("UpdateDialog.setting_name_fa_error")),
value: Yup.string("UpdateDialog.value_string")
.required(t("UpdateDialog.value_error")),
name: Yup.string("UpdateDialog.name_string").required(t("UpdateDialog.setting_name_error")),
name_fa: Yup.string("UpdateDialog.name_fa_string").required(t("UpdateDialog.setting_name_fa_error")),
value: Yup.string("UpdateDialog.value_string").required(t("UpdateDialog.value_error")),
});
const formik = useFormik({
@@ -25,19 +22,23 @@ const UpdateContent = ({row, mutate, setOpenConfirmDialog}) => {
name: row.getValue("name"),
name_fa: row.getValue("name_fa"),
value: row.getValue("value"),
}, validationSchema, onSubmit: (values, {setSubmitting}) => {
},
validationSchema,
onSubmit: (values, { setSubmitting }) => {
const formData = new FormData();
formData.append("name", values.name);
formData.append("name_fa", values.name_fa);
formData.append("value", values.value);
requestServer(`${UPDATE_ADMIN_SETTING}/${row.getValue("id")}`, 'post', {
requestServer(`${UPDATE_ADMIN_SETTING}/${row.getValue("id")}`, "post", {
data: formData,
}).then((response) => {
setOpenConfirmDialog(false)
mutate()
update_notification()
}).catch(() => {
}).finally(() => {
})
.then((response) => {
setOpenConfirmDialog(false);
mutate();
update_notification();
})
.catch(() => {})
.finally(() => {
setSubmitting(false);
});
},
@@ -58,7 +59,7 @@ const UpdateContent = ({row, mutate, setOpenConfirmDialog}) => {
onBlur={formik.handleBlur("name_fa")}
error={formik.touched.name_fa && Boolean(formik.errors.name_fa)}
helperText={formik.touched.name_fa && formik.errors.name_fa}
sx={{mt: 1}}
sx={{ mt: 1 }}
/>
</Stack>
<Stack>
@@ -73,7 +74,7 @@ const UpdateContent = ({row, mutate, setOpenConfirmDialog}) => {
onBlur={formik.handleBlur("name")}
error={formik.touched.name && Boolean(formik.errors.name)}
helperText={formik.touched.name && formik.errors.name}
sx={{mt: 1}}
sx={{ mt: 1 }}
/>
</Stack>
<Stack>
@@ -88,22 +89,31 @@ const UpdateContent = ({row, mutate, setOpenConfirmDialog}) => {
onBlur={formik.handleBlur("value")}
error={formik.touched.value && Boolean(formik.errors.value)}
helperText={formik.touched.value && formik.errors.value}
sx={{mt: 1}}
sx={{ mt: 1 }}
/>
</Stack>
</Stack>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary"
disabled={formik.isSubmitting} autoFocus>
<Button
onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("UpdateDialog.button-cancel")}
</Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}>
<Button
onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("UpdateDialog.button-update")}
</Button>
</DialogActions>
</>
)
}
export default UpdateContent
);
};
export default UpdateContent;

View File

@@ -1,10 +1,10 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material"
import EditIcon from '@mui/icons-material/Edit';
import {useTranslations} from "next-intl";
import {useState} from "react";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import EditIcon from "@mui/icons-material/Edit";
import { useTranslations } from "next-intl";
import { useState } from "react";
import UpdateContent from "./UpdateContent";
const Update = ({row, mutate}) => {
const Update = ({ row, mutate }) => {
const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
return (
@@ -13,18 +13,25 @@ const Update = ({row, mutate}) => {
<IconButton
color="primary"
onClick={() => {
setOpenConfirmDialog(true)
setOpenConfirmDialog(true);
}}
>
<EditIcon/>
<EditIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<UpdateContent row={row} mutate={mutate} setOpenConfirmDialog={setOpenConfirmDialog}/>
<UpdateContent row={row} mutate={mutate} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog>
</>
)
}
export default Update
);
};
export default Update;

View File

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

View File

@@ -1,11 +1,10 @@
import {useTranslations} from "next-intl";
import { useTranslations } from "next-intl";
import CreateForm from "@/components/dashboard/admin-setting/Form/CreateForm";
function TableToolbar({mutate}) {
function TableToolbar({ mutate }) {
const t = useTranslations();
return <CreateForm mutate={mutate}/>
return <CreateForm mutate={mutate} />;
}
export default TableToolbar;

View File

@@ -1,7 +1,7 @@
import {Box, Typography} from "@mui/material";
import {useMemo} from "react";
import {GET_ADMIN_SETTING} from "@/core/data/apiRoutes";
import {useTranslations} from "next-intl";
import { Box, Typography } from "@mui/material";
import { useMemo } from "react";
import { GET_ADMIN_SETTING } from "@/core/data/apiRoutes";
import { useTranslations } from "next-intl";
import DataTable from "@/core/components/DataTable";
import TableRowActions from "@/components/dashboard/admin-setting/TableRowActions";
import TableToolbar from "@/components/dashboard/admin-setting/TableToolbar";
@@ -18,9 +18,7 @@ function DashboardAdminSettingComponent() {
datatype: "number",
filterFn: "equals",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.name_fa,
@@ -30,9 +28,7 @@ function DashboardAdminSettingComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.name,
@@ -42,9 +38,7 @@ function DashboardAdminSettingComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.value,
@@ -53,19 +47,14 @@ function DashboardAdminSettingComponent() {
enableColumnFilter: true,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: [
"equals",
"contains",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "contains"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
],
[]
);
return (
<Box sx={{px: 3}}>
<Box sx={{ px: 3 }}>
<DataTable
tableUrl={GET_ADMIN_SETTING}
columns={columns}
@@ -73,12 +62,15 @@ function DashboardAdminSettingComponent() {
enableCustomToolbar={true}
CustomToolbar={TableToolbar}
enableLastUpdate={true}
sorting={[{
id: 'id', desc: false
}]}
sorting={[
{
id: "id",
desc: false,
},
]}
enablePinning={true}
enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large)
initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true}
enableHiding={true}
enableFullScreenToggle={false}

View File

@@ -1,18 +1,18 @@
import {Button, CircularProgress} from "@mui/material";
import {useTranslations} from "next-intl";
import {useMemo, useState} from "react";
import { Button, CircularProgress } from "@mui/material";
import { useTranslations } from "next-intl";
import { useMemo, useState } from "react";
import useRequest from "@/lib/app/hooks/useRequest";
import {EXPORT_BANK_MANAGEMENT} from "@/core/data/apiRoutes";
import { EXPORT_BANK_MANAGEMENT } from "@/core/data/apiRoutes";
import moment from "jalali-moment";
import FileSaver from 'file-saver';
import DescriptionIcon from '@mui/icons-material/Description';
import FileSaver from "file-saver";
import DescriptionIcon from "@mui/icons-material/Description";
const PrintExcel = ({table}) => {
const PrintExcel = ({ table }) => {
const t = useTranslations();
const [loading, setLoading] = useState(false)
const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}})
const {columnFilters, columnFilterFns, sorting} = table.getState()
const columns = table.getAllColumns()
const [loading, setLoading] = useState(false);
const requestServer = useRequest({ auth: true, pending: false, success: { notification: { show: false } } });
const { columnFilters, columnFilterFns, sorting } = table.getState();
const columns = table.getAllColumns();
const filterParams = useMemo(() => {
const params = new URLSearchParams();
@@ -24,31 +24,33 @@ const PrintExcel = ({table}) => {
}
}
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("sorting", JSON.stringify(sorting ?? []));
return params;
}, [columnFilters, columnFilterFns, sorting, columns,]);
}, [columnFilters, columnFilterFns, sorting, columns]);
const clickHandler = () => {
setLoading(true)
requestServer(`${EXPORT_BANK_MANAGEMENT}?${filterParams}`, 'get', {
setLoading(true);
requestServer(`${EXPORT_BANK_MANAGEMENT}?${filterParams}`, "get", {
auth: true,
notification: false,
requestOptions: {responseType: 'blob'}
}).then((response) => {
const filename = `گزارش کارتابل نظارت بانک تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`;
FileSaver.saveAs(response.data, filename);
}).catch(() => {
}).finally(() => {
setLoading(false)
requestOptions: { responseType: "blob" },
})
}
.then((response) => {
const filename = `گزارش کارتابل نظارت بانک تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})
.finally(() => {
setLoading(false);
});
};
return (
<Button
@@ -56,13 +58,13 @@ const PrintExcel = ({table}) => {
variant="contained"
size="small"
disabled={loading}
sx={{textTransform: "unset", alignSelf: "center"}}
startIcon={loading ? <CircularProgress size={18} color="inherit"/> : <DescriptionIcon/>}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler}
>
{t("BankManagement.excel_report")}
</Button>
)
}
);
};
export default PrintExcel
export default PrintExcel;

View File

@@ -1,58 +1,80 @@
import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack,} from "@mui/material"
import {useFormik} from "formik";
import {useTranslations} from "next-intl";
import {EDIT_APPROVED_AMOUNT} from "@/core/data/apiRoutes";
import { Button, DialogActions, DialogContent, Stack } from "@mui/material";
import { useFormik } from "formik";
import { useTranslations } from "next-intl";
import { EDIT_APPROVED_AMOUNT } from "@/core/data/apiRoutes";
import * as Yup from "yup";
import PriceField from "@/core/components/PriceField";
const vehicle_amount = {
"اتوبوس": 7000,
"مینی بوس": 2000,
}
"اتوبوس": parseInt(process.env.NEXT_PUBLIC_BUS_AMOUNT),
"مینی بوس": 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 requestServer = useRequest({auth: true, notification: false});
const {update_notification} = useNotification();
const requestServer = useRequest({ auth: true, notification: false });
const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({
approved_amount: Yup.mixed().test(
"is-number",
`${t("EditDialog.approved_amount_number")}`,
(value) => !isNaN(value)
).test("max-amount", `${t("EditDialog.max_amount", {value: parseInt(vehicle_amount[vehicle_type]).toLocaleString('en')})}`,
(value) => value <= vehicle_amount[vehicle_type])
approved_amount: Yup.mixed()
.test("is-number", `${t("EditDialog.approved_amount_number")}`, (value) => !isNaN(value))
.test("max-amount", function (value) {
const maxAmount =
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)
.required(t("EditDialog.edit_approved_amount_required")),
})
});
const formik = useFormik({
initialValues: {
approved_amount: String(row.original.approved_amount / 1000000)
}, validationSchema,
onSubmit: (values, {setSubmitting}) => {
requestServer(`${EDIT_APPROVED_AMOUNT}/${rowId}`, 'post', {
data: {
approved_amount: values.approved_amount
approved_amount: String(row.original.approved_amount / 1000000),
},
notification: true
}).then(() => {
setOpenEditDialog(false)
mutate()
update_notification()
}).catch(() => {
}).finally(() => {
validationSchema,
onSubmit: (values, { setSubmitting }) => {
requestServer(`${EDIT_APPROVED_AMOUNT}/${rowId}`, "post", {
data: {
approved_amount: values.approved_amount,
},
notification: true,
})
.then(() => {
setOpenEditDialog(false);
mutate();
update_notification();
})
.catch(() => {})
.finally(() => {
setSubmitting(false);
});
},
});
const handleAmountChange = (event) => {
if (!isNaN(event.target.value)) {
formik.setFieldValue("approved_amount", event.target.value)
formik.setFieldValue("approved_amount", event.target.value);
} else {
formik.setFieldValue("approved_amount", formik.values.approved_amount)
formik.setFieldValue("approved_amount", formik.values.approved_amount);
}
};
return (
@@ -62,8 +84,12 @@ const EditContent = ({rowId, row, mutate, setOpenEditDialog, vehicle_type}) => {
<Stack>
<PriceField
name="approved_amount"
label={<>
<span>{t("EditDialog.edit_approved_amount")}</span><small>{t("EditDialog.unit")}</small></>}
label={
<>
<span>{t("EditDialog.edit_approved_amount")}</span>
<small>{t("EditDialog.unit")}</small>
</>
}
type="text"
inputProps={{
inputMode: "number",
@@ -74,32 +100,34 @@ const EditContent = ({rowId, row, mutate, setOpenEditDialog, vehicle_type}) => {
value={formik.values.approved_amount}
onChange={handleAmountChange}
onBlur={formik.handleBlur("approved_amount")}
error={
formik.touched.approved_amount &&
Boolean(formik.errors.approved_amount)
}
helperText={
formik.touched.approved_amount && formik.errors.approved_amount
}
sx={{mt: 1}}
error={formik.touched.approved_amount && Boolean(formik.errors.approved_amount)}
helperText={formik.touched.approved_amount && formik.errors.approved_amount}
sx={{ mt: 1 }}
fullWidth
/>
</Stack>
</Stack>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenEditDialog(false)} variant="outlined" color="secondary"
disabled={formik.isSubmitting} autoFocus>
<Button
onClick={() => setOpenEditDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("EditDialog.button-cancel")}
</Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary"
<Button
onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.isValid || !formik.dirty}
>
{t("EditDialog.button-edit")}
</Button>
</DialogActions>
</>
)
}
export default EditContent
);
};
export default EditContent;

View File

@@ -1,10 +1,10 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material";
import {useTranslations} from "next-intl";
import {useState} from "react";
import EditIcon from '@mui/icons-material/Edit';
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import EditIcon from "@mui/icons-material/Edit";
import EditContent from "@/components/dashboard/bank-management/Form/Edit/EditContent";
const EditForm = ({rowId, row, mutate, vehicle_type}) => {
const EditForm = ({ rowId, row, mutate, vehicle_type }) => {
const t = useTranslations();
const [openEditDialog, setOpenEditDialog] = useState(false);
@@ -14,27 +14,33 @@ const EditForm = ({rowId, row, mutate, vehicle_type}) => {
<IconButton
color="primary"
onClick={() => {
setOpenEditDialog(true)
setOpenEditDialog(true);
}}
>
<EditIcon/>
<EditIcon />
</IconButton>
</Tooltip>
<Dialog fullWidth open={openEditDialog}
<Dialog
fullWidth
open={openEditDialog}
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="sm">
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="sm"
>
<DialogTitle>{t("EditDialog.edit_approved_amount")}</DialogTitle>
<EditContent
mutate={mutate} rowId={rowId} setOpenEditDialog={setOpenEditDialog} row={row}
mutate={mutate}
rowId={rowId}
setOpenEditDialog={setOpenEditDialog}
row={row}
vehicle_type={vehicle_type}
/>
</Dialog>
</>
)
}
);
};
export default EditForm;

View File

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

View File

@@ -1,25 +1,32 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material"
import {useTranslations} from "next-intl";
import {useState} from "react";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import RejectContent from "./RejectContent";
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
const RejectForm = ({rowId, mutate}) => {
const RejectForm = ({ rowId, mutate }) => {
const t = useTranslations();
const [openRejectDialog, setOpenRejectDialog] = useState(false);
return (
<>
<Tooltip title={t("RejectDialog.bank_management_reject")}>
<IconButton color="primary" onClick={() => setOpenRejectDialog(true)}>
<ThumbDownIcon/>
<ThumbDownIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog}/>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} />
</Dialog>
</>
)
}
export default RejectForm
);
};
export default RejectForm;

View File

@@ -1,5 +1,5 @@
import {useTranslations} from "next-intl";
import {useState} from "react";
import { useTranslations } from "next-intl";
import { useState } from "react";
import {
Button,
Dialog,
@@ -8,30 +8,32 @@ import {
DialogTitle,
IconButton,
Tooltip,
Typography
Typography,
} 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 useNotification from "@/lib/app/hooks/useNotification";
import {RESEND_BANK_STATEMENT} from "@/core/data/apiRoutes";
import { RESEND_BANK_STATEMENT } from "@/core/data/apiRoutes";
const UpdateForm = ({rowId, mutate}) => {
const UpdateForm = ({ rowId, mutate }) => {
const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false)
const requestServer = useRequest({auth: true})
const {update_notification} = useNotification()
const [isSubmitting, setIsSubmitting] = useState(false);
const requestServer = useRequest({ auth: true });
const { update_notification } = useNotification();
const handleSubmit = () => {
setIsSubmitting(true)
requestServer(`${RESEND_BANK_STATEMENT}/${rowId}`, 'post').then((response) => {
setOpenConfirmDialog(false)
mutate()
update_notification()
}).catch(() => {
}).finally(() => {
setIsSubmitting(false)
setIsSubmitting(true);
requestServer(`${RESEND_BANK_STATEMENT}/${rowId}`, "post")
.then((response) => {
setOpenConfirmDialog(false);
mutate();
update_notification();
})
.catch(() => {})
.finally(() => {
setIsSubmitting(false);
});
}
};
return (
<>
@@ -39,25 +41,36 @@ const UpdateForm = ({rowId, mutate}) => {
<IconButton
color="primary"
onClick={() => {
setOpenConfirmDialog(true)
setOpenConfirmDialog(true);
}}
>
<RefreshIcon/>
<RefreshIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<DialogContent>
<Typography>{t("UpdateDialog.typography")}</Typography>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenConfirmDialog(false)} variant="outlined" color="secondary"
disabled={isSubmitting} autoFocus>
<Button
onClick={() => setOpenConfirmDialog(false)}
variant="outlined"
color="secondary"
disabled={isSubmitting}
autoFocus
>
{t("UpdateDialog.button-cancel")}
</Button>
<Button onClick={handleSubmit} variant="contained" color="primary"
disabled={isSubmitting}>
<Button onClick={handleSubmit} variant="contained" color="primary" disabled={isSubmitting}>
{t("UpdateDialog.button-resend")}
</Button>
</DialogActions>

View File

@@ -1,35 +1,23 @@
import {Box} from "@mui/material";
import { Box } from "@mui/material";
import UpdateForm from "@/components/dashboard/bank-management/Form/Update";
import EditForm from "@/components/dashboard/bank-management/Form/Edit";
import RejectForm from "@/components/dashboard/bank-management/Form/Reject";
const TableRow = ({row, mutate}) => {
const TableRow = ({ row, mutate }) => {
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)) && (
<UpdateForm
rowId={row.getValue("id")}
mutate={mutate}
/>
<UpdateForm 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
rowId={row.getValue("id")}
mutate={mutate}
vehicle_type={row.original.vehicle_type}
row={row}
/>
)
}
)}
</Box>
);
};

View File

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

View File

@@ -1,10 +1,10 @@
import {Box, Typography} from "@mui/material";
import {useMemo} from "react";
import {useTranslations} from "next-intl";
import { Box, Typography } from "@mui/material";
import { useMemo } from "react";
import { useTranslations } from "next-intl";
import moment from "jalali-moment";
import DataTable from "@/core/components/DataTable";
import TableRowActions from "@/components/dashboard/bank-management/TableRowActions";
import {GET_BANK_STATEMENT} from "@/core/data/apiRoutes";
import { GET_BANK_STATEMENT } from "@/core/data/apiRoutes";
import TableToolbar from "@/components/dashboard/bank-management/TableToobar";
function DashboardBankManagementComponent() {
@@ -18,17 +18,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.navgan_id,
@@ -37,17 +28,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.name,
@@ -57,9 +39,7 @@ function DashboardBankManagementComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.national_id,
@@ -68,17 +48,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.national_serial_number,
@@ -87,17 +58,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.national_tracking_code,
@@ -106,14 +68,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true,
datatype: "text",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.birthday,
@@ -123,9 +79,10 @@ function DashboardBankManagementComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography
variant="body2">{moment(renderedCellValue).locale("fa").format("yyyy/MM/DD")}</Typography>
Cell: ({ renderedCellValue }) => (
<Typography variant="body2">
{moment(renderedCellValue).locale("fa").format("yyyy/MM/DD")}
</Typography>
),
},
{
@@ -135,12 +92,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true,
datatype: "text",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
],
Cell: ({renderedCellValue}) => (
columnFilterModeOptions: ["equals", "notEquals", "contains"],
Cell: ({ renderedCellValue }) => (
<Typography variant="body2">{Number(renderedCellValue).toLocaleString()}</Typography>
),
},
@@ -151,15 +104,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => (
<Typography variant="body2">{Number(renderedCellValue).toLocaleString()}</Typography>
),
},
@@ -171,9 +117,7 @@ function DashboardBankManagementComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.bank_state_name,
@@ -182,14 +126,8 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true,
datatype: "text",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains"
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.bank_reason_description,
@@ -198,20 +136,14 @@ function DashboardBankManagementComponent() {
enableColumnFilter: true,
datatype: "text",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains"
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
}
columnFilterModeOptions: ["equals", "notEquals", "contains"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
],
[]
);
return (
<Box sx={{px: 3}}>
<Box sx={{ px: 3 }}>
<DataTable
tableUrl={GET_BANK_STATEMENT}
columns={columns}
@@ -219,12 +151,15 @@ function DashboardBankManagementComponent() {
enableCustomToolbar={true}
CustomToolbar={TableToolbar}
enableLastUpdate={true}
sorting={[{
id: 'score', desc: false
}]}
sorting={[
{
id: "score",
desc: false,
},
]}
enablePinning={true}
enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large)
initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true}
enableHiding={true}
enableFullScreenToggle={false}

View File

@@ -1,27 +1,29 @@
import {Formik} from "formik";
import {useTranslations} from "next-intl";
import { Formik } from "formik";
import { useTranslations } from "next-intl";
import useRequest from "@/lib/app/hooks/useRequest";
import {SET_USER_PASSWORD} from "@/core/data/apiRoutes";
import {Button, Paper, Stack, Typography} from "@mui/material";
import { SET_USER_PASSWORD } from "@/core/data/apiRoutes";
import { Button, Paper, Stack, Typography } from "@mui/material";
import * as Yup from "yup";
import StyledForm from "@/core/components/StyledForm";
import PasswordField from "@/core/components/PasswordField";
const ChangePasswordForm = ({onSubmit}) => {
const ChangePasswordForm = ({ onSubmit }) => {
const t = useTranslations();
const requestServer = useRequest({auth: true})
const requestServer = useRequest({ auth: true });
const handleSubmit = (values, {setSubmitting, resetForm}) => {
requestServer(SET_USER_PASSWORD, 'post', {
const handleSubmit = (values, { setSubmitting, resetForm }) => {
requestServer(SET_USER_PASSWORD, "post", {
data: {
current_password: values.current_password,
new_password: values.new_password,
new_password_confirmation: values.new_password_confirmation,
},
}).then((response) => {
})
.then((response) => {
resetForm();
}).catch(() => {
}).finally(() => {
})
.catch(() => {})
.finally(() => {
setSubmitting(false);
});
};
@@ -31,15 +33,10 @@ const ChangePasswordForm = ({onSubmit}) => {
new_password_confirmation: "",
};
const validationSchema = Yup.object().shape({
current_password: Yup.string().required(
t("ChangePassword.error_message_current_password")
),
current_password: Yup.string().required(t("ChangePassword.error_message_current_password")),
new_password: Yup.string()
.required(t("ExpertMangement.error_message_new_password"))
.matches(
/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/,
t("ExpertMangement.error_message_new_password_regex")
),
.matches(/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/, t("ExpertMangement.error_message_new_password_regex")),
new_password_confirmation: Yup.string()
.required(t("ChangePassword.error_message_confirm_password"))
.test(
@@ -52,11 +49,7 @@ const ChangePasswordForm = ({onSubmit}) => {
});
return (
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
<Formik initialValues={initialValues} onSubmit={handleSubmit} validationSchema={validationSchema}>
{(props) => (
<StyledForm
onSubmit={(e) => {
@@ -65,7 +58,7 @@ const ChangePasswordForm = ({onSubmit}) => {
}}
>
<Paper elevation={0}>
<Stack spacing={3} sx={{p: 5}} component="div">
<Stack spacing={3} sx={{ p: 5 }} component="div">
<Typography margin={2} variant="h4" textAlign="center">
{t("ChangePassword.typography_change_password")}
</Typography>
@@ -74,30 +67,17 @@ const ChangePasswordForm = ({onSubmit}) => {
name="current_password"
label={t("ChangePassword.label_current_password")}
error={
props.touched.current_password &&
props.errors.current_password
? true
: false
}
helperText={
props.touched.current_password
? props.errors.current_password
: null
props.touched.current_password && props.errors.current_password ? true : false
}
helperText={props.touched.current_password ? props.errors.current_password : null}
/>
</Stack>
<Stack spacing={1} component="div">
<PasswordField
name="new_password"
label={t("ChangePassword.label_new_password")}
error={
props.touched.new_password && props.errors.new_password
? true
: false
}
helperText={
props.touched.new_password ? props.errors.new_password : null
}
error={props.touched.new_password && props.errors.new_password ? true : false}
helperText={props.touched.new_password ? props.errors.new_password : null}
/>
</Stack>
<Stack spacing={1} component="div">

View File

@@ -1,12 +1,12 @@
import CenterLayout from "@/layouts/CenterLayout";
import {Container} from "@mui/material";
import { Container } from "@mui/material";
import ChangePasswordForm from "@/components/dashboard/change-password/change-password-form";
const DashboardChangePasswordComponent = () => {
return (
<CenterLayout>
<Container maxWidth="sm">
<ChangePasswordForm/>
<ChangePasswordForm />
</Container>
</CenterLayout>
);

View File

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

View File

@@ -1,10 +1,10 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material";
import {useTranslations} from "next-intl";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
import {useState} from "react";
import { useState } from "react";
import ConfirmContent from "./ConfirmContent";
const Confirm = ({rowId, mutate}) => {
const Confirm = ({ rowId, mutate }) => {
const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
return (
@@ -13,19 +13,25 @@ const Confirm = ({rowId, mutate}) => {
<IconButton
color="primary"
onClick={() => {
setOpenConfirmDialog(true)
setOpenConfirmDialog(true);
}}
>
<ThumbUpAltIcon/>
<ThumbUpAltIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog}/>
<ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog>
</>
)
}
);
};
export default Confirm;

View File

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

View File

@@ -1,25 +1,32 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material"
import {useTranslations} from "next-intl";
import {useState} from "react";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import RejectContent from "./RejectContent";
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
const Reject = ({rowId, mutate}) => {
const Reject = ({ rowId, mutate }) => {
const t = useTranslations();
const [openRejectDialog, setOpenRejectDialog] = useState(false);
return (
<>
<Tooltip title={t("RejectDialog.reject")}>
<IconButton color="primary" onClick={() => setOpenRejectDialog(true)}>
<ThumbDownIcon/>
<ThumbDownIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog}/>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} />
</Dialog>
</>
)
}
export default Reject
);
};
export default Reject;

View File

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

View File

@@ -1,7 +1,7 @@
import {Box, Typography} from "@mui/material";
import {useMemo} from "react";
import {GET_COMMERCIAL_CHIEF} from "@/core/data/apiRoutes";
import {useTranslations} from "next-intl";
import { Box, Typography } from "@mui/material";
import { useMemo } from "react";
import { GET_COMMERCIAL_CHIEF } from "@/core/data/apiRoutes";
import { useTranslations } from "next-intl";
import TableRowActions from "./TableRowActions";
import moment from "jalali-moment";
import DataTable from "@/core/components/DataTable";
@@ -18,17 +18,8 @@ function DashboardCommercialChiefComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.name,
@@ -38,9 +29,7 @@ function DashboardCommercialChiefComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.national_id,
@@ -49,17 +38,8 @@ function DashboardCommercialChiefComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.phone_number,
@@ -68,47 +48,32 @@ function DashboardCommercialChiefComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) =>
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "created_at",
header: t("CommercialChief.created_at"),
enableColumnFilter: true,
datatype: "date",
filterFn: "lessThan",
columnFilterModeOptions: ["lessThan", "greaterThan"],
Cell: ({renderedCellValue}) => {
Cell: ({ renderedCellValue }) => {
return <Typography variant="body2">{renderedCellValue}</Typography>;
},
Header: ({column}) => <>{column.columnDef.header}</>,
Filter: ({column}) => {
return (
<MuiDatePicker column={column}/>
);
Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => {
return <MuiDatePicker column={column} />;
},
},
{
accessorFn: (row) =>
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
accessorFn: (row) => moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "updated_at",
header: t("CommercialChief.updated_at"),
enableColumnFilter: false,
datatype: "numeric",
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.state_name,
@@ -116,28 +81,29 @@ function DashboardCommercialChiefComponent() {
header: t("CommercialChief.state_name"),
enableColumnFilter: false,
datatype: "numeric",
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
],
[]
);
return (
<Box sx={{px: 3}}>
<Box sx={{ px: 3 }}>
<DataTable
tableUrl={GET_COMMERCIAL_CHIEF}
columns={columns}
selectableRow={false}
enableCustomToolbar={false}
enableLastUpdate={true}
sorting={[{
id: 'id', desc: false
}]}
sorting={[
{
id: "id",
desc: false,
},
]}
enablePinning={true}
enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large)
initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true}
enableHiding={true}
enableFullScreenToggle={false}

View File

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

View File

@@ -1,10 +1,10 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material";
import {useTranslations} from "next-intl";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
import {useState} from "react";
import { useState } from "react";
import ConfirmContent from "./ConfirmContent";
const Confirm = ({rowId, mutate}) => {
const Confirm = ({ rowId, mutate }) => {
const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
return (
@@ -13,19 +13,25 @@ const Confirm = ({rowId, mutate}) => {
<IconButton
color="primary"
onClick={() => {
setOpenConfirmDialog(true)
setOpenConfirmDialog(true);
}}
>
<ThumbUpAltIcon/>
<ThumbUpAltIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog}/>
<ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog>
</>
)
}
);
};
export default Confirm;

View File

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

View File

@@ -1,25 +1,32 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material"
import {useTranslations} from "next-intl";
import {useState} from "react";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import RejectContent from "./RejectContent";
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
const Reject = ({rowId, mutate}) => {
const Reject = ({ rowId, mutate }) => {
const t = useTranslations();
const [openRejectDialog, setOpenRejectDialog] = useState(false);
return (
<>
<Tooltip title={t("RejectDialog.reject")}>
<IconButton color="primary" onClick={() => setOpenRejectDialog(true)}>
<ThumbDownIcon/>
<ThumbDownIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog}/>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} />
</Dialog>
</>
)
}
export default Reject
);
};
export default Reject;

View File

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

View File

@@ -1,7 +1,7 @@
import {Box, Typography} from "@mui/material";
import {useMemo} from "react";
import {GET_DEVELOPMENT_ASSISTANT} from "@/core/data/apiRoutes";
import {useTranslations} from "next-intl";
import { Box, Typography } from "@mui/material";
import { useMemo } from "react";
import { GET_DEVELOPMENT_ASSISTANT } from "@/core/data/apiRoutes";
import { useTranslations } from "next-intl";
import TableRowActions from "./TableRowActions";
import moment from "jalali-moment";
import DataTable from "@/core/components/DataTable";
@@ -19,17 +19,8 @@ function DashboardDevelopmentAssistantComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.name,
@@ -39,9 +30,7 @@ function DashboardDevelopmentAssistantComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.national_id,
@@ -50,17 +39,8 @@ function DashboardDevelopmentAssistantComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.phone_number,
@@ -69,47 +49,32 @@ function DashboardDevelopmentAssistantComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) =>
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "created_at",
header: t("DevelopmentAssistant.created_at"),
enableColumnFilter: true,
datatype: "date",
filterFn: "lessThan",
columnFilterModeOptions: ["lessThan", "greaterThan"],
Cell: ({renderedCellValue}) => {
Cell: ({ renderedCellValue }) => {
return <Typography variant="body2">{renderedCellValue}</Typography>;
},
Header: ({column}) => <>{column.columnDef.header}</>,
Filter: ({column}) => {
return (
<MuiDatePicker column={column}/>
);
Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => {
return <MuiDatePicker column={column} />;
},
},
{
accessorFn: (row) =>
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
accessorFn: (row) => moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "updated_at",
header: t("DevelopmentAssistant.updated_at"),
enableColumnFilter: false,
datatype: "numeric",
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.state_name,
@@ -117,16 +82,14 @@ function DashboardDevelopmentAssistantComponent() {
header: t("DevelopmentAssistant.state_name"),
enableColumnFilter: false,
datatype: "numeric",
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
],
[]
);
return (
<Box sx={{px: 3}}>
<Box sx={{ px: 3 }}>
<DataTable
tableUrl={GET_DEVELOPMENT_ASSISTANT}
columns={columns}
@@ -135,10 +98,13 @@ function DashboardDevelopmentAssistantComponent() {
enableLastUpdate={true}
enablePinning={true}
enableDensityToggle={false}
sorting={[{
id: 'id', desc: false
}]}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large)
sorting={[
{
id: "id",
desc: false,
},
]}
initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true}
enableHiding={true}
enableFullScreenToggle={false}

View File

@@ -1,19 +1,17 @@
import StyledForm from "@/core/components/StyledForm";
import CenterLayout from "@/layouts/CenterLayout";
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 {Field, Formik} from "formik";
import {useTranslations} from "next-intl";
import { Field, Formik } from "formik";
import { useTranslations } from "next-intl";
import useDirection from "@/lib/app/hooks/useDirection";
const DashboardEditProfile = () => {
const t = useTranslations();
const {user, token, getUser, changeUser} = useUser();
const {directionApp} = useDirection()
const handleSubmit = (values, {setSubmitting}) => {
};
const { user, token, getUser, changeUser } = useUser();
const { directionApp } = useDirection();
const handleSubmit = (values, { setSubmitting }) => {};
const initialValues = {
expert_avatar: null,
username: user.username,
@@ -27,11 +25,7 @@ const DashboardEditProfile = () => {
return (
<CenterLayout>
<Container maxWidth="sm">
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
<Formik initialValues={initialValues} onSubmit={handleSubmit} validationSchema={validationSchema}>
{(props) => (
<StyledForm
onSubmit={(e) => {
@@ -40,11 +34,11 @@ const DashboardEditProfile = () => {
}}
>
<Paper elevation={0}>
<Stack spacing={3} sx={{p: 5}} component="div">
<Stack spacing={3} sx={{ p: 5 }} component="div">
<Typography margin={2} variant="h4" textAlign="center">
{t("UpdateProfile.typography_edit_profile")}
</Typography>
<Grid container spacing={2} sx={{pb: 2}}>
<Grid container spacing={2} sx={{ pb: 2 }}>
<Grid item xs={12} sm={6}>
<Field
as={TextField}
@@ -54,16 +48,8 @@ const DashboardEditProfile = () => {
margin="normal"
size="small"
disabled={true}
error={
props.touched.username && props.errors.username
? true
: false
}
helperText={
props.touched.username
? props.errors.username
: null
}
error={props.touched.username && props.errors.username ? true : false}
helperText={props.touched.username ? props.errors.username : null}
sx={{
width: "100%",
}}
@@ -78,14 +64,8 @@ const DashboardEditProfile = () => {
margin="normal"
size="small"
disabled={true}
error={
props.touched.name && props.errors.name
? true
: false
}
helperText={
props.touched.name ? props.errors.name : null
}
error={props.touched.name && props.errors.name ? true : false}
helperText={props.touched.name ? props.errors.name : null}
sx={{
width: "100%",
}}
@@ -100,14 +80,8 @@ const DashboardEditProfile = () => {
margin="normal"
size="small"
disabled={true}
error={
props.touched.email && props.errors.email
? true
: false
}
helperText={
props.touched.email ? props.errors.email : null
}
error={props.touched.email && props.errors.email ? true : false}
helperText={props.touched.email ? props.errors.email : null}
sx={{
width: "100%",
}}
@@ -124,15 +98,12 @@ const DashboardEditProfile = () => {
size="small"
disabled={true}
error={
props.touched.province_name &&
props.errors.province_name
props.touched.province_name && props.errors.province_name
? true
: false
}
helperText={
props.touched.province_name
? props.errors.province_name
: null
props.touched.province_name ? props.errors.province_name : null
}
sx={{
width: "100%",
@@ -148,16 +119,8 @@ const DashboardEditProfile = () => {
margin="normal"
size="small"
disabled={true}
error={
props.touched.position && props.errors.position
? true
: false
}
helperText={
props.touched.position
? props.errors.position
: null
}
error={props.touched.position && props.errors.position ? true : false}
helperText={props.touched.position ? props.errors.position : null}
sx={{
width: "100%",
}}

View File

@@ -1,14 +1,13 @@
import {useTranslations} from "next-intl";
import {Button, DialogActions, DialogContent, IconButton, InputAdornment, TextField} from "@mui/material";
import {CHANGE_PASSWORD_EXPERT_MANAGEMENT} from "@/core/data/apiRoutes";
import {useFormik} from "formik";
import { useTranslations } from "next-intl";
import { Button, DialogActions, DialogContent, IconButton, InputAdornment, TextField } from "@mui/material";
import { CHANGE_PASSWORD_EXPERT_MANAGEMENT } from "@/core/data/apiRoutes";
import { useFormik } from "formik";
import * as Yup from "yup";
import {Visibility, VisibilityOff} from "@mui/icons-material";
import {useState} from "react";
import { Visibility, VisibilityOff } from "@mui/icons-material";
import { useState } from "react";
import useRequest from "@/lib/app/hooks/useRequest";
const ChnagePasswordContent = ({rowId, mutate, setOpenChangePasswordDialog}) => {
const ChnagePasswordContent = ({ rowId, mutate, setOpenChangePasswordDialog }) => {
const t = useTranslations();
const requestServer = useRequest();
const [showPassword, setShowPassword] = useState(false);
@@ -20,10 +19,7 @@ const ChnagePasswordContent = ({rowId, mutate, setOpenChangePasswordDialog}) =>
const validationSchema = Yup.object().shape({
new_password: Yup.string()
.required(t("ExpertMangement.error_message_new_password"))
.matches(
/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/,
t("ExpertMangement.error_message_new_password_regex")
),
.matches(/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/, t("ExpertMangement.error_message_new_password_regex")),
});
const formik = useFormik({
@@ -31,19 +27,20 @@ const ChnagePasswordContent = ({rowId, mutate, setOpenChangePasswordDialog}) =>
new_password: "",
},
validationSchema,
onSubmit: (values, {setSubmitting}) => {
onSubmit: (values, { setSubmitting }) => {
const formData = new FormData();
formData.append("new_password", values.new_password);
requestServer(`${CHANGE_PASSWORD_EXPERT_MANAGEMENT}/${rowId}`, 'post', {
requestServer(`${CHANGE_PASSWORD_EXPERT_MANAGEMENT}/${rowId}`, "post", {
auth: true,
data: formData
data: formData,
})
.then((response) => {
setOpenChangePasswordDialog(false)
mutate()
}).catch(() => {
}).finally(() => {
setOpenChangePasswordDialog(false);
mutate();
})
.catch(() => {})
.finally(() => {
setSubmitting(false);
});
},
@@ -62,27 +59,38 @@ const ChnagePasswordContent = ({rowId, mutate, setOpenChangePasswordDialog}) =>
onChange={formik.handleChange}
onBlur={formik.handleBlur}
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"}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleClickShowPassword}>
{showPassword ? <Visibility/> : <VisibilityOff/>}
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
sx={{width: "100%"}}
sx={{ width: "100%" }}
/>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenChangePasswordDialog(false)} variant="outlined" color="secondary"
disabled={formik.isSubmitting} autoFocus>
<Button
onClick={() => setOpenChangePasswordDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ExpertMangement.button-cancel")}
</Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}>
<Button
onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("ExpertMangement.button-confirm")}
</Button>
</DialogActions>

View File

@@ -1,11 +1,10 @@
import {useTranslations} from "next-intl";
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material";
import KeyIcon from '@mui/icons-material/Key';
import {useState} from "react";
import { useTranslations } from "next-intl";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import KeyIcon from "@mui/icons-material/Key";
import { useState } from "react";
import ChangePasswordContent from "./ChangePasswordContent";
const ChangePassword = ({rowId, mutate}) => {
const ChangePassword = ({ rowId, mutate }) => {
const t = useTranslations();
const [openChnagePasswordDialog, setOpenChangePasswordDialog] = useState(false);
@@ -15,17 +14,28 @@ const ChangePassword = ({rowId, mutate}) => {
<IconButton
color="primary"
onClick={() => {
setOpenChangePasswordDialog(true)
setOpenChangePasswordDialog(true);
}}
>
<KeyIcon/>
<KeyIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<ChangePasswordContent rowId={rowId} mutate={mutate}
setOpenChangePasswordDialog={setOpenChangePasswordDialog}/>
<ChangePasswordContent
rowId={rowId}
mutate={mutate}
setOpenChangePasswordDialog={setOpenChangePasswordDialog}
/>
</Dialog>
</>
);

View File

@@ -15,23 +15,23 @@ import {
Select,
TextField,
} from "@mui/material";
import {useFormik} from "formik";
import {useTranslations} from "next-intl";
import { useFormik } from "formik";
import { useTranslations } from "next-intl";
import * as Yup from "yup";
import {useState} from "react";
import {CREATE_EXPERT_MANAGEMENT, GET_CITY_LIST} from "@/core/data/apiRoutes";
import { useState } from "react";
import { CREATE_EXPERT_MANAGEMENT, GET_CITY_LIST } from "@/core/data/apiRoutes";
import useRequest from "@/lib/app/hooks/useRequest";
import useProvince from "@/lib/app/hooks/useProvince";
import useRole from "@/lib/app/hooks/useRole";
import {Visibility, VisibilityOff} from "@mui/icons-material";
import { Visibility, VisibilityOff } from "@mui/icons-material";
const CreateContent = ({setOpenCreateDialog, mutate}) => {
const CreateContent = ({ setOpenCreateDialog, mutate }) => {
const t = useTranslations();
const requestServer = useRequest()
const requestServer = useRequest();
const [cityList, setCityList] = useState([]);
const [cityTextField, setCityTextField] = useState(t("ExpertMangement.text_field_please_select_province"));
const {provinceList, isLoadingProvinceList, errorProvinceList} = useProvince();
const {roleList, isLoadingRoleList, errorRoleList} = useRole();
const { provinceList, isLoadingProvinceList, errorProvinceList } = useProvince();
const { roleList, isLoadingRoleList, errorRoleList } = useRole();
const [showPassword, setShowPassword] = useState(false);
const handleClickShowPassword = () => {
@@ -40,10 +40,10 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
function getCities(province_id) {
formik.setFieldTouched("city_id", false, false);
formik.setFieldValue("city_id", "")
setCityTextField(t("ExpertMangement.text_field_loading_cities_list"))
requestServer(`${GET_CITY_LIST}?province_id=${province_id}`, "get", {auth: true, notification: false})
.then(({data}) => {
formik.setFieldValue("city_id", "");
setCityTextField(t("ExpertMangement.text_field_loading_cities_list"));
requestServer(`${GET_CITY_LIST}?province_id=${province_id}`, "get", { auth: true, notification: false })
.then(({ data }) => {
const result = data.data;
const formattedData = result.map((city, index) => ({
id: index,
@@ -51,13 +51,13 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
value: city.id,
}));
setCityList(formattedData);
setCityTextField(t("ExpertMangement.text_field_city_id"))
}).catch(() => {
setCityTextField(t("ExpertMangement.text_field_error_fetching_cities"))
setCityTextField(t("ExpertMangement.text_field_city_id"));
})
.catch(() => {
setCityTextField(t("ExpertMangement.text_field_error_fetching_cities"));
});
}
const validationSchema = Yup.object().shape({
name: Yup.string().required(t("ExpertMangement.error_message_name")),
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")),
password: Yup.string()
.required(t("ExpertMangement.error_message_password"))
.matches(
/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/,
t("ExpertMangement.error_message_password_regex")
),
.matches(/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/, t("ExpertMangement.error_message_password_regex")),
position: Yup.string().required(t("ExpertMangement.error_message_position")),
province_id: Yup.string().required(t("ExpertMangement.error_message_province_id")),
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({
@@ -87,10 +84,10 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
position: "",
province_id: "",
city_id: "",
role_id: ""
role_id: "",
},
validationSchema,
onSubmit: (values, {setSubmitting}) => {
onSubmit: (values, { setSubmitting }) => {
const formData = new FormData();
formData.append("name", values.name);
formData.append("national_id", values.national_id);
@@ -103,12 +100,13 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
formData.append("position", values.position);
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) => {
setOpenCreateDialog(false)
mutate()
}).catch(() => {
}).finally(() => {
setOpenCreateDialog(false);
mutate();
})
.catch(() => {})
.finally(() => {
setSubmitting(false);
});
},
@@ -117,14 +115,12 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
return (
<>
<DialogContent>
<Box sx={{my: 1}}>
<Box sx={{ my: 1 }}>
<Divider>
<Chip
label={t("ExpertMangement.personal_info")}
/>
<Chip label={t("ExpertMangement.personal_info")} />
</Divider>
</Box>
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
<Grid item xs={12} sm={6} md={4} lg={3}>
<TextField
name="name"
@@ -137,7 +133,7 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onBlur={formik.handleBlur}
error={formik.touched.name && !!formik.errors.name}
helperText={formik.touched.name && formik.errors.name ? formik.errors.name : null}
sx={{width: "100%"}}
sx={{ width: "100%" }}
/>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
@@ -151,8 +147,12 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.national_id && !!formik.errors.national_id}
helperText={formik.touched.national_id && formik.errors.national_id ? formik.errors.national_id : null}
sx={{width: "100%"}}
helperText={
formik.touched.national_id && formik.errors.national_id
? formik.errors.national_id
: null
}
sx={{ width: "100%" }}
/>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
@@ -166,8 +166,12 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.phone_number && !!formik.errors.phone_number}
helperText={formik.touched.phone_number && formik.errors.phone_number ? formik.errors.phone_number : null}
sx={{width: "100%"}}
helperText={
formik.touched.phone_number && formik.errors.phone_number
? formik.errors.phone_number
: null
}
sx={{ width: "100%" }}
/>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
@@ -182,18 +186,16 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onBlur={formik.handleBlur}
error={formik.touched.email && !!formik.errors.email}
helperText={formik.touched.email && formik.errors.email ? formik.errors.email : null}
sx={{width: "100%"}}
sx={{ width: "100%" }}
/>
</Grid>
</Grid>
<Box sx={{my: 1}}>
<Box sx={{ my: 1 }}>
<Divider>
<Chip
label={t("ExpertMangement.user_info")}
/>
<Chip label={t("ExpertMangement.user_info")} />
</Divider>
</Box>
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
<Grid item xs={12} sm={6}>
<TextField
name="username"
@@ -205,8 +207,10 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.username && !!formik.errors.username}
helperText={formik.touched.username && formik.errors.username ? formik.errors.username : null}
sx={{width: "100%"}}
helperText={
formik.touched.username && formik.errors.username ? formik.errors.username : null
}
sx={{ width: "100%" }}
/>
</Grid>
<Grid item xs={12} sm={6}>
@@ -220,33 +224,33 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onChange={formik.handleChange}
onBlur={formik.handleBlur}
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"}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleClickShowPassword}>
{showPassword ? <Visibility/> : <VisibilityOff/>}
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
sx={{width: "100%"}}
sx={{ width: "100%" }}
/>
</Grid>
</Grid>
<Box sx={{my: 1}}>
<Box sx={{ my: 1 }}>
<Divider>
<Chip
label={t("ExpertMangement.rest_info")}
/>
<Chip label={t("ExpertMangement.rest_info")} />
</Divider>
</Box>
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
<Grid item xs={12} sm={6}>
<FormControl
error={formik.touched.province_id && !!formik.errors.province_id}
sx={{width: "100%", mt: 2}}
sx={{ width: "100%", mt: 2 }}
size="small"
>
<InputLabel>{t("ExpertMangement.text_field_province_id")}</InputLabel>
@@ -257,20 +261,16 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
value={formik.values.province_id}
onChange={(e) => {
formik.setFieldValue("province_id", e.target.value);
getCities(e.target.value)
getCities(e.target.value);
}}
onBlur={formik.handleBlur}
fullWidth
variant="outlined"
>
{isLoadingProvinceList ? (
<MenuItem>
{t("ExpertMangement.text_field_loading_provinces_list")}
</MenuItem>
<MenuItem>{t("ExpertMangement.text_field_loading_provinces_list")}</MenuItem>
) : errorProvinceList ? (
<MenuItem>
{t("ExpertMangement.text_field_error_fetching_provinces")}
</MenuItem>
<MenuItem>{t("ExpertMangement.text_field_error_fetching_provinces")}</MenuItem>
) : (
provinceList.map((item) => (
<MenuItem key={item.id} value={item.id}>
@@ -280,7 +280,9 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
)}
</Select>
<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>
</FormControl>
</Grid>
@@ -288,7 +290,7 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
<FormControl
disabled={cityList.length === 0 ? true : false}
error={formik.touched.city_id && !!formik.errors.city_id}
sx={{width: "100%", mt: 2}}
sx={{ width: "100%", mt: 2 }}
size="small"
>
<InputLabel>{cityTextField}</InputLabel>
@@ -313,7 +315,7 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
</FormControl>
</Grid>
</Grid>
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
<Grid item xs={12} sm={6}>
<TextField
name="position"
@@ -325,14 +327,16 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.position && !!formik.errors.position}
helperText={formik.touched.position && formik.errors.position ? formik.errors.position : null}
sx={{width: "100%"}}
helperText={
formik.touched.position && formik.errors.position ? formik.errors.position : null
}
sx={{ width: "100%" }}
/>
</Grid>
<Grid item xs={12} sm={6}>
<FormControl
error={formik.touched.role_id && !!formik.errors.role_id}
sx={{width: "100%", mt: 2}}
sx={{ width: "100%", mt: 2 }}
size="small"
>
<InputLabel>{t("ExpertMangement.text_field_role_id")}</InputLabel>
@@ -346,13 +350,9 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
variant="outlined"
>
{isLoadingRoleList ? (
<MenuItem>
{t("ExpertMangement.text_field_loading_roles_list")}
</MenuItem>
<MenuItem>{t("ExpertMangement.text_field_loading_roles_list")}</MenuItem>
) : errorRoleList ? (
<MenuItem>
{t("ExpertMangement.text_field_error_fetching_roles")}
</MenuItem>
<MenuItem>{t("ExpertMangement.text_field_error_fetching_roles")}</MenuItem>
) : (
roleList.map((item) => (
<MenuItem key={item.id} value={item.id}>
@@ -369,12 +369,21 @@ const CreateContent = ({setOpenCreateDialog, mutate}) => {
</Grid>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenCreateDialog(false)} variant="outlined" color="secondary"
disabled={formik.isSubmitting} autoFocus>
<Button
onClick={() => setOpenCreateDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ExpertMangement.button-cancel")}
</Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}>
<Button
onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("ExpertMangement.button-confirm")}
</Button>
</DialogActions>

View File

@@ -1,10 +1,10 @@
import {Button, Dialog, DialogTitle, Stack, Tooltip,} from "@mui/material";
import {useTranslations} from "next-intl";
import { Button, Dialog, DialogTitle, Stack, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
import {useState} from "react";
import { useState } from "react";
import CreateContent from "./CreateContent";
const Create = ({mutate}) => {
const Create = ({ mutate }) => {
const t = useTranslations();
const [openCreateDialog, setOpenCreateDialog] = useState(false);
@@ -16,21 +16,29 @@ const Create = ({mutate}) => {
color="primary"
variant="contained"
size="small"
sx={{textTransform: "unset", alignSelf: "center"}}
startIcon={<DataSaverOnIcon/>}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={<DataSaverOnIcon />}
onClick={() => {
setOpenCreateDialog(true)
setOpenCreateDialog(true);
}}
>
{t("ExpertMangement.add")}
</Button>
</Tooltip>
</Stack>
<Dialog fullWidth maxWidth={'lg'} open={openCreateDialog}
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'}}}>
<Dialog
fullWidth
maxWidth={"lg"}
open={openCreateDialog}
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",
},
}}
>
<DialogTitle>{t("ExpertMangement.create")}</DialogTitle>
<CreateContent setOpenCreateDialog={setOpenCreateDialog} mutate={mutate}/>
<CreateContent setOpenCreateDialog={setOpenCreateDialog} mutate={mutate} />
</Dialog>
</>
);

View File

@@ -6,30 +6,29 @@ import {
DialogContentText,
DialogTitle,
IconButton,
Tooltip
Tooltip,
} from "@mui/material";
import DeleteIcon from '@mui/icons-material/Delete';
import {useState} from "react";
import {DELETE_EXPERT_MANAGEMENT} from "@/core/data/apiRoutes";
import DeleteIcon from "@mui/icons-material/Delete";
import { useState } from "react";
import { DELETE_EXPERT_MANAGEMENT } from "@/core/data/apiRoutes";
import useRequest from "@/lib/app/hooks/useRequest";
import {useTranslations} from "next-intl";
import { useTranslations } from "next-intl";
const Delete = ({rowId, mutate}) => {
const Delete = ({ rowId, mutate }) => {
const t = useTranslations();
const requestServer = useRequest({auth: true});
const requestServer = useRequest({ auth: true });
const [openDeleteDialog, setOpenDeleteDialog] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const handleDelete = () => {
setIsSubmitting(true)
requestServer(`${DELETE_EXPERT_MANAGEMENT}/${rowId}`, 'post')
setIsSubmitting(true);
requestServer(`${DELETE_EXPERT_MANAGEMENT}/${rowId}`, "post")
.then((response) => {
mutate()
})
.catch(() => {
mutate();
})
.catch(() => {})
.finally(() => {
setIsSubmitting(false)
setIsSubmitting(false);
setOpenDeleteDialog(false);
});
};
@@ -43,15 +42,15 @@ const Delete = ({rowId, mutate}) => {
setOpenDeleteDialog(true);
}}
>
<DeleteIcon/>
<DeleteIcon />
</IconButton>
</Tooltip>
<Dialog
open={openDeleteDialog}
PaperProps={{
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>

View File

@@ -1,4 +1,4 @@
import {useTranslations} from "next-intl";
import { useTranslations } from "next-intl";
import {
Box,
Button,
@@ -12,31 +12,31 @@ import {
InputLabel,
MenuItem,
Select,
TextField
TextField,
} from "@mui/material";
import {useEffect, useState} from "react";
import {useFormik} from "formik";
import {GET_CITY_LIST, UPDATE_EXPERT_MANAGEMENT} from "@/core/data/apiRoutes";
import { useEffect, useState } from "react";
import { useFormik } from "formik";
import { GET_CITY_LIST, UPDATE_EXPERT_MANAGEMENT } from "@/core/data/apiRoutes";
import * as Yup from "yup";
import useRequest from "@/lib/app/hooks/useRequest";
import useProvince from "@/lib/app/hooks/useProvince";
import useRole from "@/lib/app/hooks/useRole";
const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
const UpdateContent = ({ row, mutate, setOpenUpdateDialog }) => {
const t = useTranslations();
const requestServer = useRequest();
const [cityList, setCityList] = useState([]);
const [citiesExist, setCitiesExist] = useState(false);
const [cityTextField, setCityTextField] = useState(t("ExpertMangement.text_field_please_select_province"));
const {provinceList, isLoadingProvinceList, errorProvinceList} = useProvince();
const {roleList, isLoadingRoleList, errorRoleList} = useRole();
const { provinceList, isLoadingProvinceList, errorProvinceList } = useProvince();
const { roleList, isLoadingRoleList, errorRoleList } = useRole();
function getCities(province_id) {
formik.setFieldTouched("city_id", false, false);
citiesExist && formik.setFieldValue("city_id", "")
setCityTextField(t("ExpertMangement.text_field_loading_cities_list"))
requestServer(`${GET_CITY_LIST}?province_id=${province_id}`, "get", {auth: true, notification: false})
.then(({data}) => {
citiesExist && formik.setFieldValue("city_id", "");
setCityTextField(t("ExpertMangement.text_field_loading_cities_list"));
requestServer(`${GET_CITY_LIST}?province_id=${province_id}`, "get", { auth: true, notification: false })
.then(({ data }) => {
const result = data.data;
const formattedData = result.map((city, index) => ({
id: index,
@@ -45,9 +45,10 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
}));
setCitiesExist(true);
setCityList(formattedData);
setCityTextField(t("ExpertMangement.text_field_city_id"))
}).catch(() => {
setCityTextField(t("ExpertMangement.text_field_error_fetching_cities"))
setCityTextField(t("ExpertMangement.text_field_city_id"));
})
.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")),
province_id: Yup.string().required(t("ExpertMangement.error_message_province_id")),
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({
initialValues: {
@@ -72,10 +73,10 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
position: row.original.position,
province_id: row.original.province_id,
city_id: row.original.city_id,
role_id: row.original.roles[0].id
role_id: row.original.roles[0].id,
},
validationSchema,
onSubmit: (values, {setSubmitting}) => {
onSubmit: (values, { setSubmitting }) => {
const formData = new FormData();
formData.append("name", values.name);
formData.append("national_id", values.national_id);
@@ -87,12 +88,13 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
formData.append("position", values.position);
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) => {
setOpenUpdateDialog(false);
mutate()
}).catch(() => {
}).finally(() => {
mutate();
})
.catch(() => {})
.finally(() => {
setSubmitting(false);
});
},
@@ -105,14 +107,12 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
return (
<>
<DialogContent>
<Box sx={{my: 1}}>
<Box sx={{ my: 1 }}>
<Divider>
<Chip
label={t("ExpertMangement.personal_info")}
/>
<Chip label={t("ExpertMangement.personal_info")} />
</Divider>
</Box>
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
<Grid item xs={12} sm={6} md={4} lg={3}>
<TextField
name="name"
@@ -125,7 +125,7 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
onBlur={formik.handleBlur}
error={formik.touched.name && !!formik.errors.name}
helperText={formik.touched.name && formik.errors.name ? formik.errors.name : null}
sx={{width: "100%"}}
sx={{ width: "100%" }}
/>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
@@ -139,8 +139,12 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.national_id && !!formik.errors.national_id}
helperText={formik.touched.national_id && formik.errors.national_id ? formik.errors.national_id : null}
sx={{width: "100%"}}
helperText={
formik.touched.national_id && formik.errors.national_id
? formik.errors.national_id
: null
}
sx={{ width: "100%" }}
/>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
@@ -154,8 +158,12 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.phone_number && !!formik.errors.phone_number}
helperText={formik.touched.phone_number && formik.errors.phone_number ? formik.errors.phone_number : null}
sx={{width: "100%"}}
helperText={
formik.touched.phone_number && formik.errors.phone_number
? formik.errors.phone_number
: null
}
sx={{ width: "100%" }}
/>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
@@ -170,18 +178,16 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
onBlur={formik.handleBlur}
error={formik.touched.email && !!formik.errors.email}
helperText={formik.touched.email && formik.errors.email ? formik.errors.email : null}
sx={{width: "100%"}}
sx={{ width: "100%" }}
/>
</Grid>
</Grid>
<Box sx={{my: 1}}>
<Box sx={{ my: 1 }}>
<Divider>
<Chip
label={t("ExpertMangement.user_info")}
/>
<Chip label={t("ExpertMangement.user_info")} />
</Divider>
</Box>
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
<Grid item xs={12} sm={6}>
<TextField
name="username"
@@ -193,23 +199,23 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.username && !!formik.errors.username}
helperText={formik.touched.username && formik.errors.username ? formik.errors.username : null}
sx={{width: "100%"}}
helperText={
formik.touched.username && formik.errors.username ? formik.errors.username : null
}
sx={{ width: "100%" }}
/>
</Grid>
</Grid>
<Box sx={{my: 1}}>
<Box sx={{ my: 1 }}>
<Divider>
<Chip
label={t("ExpertMangement.rest_info")}
/>
<Chip label={t("ExpertMangement.rest_info")} />
</Divider>
</Box>
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
<Grid item xs={12} sm={6}>
<FormControl
error={formik.touched.province_id && !!formik.errors.province_id}
sx={{width: "100%", mt: 2}}
sx={{ width: "100%", mt: 2 }}
size="small"
>
<InputLabel>{t("ExpertMangement.text_field_province_id")}</InputLabel>
@@ -223,13 +229,9 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
variant="outlined"
>
{isLoadingProvinceList ? (
<MenuItem>
{t("ExpertMangement.text_field_loading_provinces_list")}
</MenuItem>
<MenuItem>{t("ExpertMangement.text_field_loading_provinces_list")}</MenuItem>
) : errorProvinceList ? (
<MenuItem>
{t("ExpertMangement.text_field_error_fetching_provinces")}
</MenuItem>
<MenuItem>{t("ExpertMangement.text_field_error_fetching_provinces")}</MenuItem>
) : (
provinceList.map((item) => (
<MenuItem key={item.id} value={item.id}>
@@ -239,7 +241,9 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
)}
</Select>
<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>
</FormControl>
</Grid>
@@ -247,7 +251,7 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
<FormControl
disabled={cityList.length === 0}
error={formik.touched.city_id && !!formik.errors.city_id}
sx={{width: "100%", mt: 2}}
sx={{ width: "100%", mt: 2 }}
size="small"
>
<InputLabel>{cityTextField}</InputLabel>
@@ -272,7 +276,7 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
</FormControl>
</Grid>
</Grid>
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid container justifyContent="space-around" spacing={2} sx={{ pb: 2 }}>
<Grid item xs={12} sm={6}>
<TextField
name="position"
@@ -284,14 +288,16 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.position && !!formik.errors.position}
helperText={formik.touched.position && formik.errors.position ? formik.errors.position : null}
sx={{width: "100%"}}
helperText={
formik.touched.position && formik.errors.position ? formik.errors.position : null
}
sx={{ width: "100%" }}
/>
</Grid>
<Grid item xs={12} sm={6}>
<FormControl
error={formik.touched.role_id && !!formik.errors.role_id}
sx={{width: "100%", mt: 2}}
sx={{ width: "100%", mt: 2 }}
size="small"
>
<InputLabel>{t("ExpertMangement.text_field_role_id")}</InputLabel>
@@ -305,13 +311,9 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
variant="outlined"
>
{isLoadingRoleList ? (
<MenuItem>
{t("ExpertMangement.text_field_loading_roles_list")}
</MenuItem>
<MenuItem>{t("ExpertMangement.text_field_loading_roles_list")}</MenuItem>
) : errorRoleList ? (
<MenuItem>
{t("ExpertMangement.text_field_error_fetching_roles")}
</MenuItem>
<MenuItem>{t("ExpertMangement.text_field_error_fetching_roles")}</MenuItem>
) : (
roleList.map((item) => (
<MenuItem key={item.id} value={item.id}>
@@ -328,12 +330,21 @@ const UpdateContent = ({row, mutate, setOpenUpdateDialog}) => {
</Grid>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenUpdateDialog(false)} variant="outlined" color="secondary"
disabled={formik.isSubmitting} autoFocus>
<Button
onClick={() => setOpenUpdateDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ExpertMangement.button-cancel")}
</Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}>
<Button
onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("ExpertMangement.button-confirm")}
</Button>
</DialogActions>

View File

@@ -1,11 +1,10 @@
import {useTranslations} from "next-intl";
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material";
import EditIcon from '@mui/icons-material/Edit';
import {useState} from "react";
import { useTranslations } from "next-intl";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import EditIcon from "@mui/icons-material/Edit";
import { useState } from "react";
import UpdateContent from "./UpdateContent";
const Update = ({row, mutate}) => {
const Update = ({ row, mutate }) => {
const t = useTranslations();
const [openUpdateDialog, setOpenUpdateDialog] = useState(false);
@@ -15,16 +14,24 @@ const Update = ({row, mutate}) => {
<IconButton
color="primary"
onClick={() => {
setOpenUpdateDialog(true)
setOpenUpdateDialog(true);
}}
>
<EditIcon/>
<EditIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<UpdateContent row={row} mutate={mutate} setOpenUpdateDialog={setOpenUpdateDialog}/>
<UpdateContent row={row} mutate={mutate} setOpenUpdateDialog={setOpenUpdateDialog} />
</Dialog>
</>
);

View File

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

View File

@@ -1,11 +1,11 @@
import {useTranslations} from "next-intl";
import { useTranslations } from "next-intl";
import Create from "./Form/CreateForm";
function TableToolbar({mutate, fetchUrl}) {
function TableToolbar({ mutate, fetchUrl }) {
const t = useTranslations();
return (
<>
<Create mutate={mutate} fetchUrl={fetchUrl}/>
<Create mutate={mutate} fetchUrl={fetchUrl} />
</>
);
}

View File

@@ -1,7 +1,7 @@
import {Box, Typography} from "@mui/material";
import {useMemo} from "react";
import {GET_EXPERT_MANAGEMENT} from "@/core/data/apiRoutes";
import {useTranslations} from "next-intl";
import { Box, Typography } from "@mui/material";
import { useMemo } from "react";
import { GET_EXPERT_MANAGEMENT } from "@/core/data/apiRoutes";
import { useTranslations } from "next-intl";
import TableRowActions from "./TableRowActions";
import DataTable from "@/core/components/DataTable";
import TableToolbar from "@/components/dashboard/expert-management/TableToolbar";
@@ -19,17 +19,8 @@ function DashboardExpertManagementComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.name,
@@ -39,9 +30,7 @@ function DashboardExpertManagementComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.username,
@@ -51,9 +40,7 @@ function DashboardExpertManagementComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.phone_number,
@@ -63,9 +50,7 @@ function DashboardExpertManagementComponent() {
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.national_id,
@@ -75,9 +60,7 @@ function DashboardExpertManagementComponent() {
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.position,
@@ -87,9 +70,7 @@ function DashboardExpertManagementComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.province_name,
@@ -99,9 +80,7 @@ function DashboardExpertManagementComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.roles[0].name_fa,
@@ -111,27 +90,22 @@ function DashboardExpertManagementComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) =>
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
accessorFn: (row) => moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "updated_at",
header: t("ExpertMangement.updated_at"),
enableColumnFilter: true,
datatype: "date",
filterFn: "lessThan",
columnFilterModeOptions: ["lessThan", "greaterThan"],
Cell: ({renderedCellValue}) => {
Cell: ({ renderedCellValue }) => {
return <Typography variant="body2">{renderedCellValue}</Typography>;
},
Header: ({column}) => <>{column.columnDef.header}</>,
Filter: ({column}) => {
return (
<MuiDatePicker column={column}/>
);
Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => {
return <MuiDatePicker column={column} />;
},
},
],
@@ -139,20 +113,23 @@ function DashboardExpertManagementComponent() {
);
return (
<Box sx={{px: 3}}>
<Box sx={{ px: 3 }}>
<DataTable
tableUrl={GET_EXPERT_MANAGEMENT}
columns={columns}
selectableRow={false}
CustomToolbar={TableToolbar}
sorting={[{
id: 'id', desc: true
}]}
sorting={[
{
id: "id",
desc: true,
},
]}
enableCustomToolbar={true}
enableLastUpdate={true}
enablePinning={true}
enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large)
initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true}
enableHiding={true}
enableFullScreenToggle={false}

View File

@@ -1,23 +1,20 @@
import FullPageLayout from "@/layouts/FullPageLayout";
import CenterLayout from "@/layouts/CenterLayout";
import {Box, Stack, Typography, Card, CardContent, CardHeader, useTheme, useMediaQuery} from "@mui/material";
import { Box, Stack, Typography, Card, CardContent, CardHeader, useTheme, useMediaQuery } from "@mui/material";
import { useEffect, useState } from "react";
import useRequest from "@/lib/app/hooks/useRequest";
import {useTranslations} from "next-intl";
import {GET_LOAN_STATISTICS} from "@/core/data/apiRoutes";
import { useTranslations } from "next-intl";
import { GET_LOAN_STATISTICS } from "@/core/data/apiRoutes";
const DashboardFirstComponent = () => {
const theme = useTheme();
const t = useTranslations();
const requestServer = useRequest({ auth: true, notification: false });
const [data, setData] = useState(null);
const isXL = useMediaQuery(theme.breakpoints.up('xl'));
const isXL = useMediaQuery(theme.breakpoints.up("xl"));
useEffect(() => {
requestServer(
`${GET_LOAN_STATISTICS}`,
"get"
)
requestServer(`${GET_LOAN_STATISTICS}`, "get")
.then((res) => {
setData(res.data.data);
})
@@ -30,210 +27,330 @@ const DashboardFirstComponent = () => {
<>
<FullPageLayout>
<CenterLayout>
<Stack 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' }}>
<Stack
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
sx={{
height: '50px',
backgroundColor: 'rgba(8, 64, 112, 0.08)',
color: 'primary.main',
textAlign:'center',
height: "50px",
backgroundColor: "rgba(8, 64, 112, 0.08)",
color: "primary.main",
textAlign: "center",
}}
titleTypographyProps={{
variant: 'body1',
variant: "body1",
sx: {
textAlign: 'center',
fontWeight: 'bold',
[theme.breakpoints.down('xl')]: {
fontSize: '12px',
textAlign: "center",
fontWeight: "bold",
[theme.breakpoints.down("xl")]: {
fontSize: "12px",
},
},
}
}}
title={t("Dashboard.total_number_loan_offers")}
/>
<CardContent sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent:'center', height: 'calc(100% - 50px)', padding: "0 !important"}}>
<Box
<CardContent
sx={{
borderBottom: '6px solid',
borderColor: 'primary.main',
borderRadius: '6px 6px 6px 6px',
width: '90%',
textAlign:'center',
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "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")}
</Typography>
</Box>
<Box component={'img'} sx={{width: '40px', height: '40px', mt:2}}
src={'/images/pie-chart.png'}/>
<Box
component={"img"}
sx={{ width: "40px", height: "40px", mt: 2 }}
src={"/images/pie-chart.png"}
/>
</CardContent>
</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
sx={{
height: '50px',
backgroundColor: 'rgba(8, 64, 112, 0.08)',
color: 'primary.main',
textAlign:'center',
fontSize: '14px',
fontWeight: 'bold',
height: "50px",
backgroundColor: "rgba(8, 64, 112, 0.08)",
color: "primary.main",
textAlign: "center",
fontSize: "14px",
fontWeight: "bold",
}}
titleTypographyProps={{
variant: 'body1',
variant: "body1",
sx: {
textAlign: 'center',
fontWeight: 'bold',
[theme.breakpoints.down('xl')]: {
fontSize: '12px',
textAlign: "center",
fontWeight: "bold",
[theme.breakpoints.down("xl")]: {
fontSize: "12px",
},
},
}
}}
title={t("Dashboard.total_amount_proposed_loan")}
/>
<CardContent sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent:'center', height: 'calc(100% - 50px)', padding: "0 !important"}}>
<Box
<CardContent
sx={{
borderBottom: '6px solid',
borderColor: 'primary.main',
borderRadius: '6px 6px 6px 6px',
width: '90%',
textAlign:'center',
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
height: "calc(100% - 50px)",
padding: "0 !important",
}}
>
<Typography variant={isXL ? 'h5' : 'h6'} sx={{ lineHeight: 1.5, fontWeight: 'bold' }}>
{(Number(data.totalProposedAmount)/1000000).toLocaleString("en")}
<Box component="span" sx={{ fontSize: '9px' , paddingLeft: '3px'}}>
<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")}
<Box component="span" sx={{ fontSize: "9px", paddingLeft: "3px" }}>
{t("million_rial")}
</Box>
</Typography>
</Box>
<Box component={'img'} sx={{width: '40px', height: '40px' , mt:2}}
src={'/images/rial.png'}/>
<Box
component={"img"}
sx={{ width: "40px", height: "40px", mt: 2 }}
src={"/images/rial.png"}
/>
</CardContent>
</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
sx={{
height: '50px',
backgroundColor: 'rgba(8, 64, 112, 0.08)',
color: 'primary.main',
textAlign:'center',
fontSize: '14px',
fontWeight: 'bold',
height: "50px",
backgroundColor: "rgba(8, 64, 112, 0.08)",
color: "primary.main",
textAlign: "center",
fontSize: "14px",
fontWeight: "bold",
}}
titleTypographyProps={{
variant: 'body1',
variant: "body1",
sx: {
textAlign: 'center',
fontWeight: 'bold',
[theme.breakpoints.down('xl')]: {
fontSize: '12px',
textAlign: "center",
fontWeight: "bold",
[theme.breakpoints.down("xl")]: {
fontSize: "12px",
},
},
}
}}
title={t("Dashboard.total_number_requests")}
/>
<CardContent sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent:'center', height: 'calc(100% - 50px)', padding: "0 !important"}}>
<Box
<CardContent
sx={{
borderBottom: '6px solid',
borderColor: 'primary.main',
borderRadius: '6px 6px 6px 6px',
width: '90%',
textAlign:'center',
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "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")}
</Typography>
</Box>
<Box component={'img'} sx={{width: '40px', height: '40px' , mt:2}}
src={'/images/pie-chart.png'}/>
<Box
component={"img"}
sx={{ width: "40px", height: "40px", mt: 2 }}
src={"/images/pie-chart.png"}
/>
</CardContent>
</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
sx={{
height: '50px',
backgroundColor: 'rgba(8, 64, 112, 0.08)',
color: 'primary.main',
textAlign:'center',
fontSize: '14px',
fontWeight: 'bold',
height: "50px",
backgroundColor: "rgba(8, 64, 112, 0.08)",
color: "primary.main",
textAlign: "center",
fontSize: "14px",
fontWeight: "bold",
}}
titleTypographyProps={{
variant: 'body1',
variant: "body1",
sx: {
textAlign: 'center',
fontWeight: 'bold',
[theme.breakpoints.down('xl')]: {
fontSize: '12px',
textAlign: "center",
fontWeight: "bold",
[theme.breakpoints.down("xl")]: {
fontSize: "12px",
},
},
}
}}
title={t("Dashboard.total_amount_approved_loans")}
/>
<CardContent sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent:'center', height: 'calc(100% - 50px)', padding: "0 !important"}}>
<Box
<CardContent
sx={{
borderBottom: '6px solid',
borderColor: 'primary.main',
borderRadius: '6px 6px 6px 6px',
width: '90%',
textAlign:'center',
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "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")}
<Box component="span" sx={{ fontSize: '9px' , paddingLeft: '3px' }}>
<Box component="span" sx={{ fontSize: "9px", paddingLeft: "3px" }}>
{t("million_rial")}
</Box>
</Typography>
</Box>
<Box component={'img'} sx={{width: '40px', height: '40px' , mt:2}}
src={'/images/rial.png'}/>
<Box
component={"img"}
sx={{ width: "40px", height: "40px", mt: 2 }}
src={"/images/rial.png"}
/>
</CardContent>
</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
sx={{
height: '50px',
backgroundColor: 'rgba(8, 64, 112, 0.08)',
color: 'primary.main',
textAlign:'center',
fontSize: '14px',
fontWeight: 'bold',
height: "50px",
backgroundColor: "rgba(8, 64, 112, 0.08)",
color: "primary.main",
textAlign: "center",
fontSize: "14px",
fontWeight: "bold",
}}
titleTypographyProps={{
variant: 'body1',
variant: "body1",
sx: {
textAlign: 'center',
fontWeight: 'bold',
[theme.breakpoints.down('xl')]: {
fontSize: '12px',
textAlign: "center",
fontWeight: "bold",
[theme.breakpoints.down("xl")]: {
fontSize: "12px",
},
},
}
}}
title={t("Dashboard.number_approved_loans")}
/>
<CardContent sx={{display: 'flex', flexDirection: 'column', alignItems: 'center' , justifyContent:'center', height: 'calc(100% - 50px)' , padding: "0 !important"}}>
<Box
<CardContent
sx={{
borderBottom: '6px solid',
borderColor: 'primary.main',
borderRadius: '6px 6px 6px 6px',
width: '90%',
textAlign:'center',
alignSelf: 'center',
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "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",
alignSelf: "center",
}}
>
<Typography
variant={isXL ? "h5" : "h6"}
sx={{ lineHeight: 1.5, fontWeight: "bold" }}
>
{Number(data.approvedCount).toLocaleString("en")}
</Typography>
</Box>
<Box component={'img'} sx={{width: '40px', height: '40px' , mt:2}}
src={'/images/pie-chart.png'}/>
<Box
component={"img"}
sx={{ width: "40px", height: "40px", mt: 2 }}
src={"/images/pie-chart.png"}
/>
</CardContent>
</Card>
</Stack>

View File

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

View File

@@ -1,10 +1,10 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material";
import {useTranslations} from "next-intl";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
import {useState} from "react";
import { useState } from "react";
import ConfirmContent from "./ConfirmContent";
const Confirm = ({rowId, mutate}) => {
const Confirm = ({ rowId, mutate }) => {
const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
return (
@@ -13,19 +13,25 @@ const Confirm = ({rowId, mutate}) => {
<IconButton
color="primary"
onClick={() => {
setOpenConfirmDialog(true)
setOpenConfirmDialog(true);
}}
>
<ThumbUpAltIcon/>
<ThumbUpAltIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog}/>
<ConfirmContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog>
</>
)
}
);
};
export default Confirm;

View File

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

View File

@@ -1,25 +1,32 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material"
import {useTranslations} from "next-intl";
import {useState} from "react";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import RejectContent from "./RejectContent";
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
const Reject = ({rowId, mutate}) => {
const Reject = ({ rowId, mutate }) => {
const t = useTranslations();
const [openRejectDialog, setOpenRejectDialog] = useState(false);
return (
<>
<Tooltip title={t("RejectDialog.reject")}>
<IconButton color="primary" onClick={() => setOpenRejectDialog(true)}>
<ThumbDownIcon/>
<ThumbDownIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog}/>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} />
</Dialog>
</>
)
}
export default Reject
);
};
export default Reject;

View File

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

View File

@@ -1,10 +1,10 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material";
import {useTranslations} from "next-intl";
import ReplyIcon from '@mui/icons-material/Reply';
import {useState} from "react";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import ReplyIcon from "@mui/icons-material/Reply";
import { useState } from "react";
import ReviseContent from "./ReviseContent";
const Revise = ({rowId, mutate}) => {
const Revise = ({ rowId, mutate }) => {
const t = useTranslations();
const [openReviseDialog, setOpenReviseDialog] = useState(false);
return (
@@ -13,19 +13,25 @@ const Revise = ({rowId, mutate}) => {
<IconButton
color="primary"
onClick={() => {
setOpenReviseDialog(true)
setOpenReviseDialog(true);
}}
>
<ReplyIcon/>
<ReplyIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<ReviseContent mutate={mutate} rowId={rowId} setOpenReviseDialog={setOpenReviseDialog}/>
<ReviseContent mutate={mutate} rowId={rowId} setOpenReviseDialog={setOpenReviseDialog} />
</Dialog>
</>
)
}
);
};
export default Revise;

View File

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

View File

@@ -1,7 +1,7 @@
import {Box, Typography} from "@mui/material";
import {useMemo} from "react";
import {GET_INSPECTOR_EXPERT} from "@/core/data/apiRoutes";
import {useTranslations} from "next-intl";
import { Box, Typography } from "@mui/material";
import { useMemo } from "react";
import { GET_INSPECTOR_EXPERT } from "@/core/data/apiRoutes";
import { useTranslations } from "next-intl";
import TableRowActions from "./TableRowActions";
import moment from "jalali-moment";
import DataTable from "@/core/components/DataTable";
@@ -18,17 +18,8 @@ function DashboardInspectorExpertComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.name,
@@ -38,9 +29,7 @@ function DashboardInspectorExpertComponent() {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.national_id,
@@ -49,17 +38,8 @@ function DashboardInspectorExpertComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.phone_number,
@@ -68,47 +48,32 @@ function DashboardInspectorExpertComponent() {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) =>
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "created_at",
header: t("InspectorExpert.created_at"),
enableColumnFilter: true,
datatype: "date",
filterFn: "lessThan",
columnFilterModeOptions: ["lessThan", "greaterThan"],
Cell: ({renderedCellValue}) => {
Cell: ({ renderedCellValue }) => {
return <Typography variant="body2">{renderedCellValue}</Typography>;
},
Header: ({column}) => <>{column.columnDef.header}</>,
Filter: ({column}) => {
return (
<MuiDatePicker column={column}/>
);
Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => {
return <MuiDatePicker column={column} />;
},
},
{
accessorFn: (row) =>
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
accessorFn: (row) => moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "updated_at",
header: t("InspectorExpert.updated_at"),
enableColumnFilter: false,
datatype: "numeric",
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.state_name,
@@ -116,16 +81,14 @@ function DashboardInspectorExpertComponent() {
header: t("InspectorExpert.state_name"),
enableColumnFilter: false,
datatype: "numeric",
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
],
[]
);
return (
<Box sx={{px: 3}}>
<Box sx={{ px: 3 }}>
<DataTable
tableUrl={GET_INSPECTOR_EXPERT}
columns={columns}
@@ -133,11 +96,14 @@ function DashboardInspectorExpertComponent() {
enableCustomToolbar={false}
enableLastUpdate={true}
enablePinning={true}
sorting={[{
id: 'id', desc: false
}]}
sorting={[
{
id: "id",
desc: false,
},
]}
enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large)
initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true}
enableHiding={true}
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,15 +1,15 @@
import useNotification from "@/lib/app/hooks/useNotification";
import useRequest from "@/lib/app/hooks/useRequest";
import {Button, DialogActions, DialogContent, Stack, TextField} from "@mui/material"
import {useFormik} from "formik";
import {useTranslations} from "next-intl";
import { Button, DialogActions, DialogContent, Stack, TextField } from "@mui/material";
import { useFormik } from "formik";
import { useTranslations } from "next-intl";
import * as Yup from "yup";
import {REFER_LOAN_FOLLOWUP_PASSENGERBOSS} from "@/core/data/apiRoutes";
import { REFER_LOAN_FOLLOWUP_PASSENGERBOSS } from "@/core/data/apiRoutes";
const ReferPassengerBossContent = ({rowId, mutate, setOpenReferDialog}) => {
const ReferPassengerBossContent = ({ rowId, mutate, setOpenReferDialog }) => {
const t = useTranslations();
const requestServer = useRequest({auth: true})
const {update_notification} = useNotification()
const requestServer = useRequest({ auth: true });
const { update_notification } = useNotification();
const validationSchema = Yup.object().shape({
description: Yup.string().required(t("ReferDialog.description_error")),
@@ -20,17 +20,19 @@ const ReferPassengerBossContent = ({rowId, mutate, setOpenReferDialog}) => {
description: "",
},
validationSchema,
onSubmit: (values, {setSubmitting}) => {
onSubmit: (values, { setSubmitting }) => {
const formData = new FormData();
formData.append("expert_description", values.description);
requestServer(`${REFER_LOAN_FOLLOWUP_PASSENGERBOSS}/${rowId}`, 'post', {
requestServer(`${REFER_LOAN_FOLLOWUP_PASSENGERBOSS}/${rowId}`, "post", {
data: formData,
}).then((response) => {
setOpenReferDialog(false)
mutate()
update_notification()
}).catch(() => {
}).finally(() => {
})
.then((response) => {
setOpenReferDialog(false);
mutate();
update_notification();
})
.catch(() => {})
.finally(() => {
setSubmitting(false);
});
},
@@ -53,28 +55,35 @@ const ReferPassengerBossContent = ({rowId, mutate, setOpenReferDialog}) => {
value={formik.values.description}
onChange={handleDescriptionChange}
onBlur={formik.handleBlur("description")}
error={
formik.touched.description && Boolean(formik.errors.description)
}
error={formik.touched.description && Boolean(formik.errors.description)}
helperText={formik.touched.description && formik.errors.description}
fullWidth
variant="outlined"
sx={{mt: 1}}
sx={{ mt: 1 }}
/>
</Stack>
</Stack>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenReferDialog(false)} variant="outlined" color="secondary"
disabled={formik.isSubmitting} autoFocus>
<Button
onClick={() => setOpenReferDialog(false)}
variant="outlined"
color="secondary"
disabled={formik.isSubmitting}
autoFocus
>
{t("ReferDialog.button-cancel")}
</Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}>
<Button
onClick={formik.handleSubmit}
variant="contained"
color="primary"
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}
>
{t("ReferDialog.button-refer")}
</Button>
</DialogActions>
</>
)
}
export default ReferPassengerBossContent
);
};
export default ReferPassengerBossContent;

View File

@@ -1,25 +1,32 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material"
import {useTranslations} from "next-intl";
import {useState} from "react";
import UTurnRightIcon from '@mui/icons-material/UTurnRight';
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import UTurnRightIcon from "@mui/icons-material/UTurnRight";
import ReferPassengerBossContent from "./ReferPassengerBossContent";
const ReferPassengerBoss = ({rowId, mutate}) => {
const ReferPassengerBoss = ({ rowId, mutate }) => {
const t = useTranslations();
const [openReferDialog, setOpenReferDialog] = useState(false);
return (
<>
<Tooltip title={t("ReferDialog.refer-passenger-boss")}>
<IconButton color="primary" onClick={() => setOpenReferDialog(true)}>
<UTurnRightIcon/>
<UTurnRightIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<ReferPassengerBossContent mutate={mutate} rowId={rowId} setOpenReferDialog={setOpenReferDialog}/>
<ReferPassengerBossContent mutate={mutate} rowId={rowId} setOpenReferDialog={setOpenReferDialog} />
</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 UserInfoForm from "./Form/UserInfoForm";
import PlanningCouncilForm from "@/components/dashboard/loan-followup/Form/PlanningCouncilForm";
const TableRow = ({row, mutate}) => {
const TableRow = ({ row, mutate }) => {
return (
<Box sx={{display: "flex", flexWrap: "nowrap", gap: "8px"}}>
{
row.original.state_id === 11 || row.original.state_id === 16 ? (
<ReferPassengerBoss
rowId={row.getValue("id")}
mutate={mutate}
/>
) : null
}
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
<UserInfoForm rowId={row.getValue("id")} row={row} />
<PlanningCouncilForm rowId={row.getValue("id")} />
{row.original.state_id === 11 || row.original.state_id === 16 ? (
<ReferPassengerBoss rowId={row.getValue("id")} mutate={mutate} />
) : null}
</Box>
);
};

View File

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

View File

@@ -1,14 +1,14 @@
import {useTranslations} from "next-intl";
import {useMemo} from "react";
import {Box, Typography} from "@mui/material";
import { useTranslations } from "next-intl";
import { useMemo } from "react";
import { Box, Typography } from "@mui/material";
import moment from "jalali-moment";
import MuiDatePicker from "@/core/components/MuiDatePicker";
import DataTable from "@/core/components/DataTable";
import {GET_LOAN_FOLLOWUP} from "@/core/data/apiRoutes";
import { GET_LOAN_FOLLOWUP } from "@/core/data/apiRoutes";
import TableToolbar from "./TableToolbar";
import TableRowActions from "./TableRowActions";
function DashboardLoanFollowUpComponent () {
function DashboardLoanFollowUpComponent() {
const t = useTranslations();
const columns = useMemo(
() => [
@@ -19,17 +19,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.navgan_id,
@@ -38,17 +29,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.name,
@@ -58,9 +40,7 @@ function DashboardLoanFollowUpComponent () {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.national_id,
@@ -69,17 +49,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.shenase_meli,
@@ -88,17 +59,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.national_serial_number,
@@ -107,17 +69,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.national_tracking_code,
@@ -126,14 +79,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true,
datatype: "text",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.birthday,
@@ -143,9 +90,10 @@ function DashboardLoanFollowUpComponent () {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography
variant="body2">{moment(renderedCellValue).locale("fa").format("yyyy/MM/DD")}</Typography>
Cell: ({ renderedCellValue }) => (
<Typography variant="body2">
{moment(renderedCellValue).locale("fa").format("yyyy/MM/DD")}
</Typography>
),
},
{
@@ -155,12 +103,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true,
datatype: "text",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
],
Cell: ({renderedCellValue}) => (
columnFilterModeOptions: ["equals", "notEquals", "contains"],
Cell: ({ renderedCellValue }) => (
<Typography variant="body2">{Number(renderedCellValue).toLocaleString()}</Typography>
),
},
@@ -172,9 +116,7 @@ function DashboardLoanFollowUpComponent () {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.province_name,
@@ -184,9 +126,7 @@ function DashboardLoanFollowUpComponent () {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.city_name,
@@ -196,27 +136,22 @@ function DashboardLoanFollowUpComponent () {
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["contains", "equals", "notEquals"],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) =>
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
id: "created_at",
header: t("LoanFollowUp.created_at"),
enableColumnFilter: true,
datatype: "date",
filterFn: "lessThan",
columnFilterModeOptions: ["lessThan", "greaterThan"],
Cell: ({renderedCellValue}) => {
Cell: ({ renderedCellValue }) => {
return <Typography variant="body2">{renderedCellValue}</Typography>;
},
Header: ({column}) => <>{column.columnDef.header}</>,
Filter: ({column}) => {
return (
<MuiDatePicker column={column}/>
);
Header: ({ column }) => <>{column.columnDef.header}</>,
Filter: ({ column }) => {
return <MuiDatePicker column={column} />;
},
},
{
@@ -226,17 +161,8 @@ function DashboardLoanFollowUpComponent () {
enableColumnFilter: true,
datatype: "numeric",
filterFn: "equals",
columnFilterModeOptions: [
"equals",
"notEquals",
"contains",
"lessThan",
"greaterThan",
"between",
],
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between"],
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
{
accessorFn: (row) => row.state_name,
@@ -244,15 +170,13 @@ function DashboardLoanFollowUpComponent () {
header: t("LoanFollowUp.state_name"),
enableColumnFilter: false,
datatype: "numeric",
Cell: ({renderedCellValue}) => (
<Typography variant="body2">{renderedCellValue}</Typography>
),
Cell: ({ renderedCellValue }) => <Typography variant="body2">{renderedCellValue}</Typography>,
},
],
[]
);
return (
<Box sx={{px: 3}}>
<Box sx={{ px: 3 }}>
<DataTable
tableUrl={GET_LOAN_FOLLOWUP}
columns={columns}
@@ -262,7 +186,7 @@ function DashboardLoanFollowUpComponent () {
enableLastUpdate={true}
enablePinning={true}
enableDensityToggle={false}
initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large)
initialState={{ density: "compact" }} //compact (small) //comfortable (medium) //spacious (large)
enableColumnFilters={true}
enableHiding={true}
enableFullScreenToggle={false}
@@ -274,4 +198,4 @@ function DashboardLoanFollowUpComponent () {
</Box>
);
}
export default DashboardLoanFollowUpComponent
export default DashboardLoanFollowUpComponent;

View File

@@ -1,18 +1,18 @@
import {Button, CircularProgress} from "@mui/material";
import {useTranslations} from "next-intl";
import {useMemo, useState} from "react";
import { Button, CircularProgress } from "@mui/material";
import { useTranslations } from "next-intl";
import { useMemo, useState } from "react";
import useRequest from "@/lib/app/hooks/useRequest";
import {EXPORT_LOAN_HISTORY} from "@/core/data/apiRoutes";
import { EXPORT_LOAN_HISTORY } from "@/core/data/apiRoutes";
import moment from "jalali-moment";
import FileSaver from 'file-saver';
import DescriptionIcon from '@mui/icons-material/Description';
import FileSaver from "file-saver";
import DescriptionIcon from "@mui/icons-material/Description";
const PrintExcel = ({table}) => {
const PrintExcel = ({ table }) => {
const t = useTranslations();
const [loading, setLoading] = useState(false)
const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}})
const {columnFilters, columnFilterFns, sorting} = table.getState()
const columns = table.getAllColumns()
const [loading, setLoading] = useState(false);
const requestServer = useRequest({ auth: true, pending: false, success: { notification: { show: false } } });
const { columnFilters, columnFilterFns, sorting } = table.getState();
const columns = table.getAllColumns();
const filterParams = useMemo(() => {
const params = new URLSearchParams();
@@ -24,30 +24,32 @@ const PrintExcel = ({table}) => {
}
}
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("sorting", JSON.stringify(sorting ?? []));
return params;
}, [columnFilters, columnFilterFns, sorting, columns,]);
}, [columnFilters, columnFilterFns, sorting, columns]);
const clickHandler = () => {
setLoading(true)
requestServer(`${EXPORT_LOAN_HISTORY}?${filterParams}`, 'get', {
setLoading(true);
requestServer(`${EXPORT_LOAN_HISTORY}?${filterParams}`, "get", {
auth: true,
requestOptions: {responseType: 'blob'}
}).then((response) => {
const filename = `خروجی کارتابل نظارت تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`;
FileSaver.saveAs(response.data, filename);
}).catch(() => {
}).finally(() => {
setLoading(false)
requestOptions: { responseType: "blob" },
})
}
.then((response) => {
const filename = `خروجی کارتابل نظارت تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})
.finally(() => {
setLoading(false);
});
};
return (
<Button
@@ -55,13 +57,13 @@ const PrintExcel = ({table}) => {
variant="contained"
size="small"
disabled={loading}
sx={{textTransform: "unset", alignSelf: "center"}}
startIcon={loading ? <CircularProgress size={18} color="inherit"/> : <DescriptionIcon/>}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler}
>
{t("LoanHistory.excel_report")}
</Button>
)
}
);
};
export default PrintExcel
export default PrintExcel;

View File

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

View File

@@ -1,11 +1,11 @@
import {Button, CircularProgress} from "@mui/material";
import {useTranslations} from "next-intl";
import {useState} from "react";
import { Button, CircularProgress } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
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";
const PrintHistory = ({attachment}) => {
const PrintHistory = ({ attachment }) => {
const t = useTranslations();
return (
<Button
@@ -20,6 +20,6 @@ const PrintHistory = ({attachment}) => {
{attachment.title}
</Button>
);
}
};
export default PrintHistory
export default PrintHistory;

View File

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

View File

@@ -1,10 +1,10 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material";
import {useTranslations} from "next-intl";
import {useState} from "react";
import HistoryIcon from '@mui/icons-material/History';
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import HistoryIcon from "@mui/icons-material/History";
import HistoryContent from "@/components/dashboard/loan-history/Form/HistoryForm/HistoryContent";
const History = ({rowId, mutate}) => {
const History = ({ rowId, mutate }) => {
const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
return (
@@ -13,19 +13,27 @@ const History = ({rowId, mutate}) => {
<IconButton
color="primary"
onClick={() => {
setOpenConfirmDialog(true)
setOpenConfirmDialog(true);
}}
>
<HistoryIcon/>
<HistoryIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<HistoryContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog}/>
<HistoryContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog>
</>
)
}
);
};
export default History;

View File

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

View File

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

View File

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

View File

@@ -1,18 +1,18 @@
import {Button, CircularProgress} from "@mui/material";
import {useTranslations} from "next-intl";
import {useMemo, useState} from "react";
import { Button, CircularProgress } from "@mui/material";
import { useTranslations } from "next-intl";
import { useMemo, useState } from "react";
import useRequest from "@/lib/app/hooks/useRequest";
import {EXPORT_LOAN_MANAGEMENT_HISTORY} from "@/core/data/apiRoutes";
import { EXPORT_LOAN_MANAGEMENT_HISTORY } from "@/core/data/apiRoutes";
import moment from "jalali-moment";
import FileSaver from 'file-saver';
import DescriptionIcon from '@mui/icons-material/Description';
import FileSaver from "file-saver";
import DescriptionIcon from "@mui/icons-material/Description";
const PrintExcel = ({table}) => {
const PrintExcel = ({ table }) => {
const t = useTranslations();
const [loading, setLoading] = useState(false)
const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}})
const {columnFilters, columnFilterFns, sorting} = table.getState()
const columns = table.getAllColumns()
const [loading, setLoading] = useState(false);
const requestServer = useRequest({ auth: true, pending: false, success: { notification: { show: false } } });
const { columnFilters, columnFilterFns, sorting } = table.getState();
const columns = table.getAllColumns();
const filterParams = useMemo(() => {
const params = new URLSearchParams();
@@ -24,30 +24,32 @@ const PrintExcel = ({table}) => {
}
}
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("sorting", JSON.stringify(sorting ?? []));
return params;
}, [columnFilters, columnFilterFns, sorting, columns,]);
}, [columnFilters, columnFilterFns, sorting, columns]);
const clickHandler = () => {
setLoading(true)
requestServer(`${EXPORT_LOAN_MANAGEMENT_HISTORY}?${filterParams}`, 'get', {
setLoading(true);
requestServer(`${EXPORT_LOAN_MANAGEMENT_HISTORY}?${filterParams}`, "get", {
auth: true,
requestOptions: {responseType: 'blob'}
}).then((response) => {
const filename = `خروجی کارتابل مدیریت وام ها تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`;
FileSaver.saveAs(response.data, filename);
}).catch(() => {
}).finally(() => {
setLoading(false)
requestOptions: { responseType: "blob" },
})
}
.then((response) => {
const filename = `خروجی کارتابل مدیریت وام ها تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})
.finally(() => {
setLoading(false);
});
};
return (
<Button
@@ -55,13 +57,13 @@ const PrintExcel = ({table}) => {
variant="contained"
size="small"
disabled={loading}
sx={{textTransform: "unset", alignSelf: "center"}}
startIcon={loading ? <CircularProgress size={18} color="inherit"/> : <DescriptionIcon/>}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler}
>
{t("NavganLoanManagement.excel_report")}
</Button>
)
}
);
};
export default PrintExcel
export default PrintExcel;

View File

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

View File

@@ -1,10 +1,10 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material";
import {useTranslations} from "next-intl";
import ChangeCircleIcon from '@mui/icons-material/ChangeCircle';
import {useState} from "react";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import ChangeCircleIcon from "@mui/icons-material/ChangeCircle";
import { useState } from "react";
import UpdateContent from "./UpdateContent";
const Update = ({rowId, mutate}) => {
const Update = ({ rowId, mutate }) => {
const t = useTranslations();
const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
return (
@@ -13,18 +13,25 @@ const Update = ({rowId, mutate}) => {
<IconButton
color="primary"
onClick={() => {
setOpenConfirmDialog(true)
setOpenConfirmDialog(true);
}}
>
<ChangeCircleIcon/>
<ChangeCircleIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<UpdateContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog}/>
<UpdateContent mutate={mutate} rowId={rowId} setOpenConfirmDialog={setOpenConfirmDialog} />
</Dialog>
</>
)
}
export default Update
);
};
export default Update;

View File

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

View File

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

View File

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

View File

@@ -1,18 +1,18 @@
import {Button, CircularProgress} from "@mui/material";
import {useTranslations} from "next-intl";
import {useMemo, useState} from "react";
import { Button, CircularProgress } from "@mui/material";
import { useTranslations } from "next-intl";
import { useMemo, useState } from "react";
import useRequest from "@/lib/app/hooks/useRequest";
import {EXPORT_NAVGAN_PROVINCE_MANAGER} from "@/core/data/apiRoutes";
import { EXPORT_NAVGAN_PROVINCE_MANAGER } from "@/core/data/apiRoutes";
import moment from "jalali-moment";
import FileSaver from 'file-saver';
import DescriptionIcon from '@mui/icons-material/Description';
import FileSaver from "file-saver";
import DescriptionIcon from "@mui/icons-material/Description";
const PrintExcel = ({table}) => {
const PrintExcel = ({ table }) => {
const t = useTranslations();
const [loading, setLoading] = useState(false)
const requestServer = useRequest({auth: true, pending: false, success: {notification: {show: false}}})
const {columnFilters, columnFilterFns, sorting} = table.getState()
const columns = table.getAllColumns()
const [loading, setLoading] = useState(false);
const requestServer = useRequest({ auth: true, pending: false, success: { notification: { show: false } } });
const { columnFilters, columnFilterFns, sorting } = table.getState();
const columns = table.getAllColumns();
const filterParams = useMemo(() => {
const params = new URLSearchParams();
@@ -24,30 +24,32 @@ const PrintExcel = ({table}) => {
}
}
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("sorting", JSON.stringify(sorting ?? []));
return params;
}, [columnFilters, columnFilterFns, sorting, columns,]);
}, [columnFilters, columnFilterFns, sorting, columns]);
const clickHandler = () => {
setLoading(true)
requestServer(`${EXPORT_NAVGAN_PROVINCE_MANAGER}?${filterParams}`, 'get', {
setLoading(true);
requestServer(`${EXPORT_NAVGAN_PROVINCE_MANAGER}?${filterParams}`, "get", {
auth: true,
requestOptions: {responseType: 'blob'}
}).then((response) => {
const filename = `خروجی کارتابل بررسی وام های تبصره 18 تاریخ_${moment().format('jYYYY_jMM_jDD')}.xlsx`;
FileSaver.saveAs(response.data, filename);
}).catch(() => {
}).finally(() => {
setLoading(false)
requestOptions: { responseType: "blob" },
})
}
.then((response) => {
const filename = `خروجی کارتابل بررسی وام های تبصره 18 تاریخ_${moment().format("jYYYY_jMM_jDD")}.xlsx`;
FileSaver.saveAs(response.data, filename);
})
.catch(() => {})
.finally(() => {
setLoading(false);
});
};
return (
<Button
@@ -55,13 +57,13 @@ const PrintExcel = ({table}) => {
variant="contained"
size="small"
disabled={loading}
sx={{textTransform: "unset", alignSelf: "center"}}
startIcon={loading ? <CircularProgress size={18} color="inherit"/> : <DescriptionIcon/>}
sx={{ textTransform: "unset", alignSelf: "center" }}
startIcon={loading ? <CircularProgress size={18} color="inherit" /> : <DescriptionIcon />}
onClick={clickHandler}
>
{t("NavganProvinceManager.excel_report")}
</Button>
)
}
);
};
export default PrintExcel
export default PrintExcel;

View File

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

View File

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

View File

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

View File

@@ -1,25 +1,32 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material"
import {useTranslations} from "next-intl";
import {useState} from "react";
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import RejectContent from "./RejectContent";
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
const Reject = ({rowId, mutate}) => {
const Reject = ({ rowId, mutate }) => {
const t = useTranslations();
const [openRejectDialog, setOpenRejectDialog] = useState(false);
return (
<>
<Tooltip title={t("RejectDialog.reject")}>
<IconButton color="primary" onClick={() => setOpenRejectDialog(true)}>
<ThumbDownIcon/>
<ThumbDownIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog}/>
<RejectContent mutate={mutate} rowId={rowId} setOpenRejectDialog={setOpenRejectDialog} />
</Dialog>
</>
)
}
export default Reject
);
};
export default Reject;

View File

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

View File

@@ -1,25 +1,32 @@
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material"
import {useTranslations} from "next-intl";
import {useState} from "react";
import CallReceivedIcon from '@mui/icons-material/CallReceived';
import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material";
import { useTranslations } from "next-intl";
import { useState } from "react";
import CallReceivedIcon from "@mui/icons-material/CallReceived";
import RevertContent from "@/components/dashboard/navgan-province-manager/Form/RevertForm/RevertContent";
const Revert = ({rowId, mutate}) => {
const Revert = ({ rowId, mutate }) => {
const t = useTranslations();
const [openRevertDialog, setOpenRevertDialog] = useState(false);
return (
<>
<Tooltip title={t("RevertDialog.revert")}>
<IconButton color="primary" onClick={() => setOpenRevertDialog(true)}>
<CallReceivedIcon/>
<CallReceivedIcon />
</IconButton>
</Tooltip>
<Dialog 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'}}}>
<Dialog
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>
<RevertContent mutate={mutate} rowId={rowId} setOpenRevertDialog={setOpenRevertDialog}/>
<RevertContent mutate={mutate} rowId={rowId} setOpenRevertDialog={setOpenRevertDialog} />
</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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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