LFFE-12 Merge branch 'feature/LFFE-12_synchronization_projects' into 'develop'
This commit is contained in:
@@ -360,7 +360,8 @@
|
||||
"permission_min_error": "حداقل باید یک دسترسی انتخاب شود",
|
||||
"type_id": "نوع کاربر",
|
||||
"navgan_id": "کد ناوگان",
|
||||
"button-update": "ویرایش"
|
||||
"button-update": "ویرایش",
|
||||
"loading_permissions_list": "درحال دریافت لیست دسترسی ها"
|
||||
},
|
||||
"UploadSystem": {
|
||||
"upload_file": "فایل خود را بارگذاری کنید",
|
||||
@@ -467,6 +468,7 @@
|
||||
"type_id": "نوع کاربر",
|
||||
"navgan_id": "کد ناوگان",
|
||||
"button-cancel": "انصراف",
|
||||
"button-add": "ثبت"
|
||||
"button-add": "ثبت",
|
||||
"loading_permissions_list": "درحال دریافت لیست دسترسی ها"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
|
||||
onSubmit: (values, {setSubmitting}) => {
|
||||
const formData = new FormData();
|
||||
formData.append("proposed_amount", values.proposed_amount);
|
||||
if (values.description != "") formData.append("description", values.description);
|
||||
if (values.description != "") formData.append("expert_description", values.description);
|
||||
if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
|
||||
|
||||
requestServer(`${CONFIRM_MACHINARY_OFFICE}/${rowId}`, 'post', {
|
||||
|
||||
@@ -6,7 +6,7 @@ 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_MACHINARY_OFFICE} from "@/core/data/apiRoutes";
|
||||
|
||||
const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
|
||||
const [selectedImage, setSelectedImage] = useState("");
|
||||
@@ -29,10 +29,10 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
|
||||
validationSchema,
|
||||
onSubmit: (values, {setSubmitting}) => {
|
||||
const formData = new FormData();
|
||||
formData.append("description", values.description);
|
||||
formData.append("expert_description", values.description);
|
||||
if (values.reject_img != null) formData.append("attachment", values.reject_img);
|
||||
|
||||
requestServer(`${REJECT_INSPECTOR_EXPERT}/${rowId}`, 'post', {
|
||||
requestServer(`${REJECT_MACHINARY_OFFICE}/${rowId}`, 'post', {
|
||||
data: formData,
|
||||
}).then((response) => {
|
||||
setOpenRejectDialog(false)
|
||||
|
||||
@@ -24,7 +24,7 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
|
||||
},
|
||||
onSubmit: (values, {setSubmitting}) => {
|
||||
const formData = new FormData();
|
||||
if (values.description != "") formData.append("description", values.description);
|
||||
if (values.description != "") formData.append("expert_description", values.description);
|
||||
if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
|
||||
|
||||
requestServer(`${CONFIRM_NAVGAN_PROVINCE_MANAGER}/${rowId}`, 'post', {
|
||||
|
||||
@@ -29,7 +29,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
|
||||
validationSchema,
|
||||
onSubmit: (values, {setSubmitting}) => {
|
||||
const formData = new FormData();
|
||||
formData.append("description", values.description);
|
||||
formData.append("expert_description", values.description);
|
||||
if (values.reject_img != null) formData.append("attachment", values.reject_img);
|
||||
|
||||
requestServer(`${REJECT_NAVGAN_PROVINCE_MANAGER}/${rowId}`, 'post', {
|
||||
|
||||
@@ -37,7 +37,7 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
|
||||
onSubmit: (values, {setSubmitting}) => {
|
||||
const formData = new FormData();
|
||||
formData.append("approved_amount", values.approved_amount);
|
||||
if (values.description != "") formData.append("description", values.description);
|
||||
if (values.description != "") formData.append("expert_description", values.description);
|
||||
if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
|
||||
|
||||
requestServer(`${CONFIRM_PASSENGER_BOSS}/${rowId}`, 'post', {
|
||||
|
||||
@@ -29,7 +29,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
|
||||
validationSchema,
|
||||
onSubmit: (values, {setSubmitting}) => {
|
||||
const formData = new FormData();
|
||||
formData.append("description", values.description);
|
||||
formData.append("expert_description", values.description);
|
||||
if (values.reject_img != null) formData.append("attachment", values.reject_img);
|
||||
|
||||
requestServer(`${REJECT_PASSENGER_BOSS}/${rowId}`, 'post', {
|
||||
|
||||
@@ -29,7 +29,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
|
||||
validationSchema,
|
||||
onSubmit: (values, {setSubmitting}) => {
|
||||
const formData = new FormData();
|
||||
formData.append("description", values.description);
|
||||
formData.append("expert_description", values.description);
|
||||
if (values.reject_img != null) formData.append("attachment", values.reject_img);
|
||||
|
||||
requestServer(`${REJECT_PASSENGER_OFFICE}/${rowId}`, 'post', {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Checkbox, CircularProgress,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
FormControl,
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
FormLabel,
|
||||
Grid,
|
||||
Stack,
|
||||
TextField
|
||||
TextField, Typography
|
||||
} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
@@ -21,7 +21,7 @@ import usePermissions from "@/lib/app/hooks/usePermissions";
|
||||
const CreateContent = ({mutate, setOpenConfirmDialog}) => {
|
||||
const t = useTranslations();
|
||||
const requestServer = useRequest({auth: true})
|
||||
const {permissions_list} = usePermissions()
|
||||
const {permissions_list, isLoading} = usePermissions()
|
||||
const validationSchema = Yup.object().shape({
|
||||
name: Yup.string().required(t("AddDialog.name_error")),
|
||||
name_fa: Yup.string().required(t("AddDialog.name_fa_error")),
|
||||
@@ -93,29 +93,40 @@ const CreateContent = ({mutate, setOpenConfirmDialog}) => {
|
||||
sx={{mt: 2}}
|
||||
>
|
||||
<FormHelperText>{formik.touched.permissions && formik.errors.permissions}</FormHelperText>
|
||||
<Grid container spacing={2}>
|
||||
{permissions_list ? (
|
||||
permissions_list.map((permission) => (
|
||||
<Grid key={permission.id} item xs={6}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={formik.values.permissions.includes(permission.id)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
formik.setFieldValue("permissions", [...formik.values.permissions, permission.id])
|
||||
} else {
|
||||
formik.setFieldValue("permissions", formik.values.permissions.filter((id) => id !== permission.id))
|
||||
}
|
||||
}}
|
||||
{isLoading ?
|
||||
<Stack direction={'row'} alignItems={'center'} spacing={2}
|
||||
justifyContent={'center'}>
|
||||
<CircularProgress size={20}/>
|
||||
<Typography
|
||||
variant={'caption'}>{t("AddDialog.loading_permissions_list")}</Typography>
|
||||
</Stack>
|
||||
: (
|
||||
<Grid container spacing={2}>
|
||||
<>
|
||||
{permissions_list.map((permission, index) => (
|
||||
<Grid key={permission.id} item xs={6} data-testid= "PermissionList-checkbox">
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
data-testid= {`PermissionList-checkbox-${index}`}
|
||||
checked={formik.values.permissions.includes(permission.id)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
formik.setFieldValue("permissions", [...formik.values.permissions, permission.id])
|
||||
} else {
|
||||
formik.setFieldValue("permissions", formik.values.permissions.filter((id) => id !== permission.id))
|
||||
}
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={permission.name_fa}
|
||||
/>
|
||||
}
|
||||
label={permission.name_fa}
|
||||
/>
|
||||
</Grid>
|
||||
))
|
||||
) : null}
|
||||
</Grid>
|
||||
</Grid>
|
||||
))}
|
||||
</>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
</FormControl>
|
||||
</FormLabel>
|
||||
</Stack>
|
||||
|
||||
@@ -4,7 +4,7 @@ import usePermissions from "@/lib/app/hooks/usePermissions";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Checkbox, CircularProgress,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
FormControl,
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
FormLabel,
|
||||
Grid,
|
||||
Stack,
|
||||
TextField
|
||||
TextField, Typography
|
||||
} from "@mui/material"
|
||||
import {useFormik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
@@ -23,7 +23,7 @@ const UpdateContent = ({row, mutate, setOpenConfirmDialog}) => {
|
||||
const t = useTranslations();
|
||||
const requestServer = useRequest({auth: true})
|
||||
const {update_notification} = useNotification()
|
||||
const {permissions_list} = usePermissions()
|
||||
const {permissions_list, isLoading} = usePermissions()
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
name: Yup.string().required(t("UpdateDialog.name_error")),
|
||||
@@ -93,29 +93,40 @@ const UpdateContent = ({row, mutate, setOpenConfirmDialog}) => {
|
||||
sx={{mt: 2}}
|
||||
>
|
||||
<FormHelperText>{formik.touched.permissions && formik.errors.permissions}</FormHelperText>
|
||||
<Grid container spacing={2}>
|
||||
{permissions_list ? (
|
||||
permissions_list.map((permission) => (
|
||||
<Grid key={permission.id} item xs={6}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={formik.values.permissions.includes(permission.id)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
formik.setFieldValue("permissions", [...formik.values.permissions, permission.id])
|
||||
} else {
|
||||
formik.setFieldValue("permissions", formik.values.permissions.filter((id) => id !== permission.id))
|
||||
}
|
||||
}}
|
||||
{isLoading ?
|
||||
<Stack direction={'row'} alignItems={'center'} spacing={2}
|
||||
justifyContent={'center'}>
|
||||
<CircularProgress size={20}/>
|
||||
<Typography
|
||||
variant={'caption'}>{t("UpdateDialog.loading_permissions_list")}</Typography>
|
||||
</Stack>
|
||||
: (
|
||||
<Grid container spacing={2}>
|
||||
<>
|
||||
{permissions_list.map((permission) => (
|
||||
<Grid key={permission.id} item xs={6}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
data-testid="PermissionList-checkbox"
|
||||
checked={formik.values.permissions.includes(permission.id)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
formik.setFieldValue("permissions", [...formik.values.permissions, permission.id])
|
||||
} else {
|
||||
formik.setFieldValue("permissions", formik.values.permissions.filter((id) => id !== permission.id))
|
||||
}
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={permission.name_fa}
|
||||
/>
|
||||
}
|
||||
label={permission.name_fa}
|
||||
/>
|
||||
</Grid>
|
||||
))
|
||||
) : null}
|
||||
</Grid>
|
||||
</Grid>
|
||||
))}
|
||||
</>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
</FormControl>
|
||||
</FormLabel>
|
||||
</Stack>
|
||||
|
||||
@@ -24,7 +24,7 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
|
||||
},
|
||||
onSubmit: (values, {setSubmitting}) => {
|
||||
const formData = new FormData();
|
||||
if (values.description != "") formData.append("description", values.description);
|
||||
if (values.description != "") formData.append("expert_description", values.description);
|
||||
if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
|
||||
|
||||
requestServer(`${CONFIRM_TRANSPORTATION_ASSISTANCE}/${rowId}`, 'post', {
|
||||
@@ -106,7 +106,7 @@ const ConfirmContent = ({rowId, mutate, setOpenConfirmDialog}) => {
|
||||
{t("ConfirmDialog.button-cancel")}
|
||||
</Button>
|
||||
<Button onClick={formik.handleSubmit} variant="contained" color="primary"
|
||||
disabled={formik.isSubmitting || !formik.dirty || !formik.isValid}>
|
||||
disabled={formik.isSubmitting}>
|
||||
{t("ConfirmDialog.button-confirm")}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
||||
@@ -29,7 +29,7 @@ const RejectContent = ({rowId, mutate, setOpenRejectDialog}) => {
|
||||
validationSchema,
|
||||
onSubmit: (values, {setSubmitting}) => {
|
||||
const formData = new FormData();
|
||||
formData.append("description", values.description);
|
||||
formData.append("expert_description", values.description);
|
||||
if (values.reject_img != null) formData.append("attachment", values.reject_img);
|
||||
|
||||
requestServer(`${REJECT_TRANSPORTATION_ASSISTANCE}/${rowId}`, 'post', {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import LinkRouting from "@/core/components/LinkRouting";
|
||||
import PasswordField from "@/core/components/PasswordField";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import {GET_USER_TOKEN} from "@/core/data/apiRoutes";
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
@@ -14,6 +13,7 @@ import * as Yup from "yup";
|
||||
import useDirection from "@/lib/app/hooks/useDirection";
|
||||
import SvgLogin from "@/core/components/svgs/SvgLogin";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
import PasswordField from "@/core/components/PasswordField";
|
||||
|
||||
const LoginComponent = () => {
|
||||
const t = useTranslations();
|
||||
|
||||
@@ -14,7 +14,6 @@ function DataTable(props) {
|
||||
const [columnFilters, setColumnFilters] = useState([]);
|
||||
const [sorting, setSorting] = useState(props.sorting || []);
|
||||
const [pagination, setPagination] = useState({pageIndex: 0, pageSize: 10});
|
||||
const [rowCount, setRowCount] = useState(0);
|
||||
const [columnFilterFns, setColumnFilterFns] = useState(() => {
|
||||
let output = {};
|
||||
const list = props.columns.map((item) => item.enableColumnFilter ? {[item.id]: item.filterFn} : {[item.id]: ""});
|
||||
@@ -34,8 +33,11 @@ function DataTable(props) {
|
||||
const tableLocalization = useMemo(() => languageList.find((item) => item.key == languageApp).tableLocalization, [languageApp, languageList]);
|
||||
|
||||
const fetchUrl = useMemo(() => {
|
||||
const url = new URL(props.tableUrl);
|
||||
url.searchParams.set("start", `${pagination.pageIndex * pagination.pageSize}`);
|
||||
const params = new URLSearchParams();
|
||||
params.set(
|
||||
"start",
|
||||
`${pagination.pageIndex * pagination.pageSize}`
|
||||
);
|
||||
const filters = columnFilters.map((filter) => {
|
||||
let datatype;
|
||||
for (const i in props.columns) {
|
||||
@@ -47,10 +49,10 @@ function DataTable(props) {
|
||||
...filter, fn: columnFilterFns[filter.id], datatype: datatype,
|
||||
};
|
||||
});
|
||||
url.searchParams.set("size", pagination.pageSize);
|
||||
url.searchParams.set("filters", JSON.stringify(filters ?? []));
|
||||
url.searchParams.set("sorting", JSON.stringify(sorting ?? []));
|
||||
return url;
|
||||
params.set("size", pagination.pageSize);
|
||||
params.set("filters", JSON.stringify(filters ?? []));
|
||||
params.set("sorting", JSON.stringify(sorting ?? []));
|
||||
return `${props.tableUrl}?${params}`;
|
||||
}, [props.tableUrl, columnFilters, columnFilterFns, pagination, sorting, props.columns,]);
|
||||
|
||||
const {data, isValidating, mutate} = useSWR(fetchUrl, (...args) =>
|
||||
|
||||
@@ -2,8 +2,8 @@ import DangerousIcon from "@mui/icons-material/Dangerous";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const ErrorNotification = (t, status, message) => {
|
||||
toast(
|
||||
const ErrorNotification = (pushToastList, notificationType, t, status, message) => {
|
||||
const toastId = toast(
|
||||
() => (
|
||||
<>
|
||||
<Box
|
||||
@@ -29,11 +29,13 @@ const ErrorNotification = (t, status, message) => {
|
||||
</>
|
||||
),
|
||||
{
|
||||
containerId: 'validation',
|
||||
autoClose: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
}
|
||||
);
|
||||
pushToastList(notificationType, toastId);
|
||||
};
|
||||
|
||||
export default ErrorNotification;
|
||||
export default ErrorNotification;
|
||||
@@ -1,12 +1,14 @@
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const PendingNotification = (t) => {
|
||||
toast(t("notifications.pending"), {
|
||||
const PendingNotification = (pushToastList, notificationType, t) => {
|
||||
const toastId = toast(t("notifications.pending"), {
|
||||
containerId: 'validation',
|
||||
autoClose: false,
|
||||
closeButton: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
});
|
||||
pushToastList(notificationType, toastId);
|
||||
};
|
||||
|
||||
export default PendingNotification;
|
||||
export default PendingNotification;
|
||||
@@ -2,8 +2,8 @@ import BeenhereIcon from "@mui/icons-material/Beenhere";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const SuccessNotification = (t, status) => {
|
||||
toast(
|
||||
const SuccessNotification = (pushToastList, notificationType, t, status) => {
|
||||
const toastId = toast(
|
||||
() => (
|
||||
<>
|
||||
<Box
|
||||
@@ -30,6 +30,7 @@ const SuccessNotification = (t, status) => {
|
||||
</>
|
||||
),
|
||||
{
|
||||
containerId: 'validation',
|
||||
autoClose: 3000,
|
||||
hideProgressBar: true,
|
||||
pauseOnHover: true,
|
||||
@@ -37,6 +38,7 @@ const SuccessNotification = (t, status) => {
|
||||
draggable: true,
|
||||
}
|
||||
);
|
||||
pushToastList(notificationType, toastId);
|
||||
};
|
||||
|
||||
export default SuccessNotification;
|
||||
export default SuccessNotification;
|
||||
@@ -26,6 +26,8 @@ const UploadFileNotification = (t) => {
|
||||
</>
|
||||
),
|
||||
{
|
||||
containerId: 'validation',
|
||||
toastId: 'upload',
|
||||
autoClose: 3000,
|
||||
hideProgressBar: true,
|
||||
pauseOnHover: true,
|
||||
@@ -35,4 +37,4 @@ const UploadFileNotification = (t) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default UploadFileNotification;
|
||||
export default UploadFileNotification;
|
||||
@@ -2,8 +2,8 @@ import ReportIcon from "@mui/icons-material/Report";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const WarningNotification = (t, status) => {
|
||||
toast(
|
||||
const WarningNotification = (pushToastList, notificationType, t, status) => {
|
||||
const toastId = toast(
|
||||
() => (
|
||||
<>
|
||||
<Box
|
||||
@@ -30,11 +30,13 @@ const WarningNotification = (t, status) => {
|
||||
</>
|
||||
),
|
||||
{
|
||||
containerId: 'validation',
|
||||
autoClose: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
}
|
||||
);
|
||||
pushToastList(notificationType, toastId);
|
||||
};
|
||||
|
||||
export default WarningNotification;
|
||||
export default WarningNotification;
|
||||
@@ -1,54 +1,27 @@
|
||||
import {toast} from "react-toastify";
|
||||
import ErrorNotification from "./ErrorNotification";
|
||||
import WarningNotification from "./WarningNotification";
|
||||
import SuccessNotification from "./SuccessNotification";
|
||||
import pendingNotification from "@/core/components/notifications/PendingNotification";
|
||||
import WarningNotification from "@/core/components/notifications/WarningNotification";
|
||||
import ErrorNotification from "@/core/components/notifications/ErrorNotification";
|
||||
import SuccessNotification from "@/core/components/notifications/SuccessNotification";
|
||||
|
||||
const Notifications = async (t, response) => {
|
||||
const {status, data} = response != undefined ? response : ""
|
||||
toast.dismiss();
|
||||
switch (status) {
|
||||
case 200:
|
||||
SuccessNotification(t, status);
|
||||
const Notifications = (pushToastList, notificationType, t, status, message) => {
|
||||
switch (notificationType) {
|
||||
case "pending":
|
||||
pendingNotification(pushToastList, notificationType, t);
|
||||
break;
|
||||
case 400:
|
||||
ErrorNotification(t, status);
|
||||
case "warning":
|
||||
WarningNotification(pushToastList, notificationType, t, status);
|
||||
break;
|
||||
case 401:
|
||||
ErrorNotification(t, status);
|
||||
case "error":
|
||||
if (message) {
|
||||
ErrorNotification(pushToastList, notificationType, t, status, message)
|
||||
} else {
|
||||
ErrorNotification(pushToastList, notificationType, t, status)
|
||||
}
|
||||
break;
|
||||
case 403:
|
||||
ErrorNotification(t, status);
|
||||
break;
|
||||
case 422:
|
||||
ErrorNotification(t, status, data.message);
|
||||
break;
|
||||
case 500:
|
||||
WarningNotification(t, status);
|
||||
break;
|
||||
case 503:
|
||||
WarningNotification(t, status);
|
||||
break;
|
||||
case 504:
|
||||
WarningNotification(t, status);
|
||||
break;
|
||||
default:
|
||||
toast(t("notifications.pending"), {
|
||||
autoClose: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
});
|
||||
case "success":
|
||||
SuccessNotification(pushToastList, notificationType, t, status);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
export default Notifications;
|
||||
|
||||
/*
|
||||
usage document
|
||||
|
||||
** for pending use ( Notifications( t, undefined) ) this before your request.
|
||||
** for success use ( Notifications( t, response) ) this inside .then() of your request.
|
||||
** for Error and Warning use ( Notifications( t, error.response) ) this inside .catche() of your request.
|
||||
|
||||
end usage document
|
||||
*/
|
||||
|
||||
@@ -1,45 +1,48 @@
|
||||
import ErrorNotification from "@/core/components/notifications/ErrorNotification";
|
||||
import WarningNotification from "@/core/components/notifications/WarningNotification";
|
||||
import {toast} from "react-toastify";
|
||||
import Notifications from "@/core/components/notifications";
|
||||
|
||||
export const errorSetting = (t, notification) => {
|
||||
if (notification) toast.dismiss();
|
||||
export const errorSetting = (dismissToastList, t, notification) => {
|
||||
if (notification) {
|
||||
dismissToastList(["pending", "warning", "error", "success"])
|
||||
}
|
||||
}
|
||||
|
||||
export const errorRequest = (t, notification) => {
|
||||
if (notification) toast.dismiss();
|
||||
}
|
||||
|
||||
export const errorResponse = (response, clearToken, t, notification) => {
|
||||
if (notification) toast.dismiss();
|
||||
if (isServerError(response.status)) {
|
||||
errorServer(response, t, notification)
|
||||
} else if (isClientError(response.status)) {
|
||||
errorClient(response, clearToken, t, notification)
|
||||
export const errorRequest = (dismissToastList, t, notification) => {
|
||||
if (notification) {
|
||||
dismissToastList(["pending", "warning", "error", "success"])
|
||||
}
|
||||
}
|
||||
|
||||
const errorServer = (response, t, notification) => {
|
||||
if (notification) WarningNotification(t, response.status);
|
||||
export const errorResponse = (pushToastList, dismissToastList, response, clearToken, t, notification) => {
|
||||
if (notification) {
|
||||
dismissToastList(["pending", "warning", "error", "success"])
|
||||
}
|
||||
if (isServerError(response.status)) {
|
||||
errorServer(pushToastList, response, t, notification)
|
||||
} else if (isClientError(response.status)) {
|
||||
errorClient(pushToastList, response, clearToken, t, notification)
|
||||
}
|
||||
}
|
||||
const errorClient = (response, clearToken, t, notification) => {
|
||||
|
||||
const errorServer = (pushToastList, response, t, notification) => {
|
||||
if (notification) Notifications(pushToastList, "warning", t, response.status);
|
||||
}
|
||||
const errorClient = (pushToastList, response, clearToken, t, notification) => {
|
||||
switch (response.status) {
|
||||
case 401:
|
||||
clearToken()
|
||||
if (notification) ErrorNotification(t, response.status)
|
||||
if (notification) Notifications(pushToastList, "error", t, response.status);
|
||||
break;
|
||||
case 422:
|
||||
if ('type' in response.data) {
|
||||
errorLogic(response, t, notification)
|
||||
errorLogic(pushToastList, response, t, notification)
|
||||
break;
|
||||
}
|
||||
errorValidation(response, t, notification)
|
||||
errorValidation(pushToastList, response, t, notification)
|
||||
break;
|
||||
case 429:
|
||||
if (notification) ErrorNotification(t, response.status)
|
||||
if (notification) Notifications(pushToastList, "error", t, response.status);
|
||||
break
|
||||
default:
|
||||
if (notification) ErrorNotification(t, response.status)
|
||||
if (notification) Notifications(pushToastList, "error", t, response.status);
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -47,16 +50,16 @@ const errorClient = (response, clearToken, t, notification) => {
|
||||
const isServerError = status => status >= 500 && status <= 599;
|
||||
const isClientError = status => status >= 400 && status <= 499;
|
||||
|
||||
const errorLogic = (response, t, notification) => {
|
||||
if (notification) ErrorNotification(t, response.status, response.data.message)
|
||||
const errorLogic = (pushToastList, response, t, notification) => {
|
||||
if (notification) Notifications(pushToastList, "error", t, response.status, response.data.message);
|
||||
}
|
||||
const errorValidation = (response, t, notification) => {
|
||||
const errorValidation = (pushToastList, response, t, notification) => {
|
||||
if (notification) {
|
||||
const errorsMap = Object.keys(response.data.errors)
|
||||
const errorsArray = response.data.errors
|
||||
|
||||
errorsMap.map((item, index) => {
|
||||
ErrorNotification(t, response.status, errorsArray[item][0]);
|
||||
Notifications(pushToastList, "error", t, response.status, errorsArray[item][0]);
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
import SuccessNotification from "@/core/components/notifications/SuccessNotification";
|
||||
import {toast} from "react-toastify";
|
||||
import Notifications from "@/core/components/notifications";
|
||||
|
||||
export const successRequest = (response, t, options) => {
|
||||
export const successRequest = (pushToastList, dismissToastList, response, t, options) => {
|
||||
if (options.notification && options.success.notification.show) {
|
||||
toast.dismiss();
|
||||
SuccessNotification(t, response.status)
|
||||
dismissToastList(["pending", "warning", "error", "success"])
|
||||
Notifications(pushToastList, "success", t, response.status);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import {FA_DATATABLE_LOCALIZATION} from "&/locales/fa/datatable";
|
||||
import {FA_CHART_LOCALIZATION} from "&/locales/fa/chart";
|
||||
import {useRouter} from "next/router";
|
||||
import {createContext, useEffect, useState} from "react";
|
||||
import useUser from "../hooks/useUser";
|
||||
import {FA_CHART_LOCALIZATION} from "&/locales/fa/chart";
|
||||
|
||||
export const LanguageContext = createContext();
|
||||
|
||||
@@ -20,7 +20,7 @@ export const LanguageProvider = ({children}) => {
|
||||
];
|
||||
const {user, userChangedLanguage, changeLanguageState} = useUser();
|
||||
const [languageIsReady, setLanguageIsReady] = useState(false);
|
||||
const [languageApp, setLanguageApp] = useState();
|
||||
const [languageApp, setLanguageApp] = useState(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE);
|
||||
const [directionApp, setDirectionApp] = useState(
|
||||
process.env.NEXT_PUBLIC_DEFAULT_DIRECTION
|
||||
);
|
||||
@@ -28,9 +28,7 @@ export const LanguageProvider = ({children}) => {
|
||||
useEffect(() => {
|
||||
const lang = localStorage.getItem("_language");
|
||||
|
||||
if (!lang && !languageApp) {
|
||||
setLanguageApp(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE);
|
||||
} else if (lang) {
|
||||
if (lang) {
|
||||
setLanguageApp(lang);
|
||||
}
|
||||
}, []);
|
||||
|
||||
37
src/lib/app/contexts/toast.jsx
Normal file
37
src/lib/app/contexts/toast.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import {createContext, useReducer} from "react";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
export const ToastContext = createContext()
|
||||
|
||||
const reducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case "PUSH":
|
||||
return {
|
||||
...state,
|
||||
[action.toast_type]: [...state[action.toast_type], action.toast_id]
|
||||
};
|
||||
case "DISMISS":
|
||||
action.toast_type.map((item) => {
|
||||
state[item].map((id) => {
|
||||
toast.dismiss(id);
|
||||
})
|
||||
state[item] = []
|
||||
});
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export const ToastProvider = ({children}) => {
|
||||
const [state, dispatch] = useReducer(reducer, {
|
||||
pending: [],
|
||||
error: [],
|
||||
warning: [],
|
||||
success: []
|
||||
});
|
||||
|
||||
return (
|
||||
<ToastContext.Provider value={{state, dispatch}}>
|
||||
{children}
|
||||
</ToastContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
import {GET_USER_ROUTE} from "@/core/data/apiRoutes";
|
||||
import axios from "axios";
|
||||
import {createContext, useCallback, useEffect, useReducer} from "react";
|
||||
import {errorRequest, errorResponse, errorSetting} from "@/core/utils/errorHandler";
|
||||
|
||||
const initialUser = {
|
||||
isAuth: false,
|
||||
@@ -78,13 +77,7 @@ export const UserProvider = ({children}) => {
|
||||
if (typeof callback === "function") callback(data);
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.response) {
|
||||
errorResponse(error.response, clearToken, null, false)
|
||||
} else if (error.request) {
|
||||
errorRequest(null, false)
|
||||
} else {
|
||||
errorSetting(null, false)
|
||||
}
|
||||
if (error.response.status === 401) clearToken()
|
||||
})
|
||||
},
|
||||
[state.token]
|
||||
|
||||
@@ -11,15 +11,16 @@ const usePermissions = () => {
|
||||
})
|
||||
};
|
||||
|
||||
const {data} = useSWR(GET_PERMISSIONS_LIST, fetcher, {
|
||||
const {data, isLoading} = useSWR(GET_PERMISSIONS_LIST, fetcher, {
|
||||
revalidateIfStale: false,
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: false
|
||||
revalidateOnReconnect: false,
|
||||
keepPreviousData : true
|
||||
})
|
||||
const permissions_list = data
|
||||
//swr config
|
||||
|
||||
// render data
|
||||
return {permissions_list}
|
||||
return {permissions_list, isLoading}
|
||||
}
|
||||
export default usePermissions;
|
||||
@@ -1,10 +1,11 @@
|
||||
import axios from "axios";
|
||||
import {successRequest} from "@/core/utils/succesHandler";
|
||||
import PendingNotification from "@/core/components/notifications/PendingNotification";
|
||||
import {useTranslations} from "next-intl";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import {errorRequest, errorResponse, errorSetting} from "@/core/utils/errorHandler";
|
||||
import useNetwork from "@/lib/app/hooks/useNetwork";
|
||||
import Notifications from "@/core/components/notifications";
|
||||
import useToast from "@/lib/app/hooks/useToast";
|
||||
|
||||
const defaultOptions = {
|
||||
auth: false, data: {}, requestOptions: {
|
||||
@@ -23,6 +24,7 @@ const useRequest = (initOptions) => {
|
||||
const network = useNetwork()
|
||||
const t = useTranslations()
|
||||
const {token, clearToken} = useUser()
|
||||
const {pushToastList, dismissToastList} = useToast();
|
||||
let _options = {...defaultOptions, ...initOptions}
|
||||
|
||||
function requestServer(url = '', method = 'get', options) {
|
||||
@@ -33,27 +35,30 @@ const useRequest = (initOptions) => {
|
||||
headers: {..._options.requestOptions.headers, authorization: `Bearer ${token}`}
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!network.online) {
|
||||
reject()
|
||||
return
|
||||
}
|
||||
if (_options.notification && _options.failed.notification.show && _options.pending) PendingNotification(t)
|
||||
if (_options.notification && _options.failed.notification.show && _options.pending) {
|
||||
dismissToastList(["pending", "warning", "error", "success"]);
|
||||
Notifications(pushToastList, "pending", t);
|
||||
}
|
||||
|
||||
axios({
|
||||
url: url, method: method, data: _options.data, ..._options.requestOptions
|
||||
})
|
||||
.then(response => {
|
||||
successRequest(response, t, _options)
|
||||
successRequest(pushToastList, dismissToastList, response, t, _options)
|
||||
resolve(response)
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.response) {
|
||||
errorResponse(error.response, clearToken, t, _options.notification && _options.failed.notification.show)
|
||||
errorResponse(pushToastList, dismissToastList, error.response, clearToken, t, _options.notification && _options.failed.notification.show)
|
||||
} else if (error.request) {
|
||||
errorRequest(t, _options.notification && _options.failed.notification.show)
|
||||
errorRequest(dismissToastList, t, _options.notification && _options.failed.notification.show)
|
||||
} else {
|
||||
errorSetting(t, _options.notification && _options.failed.notification.show)
|
||||
errorSetting(dismissToastList, t, _options.notification && _options.failed.notification.show)
|
||||
}
|
||||
reject(error)
|
||||
})
|
||||
|
||||
21
src/lib/app/hooks/useToast.jsx
Normal file
21
src/lib/app/hooks/useToast.jsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import {useContext} from "react";
|
||||
import {ToastContext} from "@/lib/app/contexts/toast";
|
||||
|
||||
const useToast = () => {
|
||||
const {dispatch} = useContext(ToastContext);
|
||||
|
||||
const pushToastList = (toast_type, toast_id) => {
|
||||
dispatch({type: "PUSH", toast_type, toast_id});
|
||||
};
|
||||
|
||||
const dismissToastList = (toast_type) => {
|
||||
dispatch({type: "DISMISS", toast_type});
|
||||
};
|
||||
|
||||
return {
|
||||
pushToastList,
|
||||
dismissToastList
|
||||
}
|
||||
};
|
||||
|
||||
export default useToast;
|
||||
@@ -8,6 +8,7 @@ import "moment/locale/fa";
|
||||
import {NextIntlProvider} from "next-intl";
|
||||
import TitlePage from "@/core/components/TitlePage";
|
||||
import Layout from "@/layouts";
|
||||
import {ToastProvider} from "@/lib/app/contexts/toast";
|
||||
|
||||
const App = ({Component, pageProps}) => {
|
||||
|
||||
@@ -19,11 +20,13 @@ const App = ({Component, pageProps}) => {
|
||||
<MuiLayout isBot={pageProps.isBot}>
|
||||
{pageProps.messages ? <TitlePage text={pageProps.title}/> : ''}
|
||||
<LoadingProvider>
|
||||
<AppLayout isBot={pageProps.isBot}>
|
||||
<Layout layout={pageProps.layout}>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
</AppLayout>
|
||||
<ToastProvider>
|
||||
<AppLayout isBot={pageProps.isBot}>
|
||||
<Layout layout={pageProps.layout}>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
</AppLayout>
|
||||
</ToastProvider>
|
||||
</LoadingProvider>
|
||||
</MuiLayout>
|
||||
</NextIntlProvider>
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.change_password",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout'}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.commercial_chief_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_commercial_refahi"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.development_assistant_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_development_refahi"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.edit_profile",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout'}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,7 +14,8 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.expert_management",
|
||||
isBot,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_transportation_navgan"]}}
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_experts"]}}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.dashboard_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout'}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.inspector_expert_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_inspector_refahi"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.machinary_office_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_machinery_navgan"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.loan_management_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_navgan_loan"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.province_manager_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_province_affairs_navgan"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.passenger_boss_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_province_working_group_navgan"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.passenger_office_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_passenger_office_navgan"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.province_head_expert",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_province_headquarter_refahi"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.loan_management_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_refahi_loan"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.province_manager_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_province_affairs_refahi"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.role_management_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_roles"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.transportation_assistance",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_transportation_navgan"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.user_management_page",
|
||||
isBot,
|
||||
locale,
|
||||
layout: {name: 'DashboardLayout', props: {permissions: ["manage_users"]}}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ export async function getServerSideProps({req, locale}) {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Titles.title_login_expert_page",
|
||||
isBot,
|
||||
locale
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user