CFE-6 Merge branch 'bugfix/CFE-6_fix_toas_containers' into 'develop'
This commit is contained in:
@@ -196,6 +196,7 @@
|
||||
"name": "نام کامل",
|
||||
"username": "نام کاربری",
|
||||
"email": "پست الکترونیک",
|
||||
"telephone_id": "کد تلفن",
|
||||
"phone_number": "شماره همراه",
|
||||
"national_id": "کد ملی",
|
||||
"position": "سمت",
|
||||
@@ -205,7 +206,7 @@
|
||||
"male": "مرد",
|
||||
"female": "زن",
|
||||
"updated_at": "آخرین بروزرسانی",
|
||||
"create": "افزودن کارشناس",
|
||||
"create": "افزودن",
|
||||
"personal_info": "مشخصات کارشناس",
|
||||
"user_info": "اطلاعات کاربری",
|
||||
"rest_info": "اطلاعات تکمیلی",
|
||||
|
||||
@@ -7,19 +7,18 @@ import * as Yup from "yup";
|
||||
import {Field, Formik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
import AvatarUpload from "@/core/components/AvatarUpload";
|
||||
import axios from "axios";
|
||||
import {UPDATE_AVATAR} from "@/core/data/apiRoutes";
|
||||
import useDirection from "@/lib/app/hooks/useDirection";
|
||||
import Notifications from "@/core/components/notifications";
|
||||
import ImageResizer from "@/core/components/ImageConvertor";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
|
||||
const DashboardEditProfile = () => {
|
||||
const t = useTranslations();
|
||||
const requestServer = useRequest({auth: true})
|
||||
const {user, token, getUser, changeUser} = useUser();
|
||||
const {directionApp} = useDirection();
|
||||
|
||||
const editAvatar = async (avatar) => {
|
||||
Notifications(t);
|
||||
try {
|
||||
const formData = new FormData();
|
||||
|
||||
@@ -28,15 +27,12 @@ const DashboardEditProfile = () => {
|
||||
resizedAvatar = await ImageResizer(avatar);
|
||||
formData.append("avatar", resizedAvatar);
|
||||
}
|
||||
|
||||
await axios.post(UPDATE_AVATAR, formData, {
|
||||
headers: {
|
||||
authorization: `Bearer ${token}`,
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
});
|
||||
await requestServer(UPDATE_AVATAR, 'post', {formData}).then((response) => {
|
||||
})
|
||||
.catch(() => {
|
||||
}).finally(() => {
|
||||
});
|
||||
} catch (error) {
|
||||
Notifications(t, error.response);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -99,11 +95,7 @@ const DashboardEditProfile = () => {
|
||||
margin="normal"
|
||||
size="small"
|
||||
disabled={true}
|
||||
error={
|
||||
props.touched.username && props.errors.username
|
||||
? true
|
||||
: false
|
||||
}
|
||||
error={!!(props.touched.username && props.errors.username)}
|
||||
helperText={
|
||||
props.touched.username
|
||||
? props.errors.username
|
||||
@@ -123,11 +115,7 @@ const DashboardEditProfile = () => {
|
||||
margin="normal"
|
||||
size="small"
|
||||
disabled={true}
|
||||
error={
|
||||
props.touched.name && props.errors.name
|
||||
? true
|
||||
: false
|
||||
}
|
||||
error={!!(props.touched.name && props.errors.name)}
|
||||
helperText={
|
||||
props.touched.name ? props.errors.name : null
|
||||
}
|
||||
@@ -145,11 +133,7 @@ const DashboardEditProfile = () => {
|
||||
margin="normal"
|
||||
size="small"
|
||||
disabled={true}
|
||||
error={
|
||||
props.touched.email && props.errors.email
|
||||
? true
|
||||
: false
|
||||
}
|
||||
error={!!(props.touched.email && props.errors.email)}
|
||||
helperText={
|
||||
props.touched.email ? props.errors.email : null
|
||||
}
|
||||
@@ -168,12 +152,7 @@ const DashboardEditProfile = () => {
|
||||
margin="normal"
|
||||
size="small"
|
||||
disabled={true}
|
||||
error={
|
||||
props.touched.province_name &&
|
||||
props.errors.province_name
|
||||
? true
|
||||
: false
|
||||
}
|
||||
error={!!(props.touched.province_name && props.errors.province_name)}
|
||||
helperText={
|
||||
props.touched.province_name
|
||||
? props.errors.province_name
|
||||
@@ -193,11 +172,7 @@ const DashboardEditProfile = () => {
|
||||
margin="normal"
|
||||
size="small"
|
||||
disabled={true}
|
||||
error={
|
||||
props.touched.position && props.errors.position
|
||||
? true
|
||||
: false
|
||||
}
|
||||
error={!!(props.touched.position && props.errors.position)}
|
||||
helperText={
|
||||
props.touched.position
|
||||
? props.errors.position
|
||||
|
||||
@@ -10,6 +10,7 @@ describe("ExpertManagementDatatable Component From Expert Management", () => {
|
||||
const nameHeader = screen.queryByText("نام کامل");
|
||||
const usernameHeader = screen.queryByText("نام کاربری");
|
||||
const emailHeader = screen.queryByText("پست الکترونیک");
|
||||
const telephone_idHeader = screen.queryByText("کد تلفن");
|
||||
const phone_numberHeader = screen.queryByText("شماره همراه");
|
||||
const national_idHeader = screen.queryByText("کد ملی");
|
||||
const positionHeader = screen.queryByText("سمت");
|
||||
@@ -21,6 +22,7 @@ describe("ExpertManagementDatatable Component From Expert Management", () => {
|
||||
expect(nameHeader).toBeInTheDocument();
|
||||
expect(usernameHeader).toBeInTheDocument();
|
||||
expect(emailHeader).toBeInTheDocument();
|
||||
expect(telephone_idHeader).toBeInTheDocument();
|
||||
expect(phone_numberHeader).toBeInTheDocument();
|
||||
expect(national_idHeader).toBeInTheDocument();
|
||||
expect(positionHeader).toBeInTheDocument();
|
||||
|
||||
@@ -67,6 +67,18 @@ function ExpertManagementDataTable() {
|
||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => row.telephone_id,
|
||||
id: "telephone_id",
|
||||
header: t("ExpertMangement.telephone_id"),
|
||||
enableColumnFilter: true,
|
||||
datatype: "numeric",
|
||||
filterFn: "equals",
|
||||
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
||||
Cell: ({renderedCellValue}) => (
|
||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => row.phone_number,
|
||||
id: "phone_number",
|
||||
|
||||
@@ -18,22 +18,22 @@ describe("CreateForm Component From Expert Management", () => {
|
||||
describe("Rendering", () => {
|
||||
it("Create Button Rendered", () => {
|
||||
render(<MockAppWithProviders><CreateForm/></MockAppWithProviders>);
|
||||
const CreateButton = screen.getByRole('button', {name: "افزودن کارشناس"});
|
||||
const CreateButton = screen.getByRole('button', {name: "افزودن"});
|
||||
expect(CreateButton).toBeInTheDocument();
|
||||
});
|
||||
it("Dialog Header Rendered", () => {
|
||||
render(<MockAppWithProviders><CreateForm/></MockAppWithProviders>);
|
||||
const CreateDialogHeader = screen.queryByText("افزودن کارشناس");
|
||||
const CreateDialogHeader = screen.queryByText("افزودن");
|
||||
expect(CreateDialogHeader).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
describe("Behavioral", () => {
|
||||
it("by Clicking Create Button Dialog Should Append To Document", async () => {
|
||||
render(<MockAppWithProviders><CreateForm/></MockAppWithProviders>);
|
||||
const CreateButton = screen.getByRole('button', {name: "افزودن کارشناس"});
|
||||
const CreateButton = screen.getByRole('button', {name: "افزودن"});
|
||||
fireEvent.click(CreateButton);
|
||||
await act(() => {
|
||||
const CreateDialog = screen.getByRole('dialog', {name: "افزودن کارشناس"})
|
||||
const CreateDialog = screen.getByRole('dialog', {name: "افزودن"})
|
||||
expect(CreateDialog).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -42,7 +42,7 @@ describe("CreateForm Component From Expert Management", () => {
|
||||
it('Should request to api and if get success close dialog', async () => {
|
||||
render(<MockAppWithProviders><CreateForm/></MockAppWithProviders>);
|
||||
|
||||
const CreateButton = screen.getByRole('button', {name: "افزودن کارشناس"});
|
||||
const CreateButton = screen.getByRole('button', {name: "افزودن"});
|
||||
fireEvent.click(CreateButton);
|
||||
|
||||
const submitButton = screen.queryByText('ثبت');
|
||||
@@ -80,7 +80,7 @@ describe("CreateForm Component From Expert Management", () => {
|
||||
it('Should request to api and if get error keep previous data', async () => {
|
||||
render(<MockAppWithProviders><CreateForm/></MockAppWithProviders>);
|
||||
|
||||
const CreateButton = screen.getByRole('button', {name: "افزودن کارشناس"});
|
||||
const CreateButton = screen.getByRole('button', {name: "افزودن"});
|
||||
fireEvent.click(CreateButton);
|
||||
|
||||
const submitButton = screen.queryByText('ثبت');
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -26,6 +26,8 @@ const UploadFileNotification = (t) => {
|
||||
</>
|
||||
),
|
||||
{
|
||||
containerId: 'validation',
|
||||
toastId: 'upload',
|
||||
autoClose: 3000,
|
||||
hideProgressBar: true,
|
||||
pauseOnHover: true,
|
||||
|
||||
@@ -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;
|
||||
@@ -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, errorsArray[item][0], response.data.message);
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -41,16 +41,22 @@ function AppLayout({children, isBot}) {
|
||||
if (!languageIsReady) return;
|
||||
}
|
||||
|
||||
return (<>
|
||||
<GlobalHead/>
|
||||
<NextNProgress
|
||||
color={theme.palette.secondary.dark}
|
||||
options={{showSpinner: false}}
|
||||
/>
|
||||
<ToastContainer position={directionApp === "ltr" ? "top-left" : "top-right"} rtl={directionApp === 'rtl'}/>
|
||||
<NetworkComponent/>
|
||||
{children}
|
||||
</>);
|
||||
return (
|
||||
<>
|
||||
<GlobalHead/>
|
||||
<NextNProgress
|
||||
color={theme.palette.secondary.dark}
|
||||
options={{showSpinner: false}}
|
||||
/>
|
||||
<ToastContainer
|
||||
enableMultiContainer
|
||||
containerId="validation"
|
||||
position={directionApp === "ltr" ? "top-left" : "top-right"}
|
||||
rtl={directionApp === 'rtl'}/>
|
||||
<NetworkComponent/>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default AppLayout;
|
||||
|
||||
@@ -2,9 +2,10 @@ import {createContext, useEffect, useMemo, useRef, useState} from "react";
|
||||
import {io} from "socket.io-client";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {toast} from "react-toastify";
|
||||
import {toast, ToastContainer} from "react-toastify";
|
||||
import PowerIcon from "@mui/icons-material/Power";
|
||||
import PowerOffIcon from "@mui/icons-material/PowerOff";
|
||||
import useDirection from "@/lib/app/hooks/useDirection";
|
||||
|
||||
export const SocketContext = createContext()
|
||||
|
||||
@@ -13,6 +14,7 @@ export const SocketProvider = ({children}) => {
|
||||
const [connectionError, setConnectionError] = useState(false)
|
||||
const socketToastId = useRef(null);
|
||||
const t = useTranslations()
|
||||
const {directionApp} = useDirection();
|
||||
const socket = useMemo(() => io(process.env.NEXT_PUBLIC_SERVER_SOCKET_URL, {
|
||||
autoConnect: false,
|
||||
transports: ['websocket'],
|
||||
@@ -58,11 +60,20 @@ export const SocketProvider = ({children}) => {
|
||||
return
|
||||
}
|
||||
socketToastId.current = toast.warn(t('socket_is_not_connect_message'), {
|
||||
containerId: 'socket',
|
||||
draggable: false,
|
||||
autoClose: false, closeButton: false, closeOnClick: false, icon: <PowerOffIcon/>
|
||||
})
|
||||
|
||||
}, [connectionError]);
|
||||
|
||||
return <SocketContext.Provider value={{socket}}>{children}</SocketContext.Provider>
|
||||
return (
|
||||
<SocketContext.Provider value={{socket}}>
|
||||
<ToastContainer
|
||||
enableMultiContainer containerId={'socket'}
|
||||
position={directionApp === "ltr" ? "top-right" : "top-left"}
|
||||
rtl={directionApp === 'rtl'}/>
|
||||
{children}
|
||||
</SocketContext.Provider>
|
||||
)
|
||||
}
|
||||
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,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,21 +8,24 @@ import "moment/locale/fa";
|
||||
import {NextIntlProvider} from "next-intl";
|
||||
import TitlePage from "@/core/components/TitlePage";
|
||||
import {SocketProvider} from "@/lib/app/contexts/socket";
|
||||
import {ToastProvider} from "@/lib/app/contexts/toast";
|
||||
|
||||
const App = ({Component, pageProps}) => {
|
||||
|
||||
return (<>
|
||||
<UserProvider>
|
||||
<LanguageProvider>
|
||||
<NextIntlProvider locale = {pageProps.locale} messages = {pageProps.messages || {}}>
|
||||
<MuiLayout isBot = {pageProps.isBot}>
|
||||
{pageProps.messages ? <TitlePage text = {pageProps.title}/> : ''}
|
||||
<NextIntlProvider locale={pageProps.locale} messages={pageProps.messages || {}}>
|
||||
<MuiLayout isBot={pageProps.isBot}>
|
||||
{pageProps.messages ? <TitlePage text={pageProps.title}/> : ''}
|
||||
<LoadingProvider>
|
||||
<AppLayout isBot = {pageProps.isBot}>
|
||||
<SocketProvider>
|
||||
<Component {...pageProps} />
|
||||
</SocketProvider>
|
||||
</AppLayout>
|
||||
<ToastProvider>
|
||||
<AppLayout isBot={pageProps.isBot}>
|
||||
<SocketProvider>
|
||||
<Component {...pageProps} />
|
||||
</SocketProvider>
|
||||
</AppLayout>
|
||||
</ToastProvider>
|
||||
</LoadingProvider>
|
||||
</MuiLayout>
|
||||
</NextIntlProvider>
|
||||
|
||||
Reference in New Issue
Block a user