merge all files
This commit is contained in:
@@ -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"
|
||||
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": "ثبت درخواست وام",
|
||||
@@ -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": "ویرایش درخواست وام"
|
||||
|
||||
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"
|
||||
]
|
||||
}
|
||||
@@ -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 (
|
||||
<CenterLayout>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
fontWeight: 600,
|
||||
my: 2
|
||||
}}>
|
||||
{t("LoanRequest.add_loan_request_permission")}
|
||||
</Typography>
|
||||
<Button color="primary" variant="contained"
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: "/dashboard/refahi/followUp-loan",
|
||||
}}>
|
||||
{t("LoanFollowUp.loan_follow_up_page")}
|
||||
</Button>
|
||||
</CenterLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default AccessibilityComponent;
|
||||
@@ -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 = () => {
|
||||
<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_id && !!props.errors.province_id}
|
||||
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_id")}</InputLabel>
|
||||
<Select
|
||||
name="province_id"
|
||||
disabled={isLoadingProvinceList || errorProvinceList}
|
||||
label={t("LoanRequest.text_field_province_id")}
|
||||
value={props.values.province_id}
|
||||
onChange={(e) => {
|
||||
props.setFieldValue("province_id", 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_id && props.errors.province_id ? props.errors.province_id : ""}
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
@@ -225,21 +240,21 @@ const AddFormComponent = () => {
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="national_code"
|
||||
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={
|
||||
!!(props.touched.national_code && props.errors.national_code)
|
||||
!!(props.touched.national_id && props.errors.national_id)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.national_code
|
||||
? props.errors.national_code
|
||||
props.touched.national_id
|
||||
? props.errors.national_id
|
||||
: null
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -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 (
|
||||
<DashboardLayouts>
|
||||
<AddFormComponent/>
|
||||
{user.can_request_a_new_loan ? <AddFormComponent/> : <AccessibilityComponent/>}
|
||||
</DashboardLayouts>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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 = () => {
|
||||
>
|
||||
<Field
|
||||
name="province_id"
|
||||
label={t("LoanRequest.text_field_province")} // t("LoanRequest.text_field_enter_your_province")
|
||||
label={t("LoanRequest.text_field_province_id")} // t("LoanRequest.text_field_enter_your_province")
|
||||
size="small"
|
||||
selectType="province_id"
|
||||
component={SelectBox}
|
||||
@@ -244,9 +195,9 @@ 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={
|
||||
|
||||
@@ -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 && (
|
||||
<DashboardLayouts>
|
||||
<EditFormComponent/>
|
||||
<EditFormComponent provinceList={provinceList} initialValues={initialValues}/>
|
||||
</DashboardLayouts>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
return (<DashboardLayouts>
|
||||
<Stack
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 4,
|
||||
width: "100%",
|
||||
p: 4, width: "100%",
|
||||
}}
|
||||
>
|
||||
<Grid
|
||||
{requestsList == null ? '' : requestsList.length ? (<Grid
|
||||
container
|
||||
columnSpacing={2}
|
||||
rowSpacing={2}
|
||||
sx={{alignItems: "start", justifyContent: "center"}}
|
||||
>
|
||||
{requestsList.map((item, index) => (
|
||||
<RequestCard item={item} key={item.id}/>
|
||||
))}
|
||||
</Grid>
|
||||
{requestsList.map((item, index) => (<RequestCard item={item} key={item.id}/>))}
|
||||
</Grid>) : (<Typography sx={{textAlign: 'center'}}>{t('LoanFollowUp.no_request_found')}</Typography>)}
|
||||
</Stack>
|
||||
</DashboardLayouts>
|
||||
);
|
||||
</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={{
|
||||
|
||||
@@ -3,6 +3,7 @@ import {toast} from "react-toastify";
|
||||
const PendingNotification = (t) => {
|
||||
toast(t("notifications.pending"), {
|
||||
autoClose: false,
|
||||
closeButton: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
});
|
||||
|
||||
@@ -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}}/>
|
||||
</>
|
||||
),
|
||||
{
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
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;
|
||||
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