diff --git a/example.env.local b/example.env.local
index 554476c..0883de5 100644
--- a/example.env.local
+++ b/example.env.local
@@ -1,11 +1,11 @@
NEXT_PUBLIC_API_NAME = "Loan Facilities Dashboard"
-NEXT_PUBLIC_API_VERSION = "1.7.1"
+NEXT_PUBLIC_API_VERSION = "1.7.3"
NEXT_PUBLIC_DEFAULT_LANGUAGE = "fa"
NEXT_PUBLIC_DEFAULT_DIRECTION = "rtl"
NEXT_PUBLIC_PRIMARY_MAIN = "#084070"
NEXT_PUBLIC_SECONDARY_MAIN = "#FF4E00"
-NEXT_PUBLIC_BASE_URL = "deploy api"
+NEXT_PUBLIC_BASE_URL = "https://loan.witel.ir"
NODE_ENV = "development"
\ No newline at end of file
diff --git a/public/icons/favicon.png b/public/icons/favicon.png
new file mode 100644
index 0000000..c82bf9a
Binary files /dev/null and b/public/icons/favicon.png differ
diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json
index 435a0c7..0c9d741 100644
--- a/public/locales/fa/app.json
+++ b/public/locales/fa/app.json
@@ -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": "ثبت درخواست وام",
@@ -122,8 +125,8 @@
"error_message_vehicle_type": "لطفا نوع وسیله نقلیه خود را وارد کنید!",
"error_message_plate_number": "لطفا شماره پلاک خود را وارد کنید!",
"error_message_navgan_id": "لطفا کد ناوگان خود را وارد کنید!",
- "error_message_province": "لطفا استان خود را وارد کنید!",
- "error_message_national_code": "لطفا کد ملی خود را وارد کنید!",
+ "error_message_province_id": "لطفا استان خود را وارد کنید!",
+ "error_message_national_id": "لطفا کد ملی خود را وارد کنید!",
"error_message_shenasname_id": "لطفا شماره شناسنامه خود را وارد کنید!",
"text_field_phone_number": "شماره تلفن",
"text_field_enter_your_phone_number": "شماره تلفن خود را وارد کنید",
@@ -131,12 +134,14 @@
"text_field_enter_your_name": "نام خود را وارد کنید",
"text_field_vehicle_type": "نام وسیله نقلیه",
"text_field_enter_your_vehicle_type": "نام وسیله نقلیه خود را وارد کنید",
- "text_field_province": "استان",
- "text_field_enter_your_province": "استان خود را وارد کنید",
+ "text_field_province_id": "استان",
+ "text_field_loading_provinces_list": "درحال دریافت استان ها",
+ "text_field_error_fetching_provinces": "خطا در دریافت استان ها",
+ "text_field_enter_your_province_id": "استان خود را وارد کنید",
"text_field_navgan_id": "شماره ناوگان",
"text_field_enter_your_navgan_id": "شماره ناوگان خود را وارد کنید",
- "text_field_national_code": "کد ملی",
- "text_field_enter_your_national_code": "کد ملی خود را وارد کنید",
+ "text_field_national_id": "کد ملی",
+ "text_field_enter_your_national_id": "کد ملی خود را وارد کنید",
"text_field_shenasname_id": "شماره شناسنامه",
"text_field_enter_your_shenasname_id": "شماره شناسنامه خود را وارد کنید",
"text_field_plate_number": "شماره پلاک",
@@ -153,7 +158,8 @@
"file_field_payan_khedmat_image": "تصویر کارت پایان خدمت",
"error_message_national_card_image": "تصویر کارت ملی خود را وارد کنید",
"error_message_shenasname_image": "تصویر شناسنامه خود را وارد کنید",
- "error_message_payan_khedmat_image": "تصویر کارت پایان خدمت خود را وارد کنید"
+ "error_message_payan_khedmat_image": "تصویر کارت پایان خدمت خود را وارد کنید",
+ "add_loan_request_permission": "اکنون امکان ثبت درخواست جدید برای شما مقدور نیست"
},
"EditLoanRequest": {
"edit_loan_request_page": "ویرایش درخواست وام"
diff --git a/public/manifest.json b/public/manifest.json
new file mode 100644
index 0000000..32bacd5
--- /dev/null
+++ b/public/manifest.json
@@ -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"
+ ]
+}
diff --git a/src/components/dashboard/refahi/add-request-loan/accessibility/index.jsx b/src/components/dashboard/refahi/add-request-loan/accessibility/index.jsx
new file mode 100644
index 0000000..3618d0b
--- /dev/null
+++ b/src/components/dashboard/refahi/add-request-loan/accessibility/index.jsx
@@ -0,0 +1,32 @@
+import {Button, Typography} from "@mui/material";
+import {useTranslations} from "next-intl";
+import CenterLayout from "@/layouts/CenterLayout";
+import {useRouter} from "next/router";
+import {NextLinkComposed} from "@/core/components/LinkRouting";
+
+const AccessibilityComponent = () => {
+ const t = useTranslations();
+ const router = useRouter();
+
+ return (
+
+
+ {t("LoanRequest.add_loan_request_permission")}
+
+
+
+ );
+};
+
+export default AccessibilityComponent;
diff --git a/src/components/dashboard/refahi/add-request-loan/forms/AddForm.jsx b/src/components/dashboard/refahi/add-request-loan/forms/AddForm.jsx
index 06a40fc..4051854 100644
--- a/src/components/dashboard/refahi/add-request-loan/forms/AddForm.jsx
+++ b/src/components/dashboard/refahi/add-request-loan/forms/AddForm.jsx
@@ -1,46 +1,39 @@
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";
+import {useRouter} from "next/router";
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();
+ const router = useRouter();
// initial values, validation and request action of form
const initialValues = {
name: "",
phone_number: "",
- province: "",
- national_code: "",
+ province_id: "",
+ national_id: "",
shenasname_id: "",
sherkat_naft_doc: null,
estate_doc: null,
@@ -55,9 +48,9 @@ const AddFormComponent = () => {
phone_number: Yup.string().required(
t("LoanRequest.error_message_phone_number")
),
- province: Yup.string().required(t("LoanRequest.error_message_province")),
- national_code: Yup.string().required(
- t("LoanRequest.error_message_national_code")
+ province_id: Yup.string().required(t("LoanRequest.error_message_province_id")),
+ national_id: Yup.string().required(
+ t("LoanRequest.error_message_national_id")
),
shenasname_id: Yup.string().required(
t("LoanRequest.error_message_shenasname_id")
@@ -73,8 +66,8 @@ const AddFormComponent = () => {
const formData = new FormData();
formData.append("name", values.name);
formData.append("phone_number", values.phone_number);
- formData.append("province_id", values.province);
- formData.append("national_id", values.national_code);
+ formData.append("province_id", values.province_id);
+ formData.append("national_id", values.national_id);
formData.append("shenasname_id", values.shenasname_id);
if (values.sherkat_naft_doc != null)
formData.append("sherkat_naft_doc", values.sherkat_naft_doc);
@@ -90,6 +83,7 @@ const AddFormComponent = () => {
formData.append("payan_khedmat_image", values.payan_khedmat_image);
requestServer(SEND_LOAN_REQUEST_WELFARE, "post", {auth: true, data: formData})
.then(function (response) {
+ router.replace('/dashboard/refahi/followUp-loan');
})
.catch(function (error) {
})
@@ -183,27 +177,48 @@ const AddFormComponent = () => {
-
+ >
+ {t("LoanRequest.text_field_province_id")}
+
+
+ {props.touched.province_id && props.errors.province_id ? props.errors.province_id : ""}
+
+
{
diff --git a/src/components/dashboard/refahi/add-request-loan/index.jsx b/src/components/dashboard/refahi/add-request-loan/index.jsx
index feb8df0..bc82ac7 100644
--- a/src/components/dashboard/refahi/add-request-loan/index.jsx
+++ b/src/components/dashboard/refahi/add-request-loan/index.jsx
@@ -1,16 +1,15 @@
import DashboardLayouts from "@/layouts/dashboardLayouts";
import useUser from "@/lib/app/hooks/useUser";
-import {Box, Chip, Divider} from "@mui/material";
import {useTranslations} from "next-intl";
import AddFormComponent from "@/components/dashboard/refahi/add-request-loan/forms/AddForm";
+import AccessibilityComponent from "@/components/dashboard/refahi/add-request-loan/accessibility";
const LoanRequestComponent = () => {
const t = useTranslations();
const {user} = useUser();
-
return (
-
+ {user.can_request_a_new_loan ? : }
);
};
diff --git a/src/components/dashboard/refahi/edit-request-loan/forms/EditForm.jsx b/src/components/dashboard/refahi/edit-request-loan/forms/EditForm.jsx
index 9ea22c2..36f5aa0 100644
--- a/src/components/dashboard/refahi/edit-request-loan/forms/EditForm.jsx
+++ b/src/components/dashboard/refahi/edit-request-loan/forms/EditForm.jsx
@@ -1,72 +1,23 @@
import StyledForm from "@/core/components/StyledForm";
import UploadSystem from "@/core/components/UploadSystem";
-import {GET_PROVINCE_LIST, UPDATE_LOAN_REQUEST_WELFARE, DETAILS_LOAN_REQUEST_WELFARE} from "@/core/data/apiRoutes";
+import {UPDATE_LOAN_REQUEST_WELFARE} from "@/core/data/apiRoutes";
import useDirection from "@/lib/app/hooks/useDirection";
import useUser from "@/lib/app/hooks/useUser";
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
import {Box, Button, Chip, Divider, Stack, TextField} from "@mui/material";
-import axios from "axios";
import {Field, Formik} from "formik";
import {useTranslations} from "next-intl";
-import {useEffect, useMemo, useState} from "react";
import * as Yup from "yup";
import SelectBox from "@/core/components/SelectBox";
import useRequest from "@/lib/app/hooks/useRequest";
import {useRouter} from "next/router";
import useLoading from "@/lib/app/hooks/useLoading";
-const EditFormComponent = () => {
+const EditFormComponent = ({provinceList, initialValues}) => {
const t = useTranslations();
- const {directionApp} = useDirection();
- const {token} = useUser();
const requestServer = useRequest();
const router = useRouter();
- const {setLoadingPage} = useLoading();
- const [provinceList, setProvinceList] = useState(null);
- const [initialValues, setInitialValues] = useState(null);
-
- // get province list
- useEffect(() => {
- setLoadingPage(true)
- 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(() => {
- });
- }, []);
-
-
- // get form data
- useEffect(() => {
- if (!provinceList) return;
- requestServer(DETAILS_LOAN_REQUEST_WELFARE + router.query.id, "get", {auth: true, notification: false})
- .then(function ({data}) {
- const item = data.data;
- const formattedData = {
- name: item.name,
- phone_number: item.phone_number,
- province_id: item.province_id,
- national_id: item.national_id,
- shenasname_id: item.shenasname_id,
- sherkat_naft_doc: item.sherkat_naft_doc,
- estate_doc: item.estate_doc,
- agreement_doc: item.agreement_doc,
- national_card_image: item.national_card_image,
- shenasname_image: item.shenasname_image,
- payan_khedmat_image: item.payan_khedmat_image,
- }
- setInitialValues(formattedData);
- setLoadingPage(false)
- })
- .catch(() => {
- })
- }, [provinceList]);
// validation and request action of form
const validationSchema = Yup.object().shape({
@@ -74,8 +25,8 @@ const EditFormComponent = () => {
phone_number: Yup.string().required(
t("LoanRequest.error_message_phone_number")
),
- province_id: Yup.string().required(t("LoanRequest.error_message_province")),
- national_id: Yup.string().required(t("LoanRequest.error_message_national_code")),
+ province_id: Yup.string().required(t("LoanRequest.error_message_province_id")),
+ national_id: Yup.string().required(t("LoanRequest.error_message_national_id")),
shenasname_id: Yup.string().required(t("LoanRequest.error_message_shenasname_id")),
sherkat_naft_doc: Yup.mixed().required(t("LoanRequest.error_message_sherkat_naft_doc")),
estate_doc: Yup.mixed().required(t("LoanRequest.error_message_estate_doc")),
@@ -205,7 +156,7 @@ const EditFormComponent = () => {
>
{
name="national_id"
variant="outlined"
size="small"
- label={t("LoanRequest.text_field_national_code")}
+ label={t("LoanRequest.text_field_national_id")}
placeholder={t(
- "LoanRequest.text_field_enter_your_national_code"
+ "LoanRequest.text_field_enter_your_national_id"
)}
type={"text"}
error={
@@ -307,7 +258,7 @@ const EditFormComponent = () => {
setFieldValue={props.setFieldValue}
default_image={initialValues.sherkat_naft_doc}
fieldName="sherkat_naft_doc"
- imageAlt={t("app_name")}
+ imageAlt={t("LoanRequest.file_field_sherkat_naft_doc")}
label={t("LoanRequest.file_field_sherkat_naft_doc")}
enableDelete={false}
error={
@@ -326,7 +277,7 @@ const EditFormComponent = () => {
setFieldValue={props.setFieldValue}
default_image={initialValues.estate_doc}
fieldName="estate_doc"
- imageAlt={t("app_name")}
+ imageAlt={t("LoanRequest.file_field_estate_doc")}
label={t("LoanRequest.file_field_estate_doc")}
enableDelete={false}
error={
@@ -345,7 +296,7 @@ const EditFormComponent = () => {
setFieldValue={props.setFieldValue}
default_image={initialValues.agreement_doc}
fieldName="agreement_doc"
- imageAlt={t("app_name")}
+ imageAlt={t("LoanRequest.file_field_agreement_doc")}
label={t("LoanRequest.file_field_agreement_doc")}
enableDelete={false}
error={
@@ -364,7 +315,7 @@ const EditFormComponent = () => {
setFieldValue={props.setFieldValue}
default_image={initialValues.shenasname_image}
fieldName="shenasname_image"
- imageAlt={t("app_name")}
+ imageAlt={t("LoanRequest.file_field_shenasname_image")}
label={t("LoanRequest.file_field_shenasname_image")}
enableDelete={false}
error={
@@ -383,7 +334,7 @@ const EditFormComponent = () => {
setFieldValue={props.setFieldValue}
default_image={initialValues.payan_khedmat_image}
fieldName="payan_khedmat_image"
- imageAlt={t("app_name")}
+ imageAlt={t("LoanRequest.file_field_payan_khedmat_image")}
label={t("LoanRequest.file_field_payan_khedmat_image")}
enableDelete={false}
error={
diff --git a/src/components/dashboard/refahi/edit-request-loan/index.jsx b/src/components/dashboard/refahi/edit-request-loan/index.jsx
index 4be62ff..89de937 100644
--- a/src/components/dashboard/refahi/edit-request-loan/index.jsx
+++ b/src/components/dashboard/refahi/edit-request-loan/index.jsx
@@ -1,16 +1,80 @@
import DashboardLayouts from "@/layouts/dashboardLayouts";
-import useUser from "@/lib/app/hooks/useUser";
-import {useTranslations} from "next-intl";
import EditFormComponent from "@/components/dashboard/refahi/edit-request-loan/forms/EditForm";
+import {useEffect, useState} from "react";
+import {DETAILS_LOAN_REQUEST_WELFARE, GET_PROVINCE_LIST} from "@/core/data/apiRoutes";
+import useLoading from "@/lib/app/hooks/useLoading";
+import useRequest from "@/lib/app/hooks/useRequest";
+import {useRouter} from "next/router";
+import {log} from "next/dist/server/typescript/utils";
const LoanRequestComponent = () => {
- const t = useTranslations();
- const {user} = useUser();
+ const requestServer = useRequest();
+ const {setLoadingPage} = useLoading();
+ const router = useRouter();
+
+ const [provinceList, setProvinceList] = useState(null);
+ const [initialValues, setInitialValues] = useState(null);
+
+ // get province list
+ useEffect(() => {
+ setLoadingPage(true);
+ 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(() => {
+ setLoadingPage(false);
+ });
+ }, []);
+
+ // get form data
+ useEffect(() => {
+ if (!provinceList) return;
+ setLoadingPage(true);
+ requestServer(DETAILS_LOAN_REQUEST_WELFARE + router.query.id, "get", {auth: true, notification: false})
+ .then(function ({data}) {
+ const item = data.data;
+ const formattedData = {
+ name: item.name,
+ phone_number: item.phone_number,
+ province_id: item.province_id,
+ national_id: item.national_id,
+ shenasname_id: item.shenasname_id,
+ sherkat_naft_doc: item.sherkat_naft_doc,
+ estate_doc: item.estate_doc,
+ agreement_doc: item.agreement_doc,
+ national_card_image: item.national_card_image,
+ shenasname_image: item.shenasname_image,
+ payan_khedmat_image: item.payan_khedmat_image,
+ state_id: item.state_id
+ };
+ setInitialValues(formattedData);
+ })
+ .catch(() => {
+ setLoadingPage(false);
+ });
+ }, [provinceList, router]);
+
+ // Redirect to /dashboard/refahi/followUp-loan if state_id is not 7
+ useEffect(() => {
+ if (!initialValues) return
+ if (initialValues.state_id === 7) return
+
+ router.replace('/dashboard/refahi/followUp-loan');
+ }, [initialValues]);
return (
-
-
-
+ <>
+ {initialValues && initialValues.state_id === 7 && (
+
+
+
+ )}
+ >
);
};
diff --git a/src/components/dashboard/refahi/followUp-loan/index.jsx b/src/components/dashboard/refahi/followUp-loan/index.jsx
index 331bab0..32b121d 100644
--- a/src/components/dashboard/refahi/followUp-loan/index.jsx
+++ b/src/components/dashboard/refahi/followUp-loan/index.jsx
@@ -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 (
-
-
+
+ {requestsList == null ? '' : requestsList.length ? (
-
- {requestsList.map((item, index) => (
-
- ))}
-
-
-
- );
+ {requestsList.map((item, index) => ())}
+ ) : ({t('LoanFollowUp.no_request_found')})}
+
+ );
};
export default LoanFollowUpComponent;
diff --git a/src/core/components/GlobalHead.jsx b/src/core/components/GlobalHead.jsx
new file mode 100644
index 0000000..5d6186d
--- /dev/null
+++ b/src/core/components/GlobalHead.jsx
@@ -0,0 +1,58 @@
+import Head from "next/head";
+
+const GlobalHead = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default GlobalHead
\ No newline at end of file
diff --git a/src/core/components/NetworkComponent.jsx b/src/core/components/NetworkComponent.jsx
new file mode 100644
index 0000000..8ebbb68
--- /dev/null
+++ b/src/core/components/NetworkComponent.jsx
@@ -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:
+ });
+ return
+ }
+ toast.dismiss()
+ toastId.current = toast.warn(t('offline_message'), {
+ autoClose: false, closeButton: false, closeOnClick: false, icon:
+ })
+ }, [network.online]);
+
+ return ''
+}
+
+export default NetworkComponent
\ No newline at end of file
diff --git a/src/core/components/notifications/ErrorNotification.jsx b/src/core/components/notifications/ErrorNotification.jsx
index 4c2e857..05e2fb9 100644
--- a/src/core/components/notifications/ErrorNotification.jsx
+++ b/src/core/components/notifications/ErrorNotification.jsx
@@ -4,7 +4,7 @@ import {toast} from "react-toastify";
const ErrorNotification = (t, status, message) => {
toast(
- ({closeToast}) => (
+ () => (
<>
{
);
};
-export default ErrorNotification;
+export default ErrorNotification;
\ No newline at end of file
diff --git a/src/core/components/notifications/PendingNotification.jsx b/src/core/components/notifications/PendingNotification.jsx
index f3a0af4..6183f6b 100644
--- a/src/core/components/notifications/PendingNotification.jsx
+++ b/src/core/components/notifications/PendingNotification.jsx
@@ -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;
\ No newline at end of file
diff --git a/src/core/components/notifications/SuccessNotification.jsx b/src/core/components/notifications/SuccessNotification.jsx
index 998deaa..3507cef 100644
--- a/src/core/components/notifications/SuccessNotification.jsx
+++ b/src/core/components/notifications/SuccessNotification.jsx
@@ -39,4 +39,4 @@ const SuccessNotification = (t, status) => {
);
};
-export default SuccessNotification;
+export default SuccessNotification;
\ No newline at end of file
diff --git a/src/core/components/notifications/WarningNotification.jsx b/src/core/components/notifications/WarningNotification.jsx
index 5e931f0..19d6a2f 100644
--- a/src/core/components/notifications/WarningNotification.jsx
+++ b/src/core/components/notifications/WarningNotification.jsx
@@ -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}) => (
+ () => (
<>
{
- {t("warning")} ({t("code")}: {status})
+ {t("notifications.warning")} ({t("notifications.code")}:{" "}
+ {status})
- {t("warning_static_text")}
+ {t("notifications.warning_static_text")}
-
>
),
{
@@ -37,4 +37,4 @@ const WarningNotification = (t, status) => {
);
};
-export default WarningNotification;
+export default WarningNotification;
\ No newline at end of file
diff --git a/src/core/utils/errorHandler.js b/src/core/utils/errorHandler.js
index ec5858a..8dbd364 100644
--- a/src/core/utils/errorHandler.js
+++ b/src/core/utils/errorHandler.js
@@ -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]);
})
}
-}
+}
\ No newline at end of file
diff --git a/src/layouts/AppLayout.jsx b/src/layouts/AppLayout.jsx
index 611e707..2b4593b 100644
--- a/src/layouts/AppLayout.jsx
+++ b/src/layouts/AppLayout.jsx
@@ -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 (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {children}
- >
- );
+ return (<>
+
+
+
+
+ {children}
+ >);
}
-export default AppLayout;
+export default AppLayout;
\ No newline at end of file
diff --git a/src/lib/app/hooks/useNetwork.jsx b/src/lib/app/hooks/useNetwork.jsx
new file mode 100644
index 0000000..4fff7fe
--- /dev/null
+++ b/src/lib/app/hooks/useNetwork.jsx
@@ -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;
\ No newline at end of file
diff --git a/src/lib/app/hooks/useProvince.jsx b/src/lib/app/hooks/useProvince.jsx
new file mode 100644
index 0000000..d0fbda0
--- /dev/null
+++ b/src/lib/app/hooks/useProvince.jsx
@@ -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;
\ No newline at end of file
diff --git a/src/lib/app/hooks/useRequest.js b/src/lib/app/hooks/useRequest.js
index 5c567ca..d361e08 100644
--- a/src/lib/app/hooks/useRequest.js
+++ b/src/lib/app/hooks/useRequest.js
@@ -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)
diff --git a/src/pages/_document.jsx b/src/pages/_document.jsx
index c9c28bb..474e29b 100644
--- a/src/pages/_document.jsx
+++ b/src/pages/_document.jsx
@@ -11,7 +11,7 @@ export default function MyDocument(props) {
-
+
{emotionStyleTags}