Merge branch 'develop' into 'feature/debug_forms'
# Conflicts: # src/components/dashboard/machinary-office/TableRowActions.jsx # src/components/dashboard/passenger-boss/TableRowActions.jsx # src/components/dashboard/passenger-office/TableRowActions.jsx # src/components/dashboard/province-manager/TableRowActions.jsx # src/components/dashboard/transportation-assistance/TableRowActions.jsx
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
NEXT_PUBLIC_API_NAME = "Loan Facilities Dashboard"
|
||||
NEXT_PUBLIC_API_VERSION = "1.0.0"
|
||||
NEXT_PUBLIC_DEFAULT_LANGUAGE = "fa"
|
||||
NEXT_PUBLIC_DEFAULT_DIRECTION = "rtl"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ const DashboardChangePasswordComponent = () => {
|
||||
const {directionApp} = useDirection();
|
||||
|
||||
const handleSubmit = (values, {setSubmitting, resetForm}) => {
|
||||
Notifications(directionApp, t);
|
||||
Notifications(t);
|
||||
axios
|
||||
.post(
|
||||
CHANGE_PASSWORD,
|
||||
@@ -35,12 +35,12 @@ const DashboardChangePasswordComponent = () => {
|
||||
)
|
||||
.then((response) => {
|
||||
toast.dismiss(pendingToast); // Dismiss the pending toast notification
|
||||
Notifications(directionApp, t, response);
|
||||
Notifications(t, response);
|
||||
resetForm();
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.dismiss(pendingToast); // Dismiss the pending toast notification
|
||||
Notifications(directionApp, t, error.response);
|
||||
Notifications(t, error.response);
|
||||
})
|
||||
.finally(() => {
|
||||
setSubmitting(false); // Set `setSubmitting` to false after the API request completes
|
||||
|
||||
@@ -20,7 +20,7 @@ const DashboardEditProfile = () => {
|
||||
const {directionApp} = useDirection();
|
||||
|
||||
const editAvatar = async (avatar) => {
|
||||
Notifications(directionApp, t);
|
||||
Notifications(t);
|
||||
try {
|
||||
const formData = new FormData();
|
||||
|
||||
@@ -37,7 +37,7 @@ const DashboardEditProfile = () => {
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
Notifications(directionApp, t, error.response);
|
||||
Notifications(t, error.response);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -55,13 +55,13 @@ const DashboardEditProfile = () => {
|
||||
// });
|
||||
// })
|
||||
// .then((response) => {
|
||||
// Notifications(directionApp, t, response);
|
||||
// Notifications( t, response);
|
||||
// getUser((data) => {
|
||||
// changeUser(data);
|
||||
// });
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// Notifications(directionApp, t, error.response);
|
||||
// Notifications( t, error.response);
|
||||
// })
|
||||
// .finally(() => {
|
||||
// setSubmitting(false);
|
||||
@@ -75,13 +75,13 @@ const DashboardEditProfile = () => {
|
||||
// },
|
||||
// })
|
||||
// .then((response) => {
|
||||
// Notifications(directionApp, t, response);
|
||||
// Notifications( t, response);
|
||||
// getUser((data) => {
|
||||
// changeUser(data);
|
||||
// });
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// Notifications(directionApp, t, error.response);
|
||||
// Notifications( t, error.response);
|
||||
// })
|
||||
// .finally(() => {
|
||||
// setSubmitting(false);
|
||||
|
||||
@@ -2,9 +2,10 @@ import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import {Button, Typography} from "@mui/material";
|
||||
import {Button, Stack, Typography} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import SvgDashboard from "@/core/components/svgs/SvgDashboard";
|
||||
import process from "next/dist/build/webpack/loaders/resolve-url-loader/lib/postcss";
|
||||
|
||||
const FirstComponent = () => {
|
||||
const t = useTranslations();
|
||||
@@ -40,6 +41,14 @@ const FirstComponent = () => {
|
||||
</Button>
|
||||
)}
|
||||
</CenterLayout>
|
||||
<Stack direction="row" alignItems="center" justifyContent="center">
|
||||
<Typography variant={"caption"}
|
||||
sx={{
|
||||
color: 'primary.main',
|
||||
fontFamily: 'Arial',
|
||||
fontWeight: 'bold'
|
||||
}}>v{process.env.NEXT_PUBLIC_API_VERSION}</Typography>
|
||||
</Stack>
|
||||
</FullPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import LinkRouting from "@/core/components/LinkRouting";
|
||||
import Notifications from "@/core/components/notifications";
|
||||
import PasswordField from "@/core/components/PasswordField";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import {GET_USER_TOKEN} from "@/core/data/apiRoutes";
|
||||
@@ -8,38 +7,39 @@ import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import LoginIcon from "@mui/icons-material/Login";
|
||||
import {Box, Button, Container, Paper, Stack, TextField, Typography,} from "@mui/material";
|
||||
import axios from "axios";
|
||||
import {Field, Formik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {useSearchParams} from "next/navigation";
|
||||
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";
|
||||
|
||||
const LoginComponent = () => {
|
||||
const t = useTranslations();
|
||||
const {directionApp} = useDirection(); // should delete because we don't have direction anymore
|
||||
const {setToken} = useUser(); // pass token to set token
|
||||
const requestServer = useRequest()
|
||||
|
||||
// getting url query
|
||||
const searchParams = useSearchParams();
|
||||
const backUrlDecodedPath = searchParams.get("back_url");
|
||||
|
||||
//formik properties
|
||||
const handleSubmit = async (values, props) => {
|
||||
Notifications(directionApp, t);
|
||||
await axios
|
||||
.post(GET_USER_TOKEN, {
|
||||
const handleSubmit = (values, props) => {
|
||||
requestServer(GET_USER_TOKEN, 'post', {
|
||||
data: {
|
||||
username: values.username,
|
||||
password: values.password,
|
||||
})
|
||||
.then(function (response) {
|
||||
setToken(response.data.token);
|
||||
})
|
||||
.catch(function (error) {
|
||||
Notifications(directionApp, t, error.response);
|
||||
props.setSubmitting(false);
|
||||
});
|
||||
},
|
||||
success: {
|
||||
notification: {show: false}
|
||||
}
|
||||
}).then((response) => {
|
||||
setToken(response.data.token)
|
||||
}).catch(() => {
|
||||
props.setSubmitting(false)
|
||||
})
|
||||
};
|
||||
const initialValues = {
|
||||
username: "",
|
||||
@@ -120,7 +120,7 @@ const LoginComponent = () => {
|
||||
fullWidth
|
||||
size="medium"
|
||||
endIcon={<LoginIcon/>}
|
||||
disabled={props.isSubmitting ? true : false}
|
||||
disabled={props.isSubmitting}
|
||||
>
|
||||
{t("LoginPage.button_submit")}
|
||||
</Button>
|
||||
|
||||
@@ -2,7 +2,7 @@ import DangerousIcon from "@mui/icons-material/Dangerous";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const ErrorNotification = (directionApp, t, status, message) => {
|
||||
const ErrorNotification = (t, status, message) => {
|
||||
toast(
|
||||
() => (
|
||||
<>
|
||||
@@ -29,7 +29,6 @@ const ErrorNotification = (directionApp, t, status, message) => {
|
||||
</>
|
||||
),
|
||||
{
|
||||
position: directionApp === "ltr" ? "top-left" : "top-right",
|
||||
autoClose: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
|
||||
11
src/core/components/notifications/PendingNotification.jsx
Normal file
11
src/core/components/notifications/PendingNotification.jsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const PendingNotification = (t) => {
|
||||
toast(t("notifications.pending"), {
|
||||
autoClose: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
});
|
||||
};
|
||||
|
||||
export default PendingNotification;
|
||||
@@ -2,7 +2,7 @@ import BeenhereIcon from "@mui/icons-material/Beenhere";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const SuccessNotification = (directionApp, t, status) => {
|
||||
const SuccessNotification = (t, status) => {
|
||||
toast(
|
||||
() => (
|
||||
<>
|
||||
@@ -30,7 +30,6 @@ const SuccessNotification = (directionApp, t, status) => {
|
||||
</>
|
||||
),
|
||||
{
|
||||
position: directionApp === "ltr" ? "top-left" : "top-right",
|
||||
autoClose: 3000,
|
||||
hideProgressBar: true,
|
||||
pauseOnHover: true,
|
||||
|
||||
@@ -2,7 +2,7 @@ import DangerousIcon from "@mui/icons-material/Dangerous";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const UploadFileNotification = (directionApp, t) => {
|
||||
const UploadFileNotification = (t) => {
|
||||
toast(
|
||||
({closeToast}) => (
|
||||
<>
|
||||
@@ -26,7 +26,6 @@ const UploadFileNotification = (directionApp, t) => {
|
||||
</>
|
||||
),
|
||||
{
|
||||
position: directionApp === "ltr" ? "top-left" : "top-right",
|
||||
autoClose: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
|
||||
@@ -2,7 +2,7 @@ import ReportIcon from "@mui/icons-material/Report";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const WarningNotification = (directionApp, t, status) => {
|
||||
const WarningNotification = (t, status) => {
|
||||
toast(
|
||||
() => (
|
||||
<>
|
||||
@@ -30,7 +30,6 @@ const WarningNotification = (directionApp, t, status) => {
|
||||
</>
|
||||
),
|
||||
{
|
||||
position: directionApp === "ltr" ? "top-left" : "top-right",
|
||||
autoClose: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
|
||||
@@ -3,37 +3,36 @@ import ErrorNotification from "./ErrorNotification";
|
||||
import WarningNotification from "./WarningNotification";
|
||||
import SuccessNotification from "./SuccessNotification";
|
||||
|
||||
const Notifications = async (directionApp, t, response) => {
|
||||
const Notifications = async (t, response) => {
|
||||
const {status, data} = response != undefined ? response : ""
|
||||
toast.dismiss();
|
||||
switch (status) {
|
||||
case 200:
|
||||
SuccessNotification(directionApp, t, status);
|
||||
SuccessNotification(t, status);
|
||||
break;
|
||||
case 400:
|
||||
ErrorNotification(directionApp, t, status);
|
||||
ErrorNotification(t, status);
|
||||
break;
|
||||
case 401:
|
||||
ErrorNotification(directionApp, t, status);
|
||||
ErrorNotification(t, status);
|
||||
break;
|
||||
case 403:
|
||||
ErrorNotification(directionApp, t, status);
|
||||
ErrorNotification(t, status);
|
||||
break;
|
||||
case 422:
|
||||
ErrorNotification(directionApp, t, status, data.message);
|
||||
ErrorNotification(t, status, data.message);
|
||||
break;
|
||||
case 500:
|
||||
WarningNotification(directionApp, t, status);
|
||||
WarningNotification(t, status);
|
||||
break;
|
||||
case 503:
|
||||
WarningNotification(directionApp, t, status);
|
||||
WarningNotification(t, status);
|
||||
break;
|
||||
case 504:
|
||||
WarningNotification(directionApp, t, status);
|
||||
WarningNotification(t, status);
|
||||
break;
|
||||
default:
|
||||
toast(t("notifications.pending"), {
|
||||
position: directionApp === "ltr" ? "top-left" : "top-right",
|
||||
autoClose: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
@@ -47,9 +46,9 @@ export default Notifications;
|
||||
/*
|
||||
usage document
|
||||
|
||||
** for pending use ( Notifications(directionApp, t, undefined) ) this before your request.
|
||||
** for success use ( Notifications(directionApp, t, response) ) this inside .then() of your request.
|
||||
** for Error and Warning use ( Notifications(directionApp, t, error.response) ) this inside .catche() of your request.
|
||||
** 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
|
||||
*/
|
||||
|
||||
62
src/core/utils/errorHandler.js
Normal file
62
src/core/utils/errorHandler.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import ErrorNotification from "@/core/components/notifications/ErrorNotification";
|
||||
import WarningNotification from "@/core/components/notifications/WarningNotification";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
export const errorSetting = (t, notification) => {
|
||||
//todo
|
||||
}
|
||||
|
||||
export const errorRequest = (t, notification) => {
|
||||
//todo
|
||||
}
|
||||
|
||||
export const errorResponse = (response, clearToken, t, notification) => {
|
||||
toast.dismiss();
|
||||
if (isServerError(response.status)) {
|
||||
errorServer(response, t, notification)
|
||||
} else if (isClientError(response.status)) {
|
||||
errorClient(response, clearToken, t, notification)
|
||||
}
|
||||
}
|
||||
|
||||
const errorServer = (response, t, notification) => {
|
||||
if (notification) WarningNotification(t, response.status);
|
||||
}
|
||||
const errorClient = (response, clearToken, t, notification) => {
|
||||
switch (response.status) {
|
||||
case 401:
|
||||
clearToken()
|
||||
if (notification) ErrorNotification(t, response.status)
|
||||
break;
|
||||
case 422:
|
||||
if ('type' in response.data) {
|
||||
errorLogic(response, t, notification)
|
||||
break;
|
||||
}
|
||||
errorValidation(response, t, notification)
|
||||
break;
|
||||
case 429:
|
||||
if (notification) ErrorNotification(t, response.status)
|
||||
break
|
||||
default:
|
||||
if (notification) ErrorNotification(t, response.status)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
const errorValidation = (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]);
|
||||
})
|
||||
}
|
||||
}
|
||||
9
src/core/utils/succesHandler.js
Normal file
9
src/core/utils/succesHandler.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import SuccessNotification from "@/core/components/notifications/SuccessNotification";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
export const successRequest = (response, t, options) => {
|
||||
toast.dismiss();
|
||||
if (options.notification && options.success.notification.show) {
|
||||
SuccessNotification(t, response.status)
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ const theme = {
|
||||
MuiBackdrop: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: "#02020226", // Replace with your desired backdrop color and opacity
|
||||
backgroundColor: colord(process.env.NEXT_PUBLIC_PRIMARY_MAIN).darken(0.2).alpha(0.7).toHex(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -96,7 +96,7 @@ function AppLayout({children, isBot}) {
|
||||
color={theme.palette.secondary.dark}
|
||||
options={{showSpinner: false}}
|
||||
/>
|
||||
{directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
|
||||
<ToastContainer position={directionApp === "ltr" ? "top-left" : "top-right"} rtl={directionApp === 'rtl'}/>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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,
|
||||
@@ -75,7 +76,16 @@ export const UserProvider = ({children}) => {
|
||||
})
|
||||
.then(({data}) => {
|
||||
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)
|
||||
}
|
||||
})
|
||||
},
|
||||
[state.token]
|
||||
);
|
||||
|
||||
59
src/lib/app/hooks/useRequest.jsx
Normal file
59
src/lib/app/hooks/useRequest.jsx
Normal file
@@ -0,0 +1,59 @@
|
||||
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";
|
||||
|
||||
const defaultOptions = {
|
||||
data: {},
|
||||
requestOptions: {},
|
||||
notification: true,
|
||||
pending: true,
|
||||
success: {
|
||||
notification: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
failed: {
|
||||
notification: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
const useRequest = (initOptions) => {
|
||||
const t = useTranslations()
|
||||
const {clearToken} = useUser()
|
||||
let _options = {...defaultOptions, ...initOptions}
|
||||
|
||||
function requestServer(url = '', method = 'get', options) {
|
||||
_options = {..._options, ...options}
|
||||
return new Promise((resolve, reject) => {
|
||||
if (_options.notification && _options.failed.notification.show && _options.pending) PendingNotification(t)
|
||||
axios({
|
||||
url: url,
|
||||
method: method,
|
||||
data: _options.data,
|
||||
..._options.requestOptions
|
||||
})
|
||||
.then(response => {
|
||||
successRequest(response, t, _options)
|
||||
resolve(response)
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.response) {
|
||||
errorResponse(error.response, clearToken, t, _options.notification && _options.failed.notification.show)
|
||||
} else if (error.request) {
|
||||
errorRequest(t, _options.notification && _options.failed.notification.show)
|
||||
} else {
|
||||
errorSetting(t, _options.notification && _options.failed.notification.show)
|
||||
}
|
||||
reject(error)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
return requestServer
|
||||
}
|
||||
|
||||
export default useRequest
|
||||
Reference in New Issue
Block a user