TF-102 Merge branch 'bugfix/TF-102_fixed_bug' into 'develop'
This commit is contained in:
BIN
public/icons/favicon.png
Normal file
BIN
public/icons/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
@@ -15,6 +15,8 @@
|
||||
"Resend_code_in": "ارسال مجدد کد در",
|
||||
"seconds_later": "ثانیه دیگر",
|
||||
"upload_file_text": "بارگذاری فایل",
|
||||
"online_message": "شما به اینترنت وصل هستید",
|
||||
"offline_message": "اتصال شما به اینترنت قطع شده است",
|
||||
"header": {
|
||||
"open_profile": "پروفایل",
|
||||
"edit_profile": "ویرایش پروفایل",
|
||||
@@ -111,7 +113,8 @@
|
||||
"loan_follow_up_page": "پیگیری درخواست",
|
||||
"loan_request_correction": "اصلاح درخواست",
|
||||
"loan_request_detail": "مشاهده جزئیات",
|
||||
"request_number": "درخواست شماره"
|
||||
"request_number": "درخواست شماره",
|
||||
"no_request_found": "درخواستی یافت نشد"
|
||||
},
|
||||
"LoanRequest": {
|
||||
"loan_request_page": "ثبت درخواست وام",
|
||||
@@ -132,6 +135,8 @@
|
||||
"text_field_vehicle_type": "نام وسیله نقلیه",
|
||||
"text_field_enter_your_vehicle_type": "نام وسیله نقلیه خود را وارد کنید",
|
||||
"text_field_province": "استان",
|
||||
"text_field_loading_provinces_list": "درحال دریافت استان ها",
|
||||
"text_field_error_fetching_provinces": "خطا در دریافت استان ها",
|
||||
"text_field_enter_your_province": "استان خود را وارد کنید",
|
||||
"text_field_navgan_id": "شماره ناوگان",
|
||||
"text_field_enter_your_navgan_id": "شماره ناوگان خود را وارد کنید",
|
||||
|
||||
57
public/manifest.json
Normal file
57
public/manifest.json
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"short_name": "Loan Facilities Dashboard",
|
||||
"name": "Loan Facilities User Dashboard",
|
||||
"description": "Loan Facilities",
|
||||
"version": "1.0.0",
|
||||
"version_name": "1.0.0 beta",
|
||||
"start_url": "/dashboard",
|
||||
"orientation": "portrait",
|
||||
"display": "standalone",
|
||||
"theme_color": "#084070",
|
||||
"background_color": "#084070",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icons/maskable_icon.png",
|
||||
"sizes": "any",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/maskable_icon_x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/maskable_icon_x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/maskable_icon_x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/maskable_icon_x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/maskable_icon_x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/maskable_icon_x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/maskable_icon_x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
"government"
|
||||
]
|
||||
}
|
||||
@@ -1,39 +1,30 @@
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import UploadSystem from "@/core/components/UploadSystem";
|
||||
import {GET_PROVINCE_LIST, SEND_LOAN_REQUEST_WELFARE} from "@/core/data/apiRoutes";
|
||||
import useDirection from "@/lib/app/hooks/useDirection";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import {SEND_LOAN_REQUEST_WELFARE} from "@/core/data/apiRoutes";
|
||||
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
|
||||
import {Box, Button, Chip, Divider, Stack, TextField} from "@mui/material";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Chip,
|
||||
Divider,
|
||||
FormControl,
|
||||
FormHelperText,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
Stack,
|
||||
TextField
|
||||
} from "@mui/material";
|
||||
import {Field, Formik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {useEffect, useState} from "react";
|
||||
import * as Yup from "yup";
|
||||
import SelectBox from "@/core/components/SelectBox";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
import useProvince from "@/lib/app/hooks/useProvince";
|
||||
|
||||
const AddFormComponent = () => {
|
||||
const t = useTranslations();
|
||||
const {directionApp} = useDirection();
|
||||
const {token} = useUser();
|
||||
const requestServer = useRequest()
|
||||
|
||||
const [provinceList, setProvinceList] = useState([]);
|
||||
|
||||
// get province list
|
||||
useEffect(() => {
|
||||
requestServer(GET_PROVINCE_LIST, "get", {auth: true, notification: false})
|
||||
.then(function ({data}) {
|
||||
const formattedData = data.map((province, index) => ({
|
||||
id: index,
|
||||
name: province.name,
|
||||
value: province.id,
|
||||
}));
|
||||
setProvinceList(formattedData);
|
||||
}).catch(() => {
|
||||
})
|
||||
}, []);
|
||||
// end get province list
|
||||
const {provinceList, isLoadingProvinceList, errorProvinceList} = useProvince()
|
||||
|
||||
// initial values, validation and request action of form
|
||||
const initialValues = {
|
||||
@@ -183,27 +174,48 @@ const AddFormComponent = () => {
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
mt: 0,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
name="province"
|
||||
label={t("LoanRequest.text_field_province")} // t("LoanRequest.text_field_enter_your_province")
|
||||
<FormControl
|
||||
error={props.touched.province && !!props.errors.province}
|
||||
sx={{width: "100%", mt: 2}}
|
||||
size="small"
|
||||
selectType="province"
|
||||
component={SelectBox}
|
||||
selectors={provinceList}
|
||||
select={props.values.province}
|
||||
setFieldValue={props.setFieldValue}
|
||||
setFieldTouched={props.setFieldTouched}
|
||||
error={
|
||||
!!(props.touched.province && props.errors.province)
|
||||
}
|
||||
helperText={
|
||||
props.touched.province ? props.errors.province : null
|
||||
}
|
||||
/>
|
||||
>
|
||||
<InputLabel>{t("LoanRequest.text_field_province")}</InputLabel>
|
||||
<Select
|
||||
name="province"
|
||||
disabled={isLoadingProvinceList || errorProvinceList}
|
||||
label={t("LoanRequest.text_field_province")}
|
||||
value={props.values.province}
|
||||
onChange={(e) => {
|
||||
props.setFieldValue("province", e.target.value);
|
||||
}}
|
||||
onBlur={props.handleBlur}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
>
|
||||
{isLoadingProvinceList ? (
|
||||
<MenuItem>
|
||||
{t("LoanRequest.text_field_loading_provinces_list")}
|
||||
</MenuItem>
|
||||
) : errorProvinceList ? (
|
||||
<MenuItem>
|
||||
{t("LoanRequest.text_field_error_fetching_provinces")}
|
||||
</MenuItem>
|
||||
) : (
|
||||
provinceList.map((item) => (
|
||||
<MenuItem key={item.id} value={item.id}>
|
||||
{item.name}
|
||||
</MenuItem>
|
||||
))
|
||||
)}
|
||||
</Select>
|
||||
<FormHelperText>
|
||||
{props.touched.province && props.errors.province ? props.errors.province : ""}
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||
import {
|
||||
Grid,
|
||||
Stack,
|
||||
} from "@mui/material";
|
||||
import {Grid, Stack, Typography,} from "@mui/material";
|
||||
import {useEffect, useState} from "react";
|
||||
import {SHOW_LOAN_REQUEST_WELFARE} from "@/core/data/apiRoutes";
|
||||
import useLoading from "@/lib/app/hooks/useLoading";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
import moment from "jalali-moment";
|
||||
import RequestCard from "@/components/dashboard/refahi/followUp-loan/RequestCard";
|
||||
import {useTranslations} from "next-intl";
|
||||
|
||||
const LoanFollowUpComponent = () => {
|
||||
const t = useTranslations()
|
||||
const requestServer = useRequest();
|
||||
const {setLoadingPage} = useLoading();
|
||||
const [requestsList, setRequestsList] = useState([]);
|
||||
const [requestsList, setRequestsList] = useState(null);
|
||||
// get form data
|
||||
useEffect(() => {
|
||||
setLoadingPage(true)
|
||||
@@ -33,28 +32,23 @@ const LoanFollowUpComponent = () => {
|
||||
})
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<DashboardLayouts>
|
||||
<Stack
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 4,
|
||||
width: "100%",
|
||||
}}
|
||||
return (<DashboardLayouts>
|
||||
<Stack
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 4, width: "100%",
|
||||
}}
|
||||
>
|
||||
{requestsList == null ? '' : requestsList.length ? (<Grid
|
||||
container
|
||||
columnSpacing={2}
|
||||
rowSpacing={2}
|
||||
sx={{alignItems: "start", justifyContent: "center"}}
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
columnSpacing={2}
|
||||
rowSpacing={2}
|
||||
sx={{alignItems: "start", justifyContent: "center"}}
|
||||
>
|
||||
{requestsList.map((item, index) => (
|
||||
<RequestCard item={item} key={item.id}/>
|
||||
))}
|
||||
</Grid>
|
||||
</Stack>
|
||||
</DashboardLayouts>
|
||||
);
|
||||
{requestsList.map((item, index) => (<RequestCard item={item} key={item.id}/>))}
|
||||
</Grid>) : (<Typography sx={{textAlign: 'center'}}>{t('LoanFollowUp.no_request_found')}</Typography>)}
|
||||
</Stack>
|
||||
</DashboardLayouts>);
|
||||
};
|
||||
|
||||
export default LoanFollowUpComponent;
|
||||
|
||||
58
src/core/components/GlobalHead.jsx
Normal file
58
src/core/components/GlobalHead.jsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import Head from "next/head";
|
||||
|
||||
const GlobalHead = () => {
|
||||
return (
|
||||
<Head>
|
||||
<meta
|
||||
name="application-name"
|
||||
content={process.env.NEXT_PUBLIC_API_NAME}
|
||||
/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||||
<meta
|
||||
name="apple-mobile-web-app-status-bar-style"
|
||||
content="black-translucent"
|
||||
/>
|
||||
<meta
|
||||
name="apple-mobile-web-app-title"
|
||||
content={process.env.NEXT_PUBLIC_API_NAME}
|
||||
/>
|
||||
<meta name="description" content="Marhaba does it for you"/>
|
||||
<meta name="format-detection" content="telephone=no"/>
|
||||
<meta name="format-detection" content="date=no"/>
|
||||
<meta name="format-detection" content="address=no"/>
|
||||
<meta name="format-detection" content="email=no"/>
|
||||
<meta name="mobile-web-app-capable" content="yes"/>
|
||||
<link rel="apple-touch-icon" href="/icons/maskable_icon_x512.png"/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="120x120"
|
||||
href="/icons/maskable_icon_x128.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/icons/maskable_icon_x192.png"
|
||||
/>
|
||||
<meta name="google" content="notranslate"/>
|
||||
<meta name="robots" content="noindex"/>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/svg"
|
||||
sizes="32x32"
|
||||
href="/icons/favicon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/svg"
|
||||
sizes="16x16"
|
||||
href="/icons/favicon.png"
|
||||
/>
|
||||
</Head>
|
||||
)
|
||||
}
|
||||
|
||||
export default GlobalHead
|
||||
34
src/core/components/NetworkComponent.jsx
Normal file
34
src/core/components/NetworkComponent.jsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import useNetwork from "@/lib/app/hooks/useNetwork";
|
||||
import {useEffect, useRef} from "react";
|
||||
import {toast} from "react-toastify";
|
||||
import WifiIcon from '@mui/icons-material/Wifi';
|
||||
import WifiOffIcon from '@mui/icons-material/WifiOff';
|
||||
import {useTranslations} from "next-intl";
|
||||
|
||||
const NetworkComponent = () => {
|
||||
const toastId = useRef(null);
|
||||
const network = useNetwork()
|
||||
const t = useTranslations()
|
||||
|
||||
useEffect(() => {
|
||||
if (network.online) {
|
||||
toast.update(toastId.current, {
|
||||
type: toast.TYPE.SUCCESS,
|
||||
render: t('online_message'),
|
||||
autoClose: 2000,
|
||||
closeButton: true,
|
||||
closeOnClick: true,
|
||||
icon: <WifiIcon/>
|
||||
});
|
||||
return
|
||||
}
|
||||
toast.dismiss()
|
||||
toastId.current = toast.warn(t('offline_message'), {
|
||||
autoClose: false, closeButton: false, closeOnClick: false, icon: <WifiOffIcon/>
|
||||
})
|
||||
}, [network.online]);
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
export default NetworkComponent
|
||||
@@ -4,7 +4,7 @@ import {toast} from "react-toastify";
|
||||
|
||||
const ErrorNotification = (t, status, message) => {
|
||||
toast(
|
||||
({closeToast}) => (
|
||||
() => (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
@@ -36,4 +36,4 @@ const ErrorNotification = (t, status, message) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default ErrorNotification;
|
||||
export default ErrorNotification;
|
||||
@@ -3,9 +3,10 @@ import {toast} from "react-toastify";
|
||||
const PendingNotification = (t) => {
|
||||
toast(t("notifications.pending"), {
|
||||
autoClose: false,
|
||||
closeButton: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
});
|
||||
};
|
||||
|
||||
export default PendingNotification;
|
||||
export default PendingNotification;
|
||||
@@ -39,4 +39,4 @@ const SuccessNotification = (t, status) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default SuccessNotification;
|
||||
export default SuccessNotification;
|
||||
@@ -1,10 +1,10 @@
|
||||
import ReportIcon from "@mui/icons-material/Report";
|
||||
import {Box, Divider, Typography} from "@mui/material";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const WarningNotification = (t, status) => {
|
||||
toast(
|
||||
({closeToast}) => (
|
||||
() => (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
@@ -18,15 +18,15 @@ const WarningNotification = (t, status) => {
|
||||
<ReportIcon color="warning" sx={{mr: 1.6}}/>
|
||||
<Box sx={{display: "flex", flexDirection: "column"}}>
|
||||
<Typography color="warning.main" variant="button">
|
||||
{t("warning")} ({t("code")}: {status})
|
||||
{t("notifications.warning")} ({t("notifications.code")}:{" "}
|
||||
{status})
|
||||
</Typography>
|
||||
<Typography variant="caption">
|
||||
{t("warning_static_text")}
|
||||
{t("notifications.warning_static_text")}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Divider sx={{my: 1}}/>
|
||||
</>
|
||||
),
|
||||
{
|
||||
@@ -37,4 +37,4 @@ const WarningNotification = (t, status) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default WarningNotification;
|
||||
export default WarningNotification;
|
||||
@@ -3,11 +3,11 @@ import WarningNotification from "@/core/components/notifications/WarningNotifica
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
export const errorSetting = (t, notification) => {
|
||||
//todo
|
||||
if (notification) toast.dismiss();
|
||||
}
|
||||
|
||||
export const errorRequest = (t, notification) => {
|
||||
//todo
|
||||
if (notification) toast.dismiss();
|
||||
}
|
||||
|
||||
export const errorResponse = (response, clearToken, t, notification) => {
|
||||
@@ -48,7 +48,7 @@ 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)
|
||||
if (notification) ErrorNotification(t, response.status, response.data.message)
|
||||
}
|
||||
const errorValidation = (response, t, notification) => {
|
||||
if (notification) {
|
||||
@@ -59,4 +59,4 @@ const errorValidation = (response, t, notification) => {
|
||||
ErrorNotification(t, response.status, errorsArray[item][0]);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,13 @@ import theme from "@/core/utils/theme";
|
||||
import useLanguage from "@/lib/app/hooks/useLanguage";
|
||||
import useLoading from "@/lib/app/hooks/useLoading";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import Head from "next/head";
|
||||
import NextNProgress from "nextjs-progressbar";
|
||||
import {useEffect} from "react";
|
||||
import {ToastContainer} from "react-toastify";
|
||||
import useDirection from "@/lib/app/hooks/useDirection";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
import NetworkComponent from "@/core/components/NetworkComponent";
|
||||
import GlobalHead from "@/core/components/GlobalHead";
|
||||
|
||||
function AppLayout({children, isBot}) {
|
||||
const {languageIsReady} = useLanguage();
|
||||
@@ -40,66 +41,16 @@ function AppLayout({children, isBot}) {
|
||||
if (!languageIsReady) return;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<meta
|
||||
name="application-name"
|
||||
content={process.env.NEXT_PUBLIC_API_NAME}
|
||||
/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||||
<meta
|
||||
name="apple-mobile-web-app-status-bar-style"
|
||||
content="black-translucent"
|
||||
/>
|
||||
<meta
|
||||
name="apple-mobile-web-app-title"
|
||||
content={process.env.NEXT_PUBLIC_API_NAME}
|
||||
/>
|
||||
<meta name="description" content="Marhaba does it for you"/>
|
||||
<meta name="format-detection" content="telephone=no"/>
|
||||
<meta name="format-detection" content="date=no"/>
|
||||
<meta name="format-detection" content="address=no"/>
|
||||
<meta name="format-detection" content="email=no"/>
|
||||
<meta name="mobile-web-app-capable" content="yes"/>
|
||||
<link rel="apple-touch-icon" href="/icons/maskable_icon_x512.png"/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="120x120"
|
||||
href="/icons/maskable_icon_x128.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/icons/maskable_icon_x192.png"
|
||||
/>
|
||||
<meta name="google" content="notranslate"/>
|
||||
<meta name="robots" content="noindex"/>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/svg"
|
||||
sizes="32x32"
|
||||
href="/images/logo.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/svg"
|
||||
sizes="16x16"
|
||||
href="/images/logo.png"
|
||||
/>
|
||||
</Head>
|
||||
<NextNProgress
|
||||
color={theme.palette.secondary.dark}
|
||||
options={{showSpinner: false}}
|
||||
/>
|
||||
<ToastContainer position={directionApp === "ltr" ? "top-left" : "top-right"} rtl={directionApp === 'rtl'}/>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
return (<>
|
||||
<GlobalHead/>
|
||||
<NextNProgress
|
||||
color={theme.palette.secondary.dark}
|
||||
options={{showSpinner: false}}
|
||||
/>
|
||||
<ToastContainer position={directionApp === "ltr" ? "top-left" : "top-right"} rtl={directionApp === 'rtl'}/>
|
||||
<NetworkComponent/>
|
||||
{children}
|
||||
</>);
|
||||
}
|
||||
|
||||
export default AppLayout;
|
||||
export default AppLayout;
|
||||
58
src/lib/app/hooks/useNetwork.jsx
Normal file
58
src/lib/app/hooks/useNetwork.jsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import {useEffect, useState} from "react";
|
||||
|
||||
function getNetworkConnection() {
|
||||
return (
|
||||
navigator.connection ||
|
||||
navigator.mozConnection ||
|
||||
navigator.webkitConnection ||
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
function getNetworkConnectionInfo() {
|
||||
const connection = getNetworkConnection();
|
||||
if (!connection) {
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
rtt: connection.rtt,
|
||||
type: connection.type,
|
||||
saveData: connection.saveData,
|
||||
downLink: connection.downLink,
|
||||
downLinkMax: connection.downLinkMax,
|
||||
effectiveType: connection.effectiveType,
|
||||
};
|
||||
}
|
||||
|
||||
function useNetwork() {
|
||||
const [state, setState] = useState(() => {
|
||||
return {
|
||||
online: navigator.onLine,
|
||||
};
|
||||
});
|
||||
useEffect(() => {
|
||||
const handleOnline = () => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
online: true,
|
||||
}));
|
||||
};
|
||||
const handleOffline = () => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
online: false,
|
||||
}));
|
||||
};
|
||||
|
||||
window.addEventListener("online", handleOnline);
|
||||
window.addEventListener("offline", handleOffline);
|
||||
return () => {
|
||||
window.removeEventListener("online", handleOnline);
|
||||
window.removeEventListener("offline", handleOffline);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
export default useNetwork;
|
||||
29
src/lib/app/hooks/useProvince.jsx
Normal file
29
src/lib/app/hooks/useProvince.jsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import {GET_PROVINCE_LIST} from "@/core/data/apiRoutes";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
import useSWR from "swr";
|
||||
|
||||
const useProvince = () => {
|
||||
const requestServer = useRequest({auth: true, notification: false})
|
||||
|
||||
//swr config
|
||||
const fetcher = (...args) => {
|
||||
return requestServer(args, 'get').then(({data}) => {
|
||||
return data;
|
||||
}).catch(() => {
|
||||
})
|
||||
};
|
||||
|
||||
const {data, isLoading} = useSWR(GET_PROVINCE_LIST, fetcher, {
|
||||
revalidateIfStale: false,
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: false
|
||||
});
|
||||
|
||||
return {
|
||||
provinceList: data,
|
||||
isLoadingProvinceList: isLoading,
|
||||
errorProvinceList: !data
|
||||
}
|
||||
};
|
||||
|
||||
export default useProvince;
|
||||
@@ -4,27 +4,23 @@ import PendingNotification from "@/core/components/notifications/PendingNotifica
|
||||
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";
|
||||
|
||||
const defaultOptions = {
|
||||
auth: false,
|
||||
data: {},
|
||||
requestOptions: {
|
||||
auth: false, data: {}, requestOptions: {
|
||||
headers: {}
|
||||
},
|
||||
notification: true,
|
||||
pending: true,
|
||||
success: {
|
||||
}, notification: true, pending: true, success: {
|
||||
notification: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
failed: {
|
||||
}, failed: {
|
||||
notification: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
const useRequest = (initOptions) => {
|
||||
const network = useNetwork()
|
||||
const t = useTranslations()
|
||||
const {token, clearToken} = useUser()
|
||||
let _options = {...defaultOptions, ...initOptions}
|
||||
@@ -32,20 +28,20 @@ const useRequest = (initOptions) => {
|
||||
function requestServer(url = '', method = 'get', options) {
|
||||
_options = {..._options, ...options}
|
||||
if (_options.auth) _options = {
|
||||
..._options,
|
||||
requestOptions: {
|
||||
..._options, requestOptions: {
|
||||
..._options.requestOptions,
|
||||
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)
|
||||
axios({
|
||||
url: url,
|
||||
method: method,
|
||||
data: _options.data,
|
||||
..._options.requestOptions
|
||||
url: url, method: method, data: _options.data, ..._options.requestOptions
|
||||
})
|
||||
.then(response => {
|
||||
successRequest(response, t, _options)
|
||||
|
||||
@@ -11,7 +11,7 @@ export default function MyDocument(props) {
|
||||
<Head>
|
||||
<meta name="theme-color" content={theme.palette.primary.main}/>
|
||||
<meta name="emotion-insertion-point" content=""/>
|
||||
<link rel="shortcut icon" href="/icons/favicon.ico"/>
|
||||
<link rel="shortcut icon" href="/icons/favicon.png"/>
|
||||
<link rel="manifest" href="/manifest.json"/>
|
||||
{emotionStyleTags}
|
||||
</Head>
|
||||
|
||||
Reference in New Issue
Block a user