Merge branch 'release/v1.25.1'
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -31,4 +31,6 @@ cypress/screenshots
|
||||
.env
|
||||
.idea
|
||||
package-lock.json
|
||||
ecosystem.config
|
||||
ecosystem.config
|
||||
|
||||
public/config.json
|
||||
@@ -1,5 +1,5 @@
|
||||
NEXT_PUBLIC_API_NAME = "Loan Facilities Dashboard"
|
||||
NEXT_PUBLIC_API_VERSION = "1.22.3"
|
||||
NEXT_PUBLIC_API_VERSION = "1.25.1"
|
||||
NEXT_PUBLIC_DEFAULT_LANGUAGE = "fa"
|
||||
NEXT_PUBLIC_DEFAULT_DIRECTION = "rtl"
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
images: {
|
||||
domains: ['loan.witel.ir', /* other domains */],
|
||||
domains: [process.env.NEXT_PUBLIC_BASE_URL],
|
||||
},
|
||||
i18n: {
|
||||
defaultLocale: 'fa',
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
"@mui/icons-material": "^5.11.16",
|
||||
"@mui/lab": "^5.0.0-alpha.152",
|
||||
"@mui/material": "^5.12.0",
|
||||
"@mui/x-date-pickers": "^6.18.5",
|
||||
"@witel/webapp-builder": "^1.2.4",
|
||||
"axios": "^1.4.0",
|
||||
"colord": "^2.9.3",
|
||||
"date-fns-jalali": "^2.13.0-0",
|
||||
"eslint": "8.36.0",
|
||||
"formik": "^2.2.9",
|
||||
"fs-extra": "^11.1.1",
|
||||
|
||||
41
public/config.json.example
Normal file
41
public/config.json.example
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"middlewares": {},
|
||||
"deadlines": {
|
||||
"register": {
|
||||
"date": {
|
||||
"from": "1402/09/01",
|
||||
"to": "1402/09/10"
|
||||
},
|
||||
"messages": {
|
||||
"before": "ثبت نام هنوز شروع نشده",
|
||||
"after": "زمان ثبت نام به اتمام رسید"
|
||||
},
|
||||
"timeline_label": {
|
||||
"primary": "ثبت نام متقاضی",
|
||||
"secondary": "ثبت نام متقاضیان واجد شرایط"
|
||||
}
|
||||
},
|
||||
"validation": {
|
||||
"date": {
|
||||
"from": "1402/09/15",
|
||||
"to": "1402/11/10"
|
||||
},
|
||||
"messages": {},
|
||||
"timeline_label": {
|
||||
"primary": "صحت سنجی متقاضیان",
|
||||
"secondary": "بررسی و کارشناسی درخواست ها"
|
||||
}
|
||||
},
|
||||
"done": {
|
||||
"date": {
|
||||
"from": "1402/11/10",
|
||||
"to": "1402/12/20"
|
||||
},
|
||||
"messages": {},
|
||||
"timeline_label": {
|
||||
"primary": "ارجاع به بانک",
|
||||
"secondary": "فرآیند معرفی ضامن و پرداخت"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
public/files/راهنما.xlsx
Normal file
BIN
public/files/راهنما.xlsx
Normal file
Binary file not shown.
2
public/global.scss
Normal file
2
public/global.scss
Normal file
@@ -0,0 +1,2 @@
|
||||
@import "fontiran";
|
||||
@import 'react-toastify/dist/ReactToastify.css';
|
||||
BIN
public/images/bg-firstpage-bus.png
Normal file
BIN
public/images/bg-firstpage-bus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 565 KiB |
@@ -1,10 +1,18 @@
|
||||
{
|
||||
"app_name": "سامانه جامع تسهیلات",
|
||||
"app_short_name": "سامانه تسهیلات",
|
||||
"birthday": "تاریخ تولد",
|
||||
"birthday_error": "تاریخ تولد خود را وارد کنید!",
|
||||
"dashboard": "داشبورد",
|
||||
"text_field_city_id": "شهر",
|
||||
"text_field_error_fetching_cities": "لطفا شهر خود را وارد کنید!",
|
||||
"text_field_loading_cities_list": "درحال دریافت اطلاعات شهر ها...",
|
||||
"text_field_loading": "درحال دریافت اطلاعات",
|
||||
"text_field_error_fetching": "خطا در دریافت اطلاعات",
|
||||
"first_page": "خوش آمدید",
|
||||
"powered_by_witel": "توسعه یافته توسط وایتل",
|
||||
"login": "ورود",
|
||||
"today": "امروز",
|
||||
"pending": "درحال اجرا...",
|
||||
"login_user_panel": "ورود به پنل کاربران",
|
||||
"register_navy": "ثبت نام اعضای ناوگان",
|
||||
@@ -18,6 +26,8 @@
|
||||
"upload_file_text": "بارگذاری فایل",
|
||||
"online_message": "شما به اینترنت وصل هستید",
|
||||
"offline_message": "اتصال شما به اینترنت قطع شده است",
|
||||
"routing_to": "در حال انتقال به صفحه",
|
||||
"error_message_plate_number": "لطفا شماره پلاک خود را وارد کنید!",
|
||||
"header": {
|
||||
"open_profile": "پروفایل",
|
||||
"edit_profile": "ویرایش پروفایل",
|
||||
@@ -43,7 +53,7 @@
|
||||
"button_back_dashboard": "بازگشت به صفحه اصلی"
|
||||
},
|
||||
"Titles": {
|
||||
"title_login_page": "صفحه ورود",
|
||||
"title_login_page": "ورود به سامانه",
|
||||
"title_register_page": "صفحه ثبت نام",
|
||||
"title_login_navy_page": "ورود اعضای ناوگان",
|
||||
"title_login_welfare_services_page": "ورود اعضای خدمات رفاهی",
|
||||
@@ -122,51 +132,82 @@
|
||||
"loan_request_correction": "اصلاح درخواست",
|
||||
"loan_request_detail": "مشاهده جزئیات",
|
||||
"request_number": "درخواست شماره",
|
||||
"no_request_found": "درخواستی یافت نشد"
|
||||
"no_request_found": "درخواستی یافت نشد",
|
||||
"loan_unique_code": "کد یکتا",
|
||||
"loan_date": "تاریخ درخواست",
|
||||
"loan_status": "وضعیت",
|
||||
"loan_bank_branch": "اطلاعات شعبه",
|
||||
"loan_details": "نمایش"
|
||||
},
|
||||
"LoanRequest": {
|
||||
"finish_loan_request": "درخواست شما با موفقیت ثبت شد",
|
||||
"button_while_submit": "درحال بارگذاری ...",
|
||||
"checkbox": "بدینوسیله صحت کلیه اطلاعات مندرج در این فرم را تایید و گواهی میدهم .",
|
||||
"back_to_dashboard": "پیگیری درخواست ها",
|
||||
"cityList_empty": "ابتدا استان را وارد کنید",
|
||||
"cityList_loading": "درحال دریافت لیست شهر ها ...",
|
||||
"loan_request_page": "ثبت درخواست وام",
|
||||
"personal_info": "اطلاعات شخصی",
|
||||
"national_code_number": "کد ملی می بایست شامل اعداد باشد",
|
||||
"national_code_max": "کد ملی می بایست 10 رقم باشد",
|
||||
"shenasname_serial_max": "سریال پشت کارت ملی می بایست شامل 10 بخش باشد",
|
||||
"postal_code_max": "کد پستی می بایست 10 رقم باشد",
|
||||
"tel_number_max": "شماره ثابت می بایست 11 رقم باشد",
|
||||
"national_code_positive": "کد ملی می بایست مثبت باشد",
|
||||
"uploading_documents": "اسناد",
|
||||
"error_message_name": "لطفا نام خود را وارد کنید!",
|
||||
"error_message_phone_number": "لطفا شماره تلفن خود را وارد کنید!",
|
||||
"error_message_plate_number": "لطفا شماره پلاک را به درستی وارد کنید!",
|
||||
"error_message_occupation_id": "لطفا کد شغل را به درستی وارد کنید!",
|
||||
"error_message_education_id": "لطفا تحصیلات را به درستی وارد کنید!",
|
||||
"error_message_tel_number": "لطفا شماره ثابت (با پیش شماره استان) خود را وارد کنید!",
|
||||
"error_message_vehicle_type": "لطفا نوع وسیله نقلیه خود را وارد کنید!",
|
||||
"error_message_plate_number": "لطفا شماره پلاک خود را وارد کنید!",
|
||||
"error_message_navgan_id": "لطفا کد ناوگان خود را وارد کنید!",
|
||||
"error_message_navgan_id": "لطفا کد هوشمند ناوگان خود را وارد کنید!",
|
||||
"error_message_province_id": "لطفا استان خود را وارد کنید!",
|
||||
"error_message_national_id": "لطفا کد ملی خود را وارد کنید!",
|
||||
"error_message_shenasname_id": "لطفا شماره شناسنامه خود را وارد کنید!",
|
||||
"text_field_phone_number": "شماره تلفن",
|
||||
"text_field_enter_your_phone_number": "شماره تلفن خود را وارد کنید",
|
||||
"error_message_date_of_birth": "لطفا تاریخ تولد خود را وارد کنید!",
|
||||
"error_message_shenasname_serial": "لطفا سریال پشت کارت ملی خود را وارد کنید!",
|
||||
"error_message_postal_code": "لطفا کد پستی خود را وارد کنید!",
|
||||
"error_message_national_code": "لطفا کد ملی خود را وارد کنید!",
|
||||
"error_message_checkedBox": "لطفا کد صحت اطلاعات خود را تایید کنید!",
|
||||
"error_message_navgan_type": "لطفا نوع ناوگان خود را وارد کنید!",
|
||||
"error_message_address": "لطفا آدرس خود را وارد کنید!",
|
||||
"text_field_tel_number": "شماره ثابت (با پیش شماره استان)",
|
||||
"text_field_education_id": "تحصیلات",
|
||||
"text_field_occupation_id": "شغل",
|
||||
"text_field_enter_your_tel_number": "شماره ثابت (با پیش شماره استان) خود را وارد کنید",
|
||||
"text_field_name": "نام",
|
||||
"text_field_plate_part4": "بخش چهارم",
|
||||
"text_field_plate_part3": "بخش سوم",
|
||||
"text_field_plate_part2": "بخش دوم",
|
||||
"text_field_plate_part1": "بخش اول",
|
||||
"text_field_postal_code": "کد پستی",
|
||||
"text_field_navgan_type": "نوع ناوگان",
|
||||
"text_field_address": "آدرس",
|
||||
"text_field_enter_your_plate_part1": "بخش اول پلاک را وارد کنید",
|
||||
"text_field_enter_your_plate_part2": "بخش دوم پلاک را وارد کنید",
|
||||
"text_field_enter_your_plate_part3": "بخش سوم پلاک را وارد کنید",
|
||||
"text_field_enter_your_plate_part4": "بخش چهارم پلاک راوارد کنید",
|
||||
"text_field_enter_your_address": "آدرس خود راوارد کنید",
|
||||
"text_field_enter_your_name": "نام خود را وارد کنید",
|
||||
"text_field_vehicle_type": "نام وسیله نقلیه",
|
||||
"text_field_enter_your_vehicle_type": "نام وسیله نقلیه خود را وارد کنید",
|
||||
"text_field_enter_your_postal_code": "کد پستی خود را وارد کنید",
|
||||
"text_field_vehicle_type": "نوع وسیله نقلیه",
|
||||
"text_field_enter_your_vehicle_type": "نوع وسیله نقلیه خود را وارد کنید",
|
||||
"text_field_province_id": "استان",
|
||||
"text_field_loading_provinces_list": "درحال دریافت استان ها",
|
||||
"text_field_loading_provinces_list": "درحال دریافت استان ها ...",
|
||||
"text_field_error_fetching_provinces": "خطا در دریافت استان ها",
|
||||
"text_field_enter_your_national_code": "کد ملی خود را وارد کنید",
|
||||
"text_field_enter_your_province_id": "استان خود را وارد کنید",
|
||||
"text_field_navgan_id": "شماره ناوگان",
|
||||
"text_field_enter_your_navgan_id": "شماره ناوگان خود را وارد کنید",
|
||||
"text_field_enter_your_city_id": "شهر خود را وارد کنید",
|
||||
"text_field_navgan_id": "کد هوشمند ناوگان",
|
||||
"text_field_enter_your_navgan_id": "کد هوشمند ناوگان خود را وارد کنید",
|
||||
"text_field_national_code": "کد ملی",
|
||||
"text_field_enter_your_national_id": "کد ملی خود را وارد کنید",
|
||||
"text_field_shenasname_id": "شماره شناسنامه",
|
||||
"text_field_enter_your_shenasname_id": "شماره شناسنامه خود را وارد کنید",
|
||||
"text_field_shenasname_serial": "سریال پشت کارت ملی",
|
||||
"text_field_enter_your_shenasname_serial": "سریال پشت کارت ملی خود را وارد کنید",
|
||||
"text_field_plate_number": "شماره پلاک",
|
||||
"text_field_enter_your_plate_number": "شماره پلاک خود را وارد کنید",
|
||||
"button_submit": "ثبت درخواست",
|
||||
"file_field_sherkat_naft_doc": "مجوز شرکت نفت",
|
||||
"file_field_estate_doc": "سند مالکیت",
|
||||
"file_field_agreement_doc": "موافقت نامه اصولی",
|
||||
"error_message_sherkat_naft_doc": "مجوز شرکت نفت خود را وارد کنید",
|
||||
"error_message_estate_doc": "سند مالکیت خود را وارد کنید",
|
||||
"error_message_agreement_doc": "موافقت نامه اصولی خود را وارد کنید",
|
||||
"file_field_shenasname_image": "تصویر شناسنامه",
|
||||
"file_field_national_card_image": "تصویر کارت ملی",
|
||||
"file_field_payan_khedmat_image": "تصویر کارت پایان خدمت",
|
||||
"error_message_national_card_image": "تصویر کارت ملی خود را وارد کنید",
|
||||
"error_message_shenasname_image": "تصویر شناسنامه خود را وارد کنید",
|
||||
"error_message_payan_khedmat_image": "تصویر کارت پایان خدمت خود را وارد کنید",
|
||||
"error_message_city_id": "لطفا شهر خود را وارد کنید!",
|
||||
"add_loan_request_permission": "اکنون امکان ثبت درخواست جدید برای شما مقدور نیست"
|
||||
},
|
||||
"EditLoanRequest": {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"short_name": "Loan Facilities Dashboard",
|
||||
"short_name": "Loan Facilities",
|
||||
"name": "Loan Facilities User Dashboard",
|
||||
"description": "Loan Facilities",
|
||||
"version": "1.0.0",
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||
|
||||
const FirstComponent = () => {
|
||||
return <DashboardLayouts></DashboardLayouts>;
|
||||
return <></>;
|
||||
};
|
||||
|
||||
export default FirstComponent;
|
||||
|
||||
@@ -1,463 +1,471 @@
|
||||
import Notifications from "@/core/components/notifications";
|
||||
import SelectBox from "@/core/components/SelectBox";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import UploadSystem from "@/core/components/UploadSystem";
|
||||
import {GET_PROVINCE_LIST, SEND_LOAN_REQUEST_NAVGAN,} 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, Stack, TextField} from "@mui/material";
|
||||
import axios from "axios";
|
||||
import {Field, Formik} from "formik";
|
||||
import {Box, Button, Checkbox, FormControlLabel, Grid, Stack, TextField, Typography} from "@mui/material";
|
||||
import {useFormik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {useEffect, useState} from "react";
|
||||
import * as Yup from "yup";
|
||||
import {CenterLayout, useRequest} from "@witel/webapp-builder";
|
||||
import useProvince from "@/lib/app/hooks/useProvince";
|
||||
import useCities from "@/lib/app/hooks/useCities";
|
||||
import PlateNumber from "@/core/components/PlateNumber";
|
||||
import MuiDatePicker from "@/core/components/MuiDatePicker";
|
||||
import UseEducations from "@/lib/app/hooks/useEducations";
|
||||
import useOccupations from "@/lib/app/hooks/useOccupations";
|
||||
import {useState} from "react";
|
||||
import DoneIcon from '@mui/icons-material/Done';
|
||||
import {NextLinkComposed} from "@witel/webapp-builder/dist/utils/linkRouting";
|
||||
import SvgDone from "@/core/components/svgs/SvgDone";
|
||||
import {SEND_LOAN_REQUEST_NAVGAN} from "@/core/data/apiRoutes";
|
||||
|
||||
const AddFormComponent = () => {
|
||||
const t = useTranslations();
|
||||
const {directionApp} = useDirection();
|
||||
const {token} = useUser();
|
||||
const [finishLoanRequest, setFinishLoanRequest] = useState(false)
|
||||
const [checked, setChecked] = useState(false);
|
||||
const requestServer = useRequest()
|
||||
const {provinceList, isLoadingProvinceList, errorProvinceList} = useProvince()
|
||||
const {cityTextField, cityList, setProvinceID, isLoadingCityList} = useCities()
|
||||
const {educationsList, isLoadingEducationsList, errorEducationsList} = UseEducations()
|
||||
const {occupationsList, isLoadingOccupationsList, errorOccupationsList} = useOccupations()
|
||||
|
||||
// get province list
|
||||
const [provinceList, setProvinceList] = useState([]);
|
||||
useEffect(() => {
|
||||
axios
|
||||
.get(GET_PROVINCE_LIST, {
|
||||
headers: {Authorization: `Bearer ${token}`},
|
||||
})
|
||||
.then(({data}) => {
|
||||
const formattedData = data.map((province, index) => ({
|
||||
id: index,
|
||||
name: province.name,
|
||||
value: province.id,
|
||||
}));
|
||||
setProvinceList(formattedData);
|
||||
})
|
||||
.catch((error) => {
|
||||
Notifications(t, error.response);
|
||||
});
|
||||
}, []);
|
||||
// end get province list
|
||||
|
||||
// upload files
|
||||
const [selectedImageShenasname, setSelectedImageShenasname] = useState(
|
||||
"/images/upload-image.svg"
|
||||
);
|
||||
const [fileTypeShenasname, setFileTypeShenasname] = useState(null);
|
||||
const [fileNameShenasname, setFileNameShenasname] = useState(null);
|
||||
const [selectedImageNationalCard, setSelectedImageNationalCard] = useState(
|
||||
"/images/upload-image.svg"
|
||||
);
|
||||
const [fileTypeNationalCard, setFileTypeNationalCard] = useState(null);
|
||||
const [fileNameNationalCard, setFileNameNationalCard] = useState(null);
|
||||
|
||||
const handleUploadChangeShenasname = (event, setFieldValue) => {
|
||||
const uploadedFile = event.target?.files?.[0];
|
||||
if (uploadedFile) {
|
||||
const fileType = event.target?.files?.[0].type;
|
||||
const fileName = event.target?.files?.[0].name;
|
||||
setSelectedImageShenasname(URL.createObjectURL(uploadedFile));
|
||||
setFileTypeShenasname(fileType);
|
||||
setFileNameShenasname(fileName);
|
||||
setFieldValue("shenasname_img", uploadedFile);
|
||||
}
|
||||
};
|
||||
const handleUploadChangeNationalCard = (event, setFieldValue) => {
|
||||
const uploadedFile = event.target?.files?.[0];
|
||||
const fileType = event.target.files[0].type;
|
||||
const fileName = event.target.files[0].name;
|
||||
if (uploadedFile) {
|
||||
setSelectedImageNationalCard(URL.createObjectURL(uploadedFile));
|
||||
setFileTypeNationalCard(fileType);
|
||||
setFileNameNationalCard(fileName);
|
||||
setFieldValue("national_card_img", uploadedFile);
|
||||
}
|
||||
};
|
||||
// end upload files
|
||||
|
||||
// initial values
|
||||
const initialValues = {
|
||||
name: "",
|
||||
phone_number: "",
|
||||
telephone_number: "",
|
||||
vehicle_type: "",
|
||||
plate_number: "",
|
||||
province_id: "",
|
||||
city_id: "",
|
||||
navgan_id: "",
|
||||
national_code: "",
|
||||
shenasname_id: "",
|
||||
national_card_img: null,
|
||||
shenasname_img: null,
|
||||
national_id: "",
|
||||
national_serial_number: "",
|
||||
postal_code: "",
|
||||
navgan_type: "",
|
||||
plate_part1: "",
|
||||
plate_part2: "الف",
|
||||
plate_part3: "",
|
||||
plate_part4: "",
|
||||
address: "",
|
||||
birthday: "",
|
||||
education_id: "",
|
||||
occupation_id: "",
|
||||
checkedBox: false
|
||||
};
|
||||
// end initial values
|
||||
|
||||
// validation
|
||||
const validationSchema = Yup.object().shape({
|
||||
name: Yup.string().required(t("LoanRequest.error_message_name")),
|
||||
phone_number: Yup.string().required(
|
||||
t("LoanRequest.error_message_phone_number")
|
||||
),
|
||||
telephone_number: Yup.mixed()
|
||||
.test("max", `${t("LoanRequest.tel_number_max")}`, (value) => {
|
||||
const stringValue = String(value);
|
||||
return stringValue.length === 11
|
||||
})
|
||||
.required(t("LoanRequest.error_message_tel_number")),
|
||||
vehicle_type: Yup.string().required(
|
||||
t("LoanRequest.error_message_vehicle_type")
|
||||
),
|
||||
plate_number: Yup.string().required(
|
||||
t("LoanRequest.error_message_plate_number")
|
||||
navgan_type: Yup.string().required(
|
||||
t("LoanRequest.error_message_navgan_type")
|
||||
),
|
||||
navgan_id: Yup.string().required(t("LoanRequest.error_message_navgan_id")),
|
||||
occupation_id: Yup.string().required(
|
||||
t("LoanRequest.error_message_occupation_id")
|
||||
),
|
||||
education_id: Yup.string().required(
|
||||
t("LoanRequest.error_message_education_id")
|
||||
),
|
||||
address: Yup.string().required(
|
||||
t("LoanRequest.error_message_address")
|
||||
),
|
||||
birthday: Yup.string().required(
|
||||
t("LoanRequest.error_message_date_of_birth")
|
||||
),
|
||||
postal_code: Yup.mixed()
|
||||
.test("max", `${t("LoanRequest.postal_code_max")}`, (value) => value.toString().length === 10)
|
||||
.required(
|
||||
t("LoanRequest.error_message_postal_code")
|
||||
),
|
||||
plate_part1: Yup.mixed().test("max", `${t("LoanRequest.error_message_plate_number")}`, (value) => value.toString().length === 2)
|
||||
.required(
|
||||
t("LoanRequest.error_message_plate_number")
|
||||
),
|
||||
plate_part2: Yup.mixed()
|
||||
.required(
|
||||
t("LoanRequest.error_message_plate_number")
|
||||
),
|
||||
plate_part3: Yup.mixed().test("max", `${t("LoanRequest.error_message_plate_number")}`, (value) => value.toString().length === 3)
|
||||
.required(
|
||||
t("LoanRequest.error_message_plate_number")
|
||||
),
|
||||
plate_part4: Yup.mixed().test("max", `${t("LoanRequest.error_message_plate_number")}`, (value) => value.toString().length === 2)
|
||||
.required(
|
||||
t("LoanRequest.error_message_plate_number")
|
||||
),
|
||||
navgan_id: Yup.mixed().required(t("LoanRequest.error_message_navgan_id")),
|
||||
province_id: Yup.string().required(t("LoanRequest.error_message_province_id")),
|
||||
national_code: Yup.string().required(
|
||||
t("LoanRequest.error_message_national_code")
|
||||
),
|
||||
shenasname_id: Yup.string().required(
|
||||
t("LoanRequest.error_message_shenasname_id")
|
||||
),
|
||||
city_id: Yup.string().required(t("LoanRequest.error_message_city_id")),
|
||||
national_id: Yup.mixed()
|
||||
.test("is-number", `${t("LoanRequest.national_code_number")}`,
|
||||
(value) => !isNaN(value))
|
||||
.test("positive", `${t("LoanRequest.national_code_positive")}`, (value) => value >= 0)
|
||||
.test("max", `${t("LoanRequest.national_code_max")}`, (value) => value.toString().length === 10)
|
||||
.required(t("LoanRequest.error_message_national_id")),
|
||||
national_serial_number: Yup.string().required(t("LoanRequest.error_message_shenasname_serial")),
|
||||
});
|
||||
// end validation
|
||||
|
||||
// submit
|
||||
|
||||
const handleSubmit = async (values, props) => {
|
||||
Notifications(t, undefined);
|
||||
const formData = new FormData();
|
||||
formData.append("name", values.name);
|
||||
formData.append("phone_number", values.phone_number);
|
||||
formData.append("vehicle_type", values.vehicle_type);
|
||||
formData.append("plate_number", values.plate_number);
|
||||
formData.append("province_id", values.province_id);
|
||||
formData.append("navgan_id", values.navgan_id);
|
||||
formData.append("national_code", values.national_code);
|
||||
formData.append("shenasname_id", values.shenasname_id);
|
||||
if (values.shenasname_img != null)
|
||||
formData.append("shenasname_image", values.shenasname_img);
|
||||
if (values.national_card_img != null)
|
||||
formData.append("national_card_image", values.national_card_img);
|
||||
props.setSubmitting(true)
|
||||
|
||||
await axios
|
||||
.post(SEND_LOAN_REQUEST_NAVGAN, formData, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
})
|
||||
.then(function (response) {
|
||||
Notifications(t, response);
|
||||
})
|
||||
.catch(function (error) {
|
||||
Notifications(t, error.response);
|
||||
props.setSubmitting(false);
|
||||
});
|
||||
await requestServer(SEND_LOAN_REQUEST_NAVGAN, "post", {
|
||||
auth: true, notification: true, data: {
|
||||
telephone_number: values.telephone_number,
|
||||
vehicle_type: values.vehicle_type,
|
||||
province_id: values.province_id,
|
||||
city_id: values.city_id,
|
||||
navgan_id: values.navgan_id,
|
||||
national_id: values.national_id,
|
||||
national_serial_number: values.national_serial_number,
|
||||
postal_code: values.postal_code,
|
||||
navgan_type: values.navgan_type,
|
||||
plate_part1: values.plate_part1,
|
||||
plate_part2: values.plate_part2,
|
||||
plate_part3: values.plate_part3,
|
||||
plate_part4: values.plate_part4,
|
||||
address: values.address,
|
||||
birthday: values.birthday.locale('en').format("YYYY-MM-DD"),
|
||||
education_id: values.education_id,
|
||||
occupation_id: values.occupation_id,
|
||||
}
|
||||
}).then(() => {
|
||||
setFinishLoanRequest(true)
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
props.setSubmitting(false)
|
||||
})
|
||||
};
|
||||
// end submit
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues, validationSchema, onSubmit: handleSubmit
|
||||
})
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validationSchema={validationSchema}
|
||||
>
|
||||
{(props) => (
|
||||
<Stack
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 1,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<StyledForm sx={{width: "100%"}}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: {xs: "column", sm: "row"},
|
||||
alignItems: "start",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}
|
||||
<>
|
||||
{finishLoanRequest ?
|
||||
(
|
||||
<CenterLayout>
|
||||
<SvgDone width={200} height={200}/>
|
||||
<Stack direction={'row'} spacing={0.7} sx={{mb: 4}}>
|
||||
<Typography variant={'h5'}
|
||||
align={'center'}>{t("LoanRequest.finish_loan_request")}</Typography>
|
||||
<DoneIcon color={'success'}/>
|
||||
</Stack>
|
||||
<Button variant={'contained'} component={NextLinkComposed}
|
||||
to={'/dashboard/navgan/followUp-loan'}>
|
||||
{t("LoanRequest.back_to_dashboard")}
|
||||
</Button>
|
||||
</CenterLayout>
|
||||
) : (
|
||||
<>
|
||||
<Grid container spacing={2} sx={{padding: 2}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
<Grid item xs={12} sm={4}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
<TextField
|
||||
sx={{width: "100%"}}
|
||||
name="name"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_name")}
|
||||
placeholder={t("LoanRequest.text_field_enter_your_name")}
|
||||
type={"text"}
|
||||
error={props.touched.name && props.errors.name ? true : false}
|
||||
fullWidth
|
||||
helperText={props.touched.name ? props.errors.name : null}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="phone_number"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_phone_number")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_phone_number"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
props.touched.phone_number && props.errors.phone_number
|
||||
? true
|
||||
: false
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.phone_number
|
||||
? props.errors.phone_number
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: {xs: "column", sm: "row"},
|
||||
alignItems: "start",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="vehicle_type"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_vehicle_type")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_vehicle_type"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
props.touched.vehicle_type && props.errors.vehicle_type
|
||||
? true
|
||||
: false
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.vehicle_type
|
||||
? props.errors.vehicle_type
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="plate_number"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_plate_number")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_plate_number"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
props.touched.plate_number && props.errors.plate_number
|
||||
? true
|
||||
: false
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.plate_number
|
||||
? props.errors.plate_number
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
name="province_id"
|
||||
label={t("LoanRequest.text_field_province_id")} // t("LoanRequest.text_field_enter_your_province")
|
||||
size="small"
|
||||
selectType="province_id"
|
||||
component={SelectBox}
|
||||
selectors={provinceList}
|
||||
select={props.values.province_id}
|
||||
setFieldValue={props.setFieldValue}
|
||||
setFieldTouched={props.setFieldTouched}
|
||||
error={
|
||||
props.touched.gender && props.errors.province_id ? true : false
|
||||
}
|
||||
helperText={
|
||||
props.touched.gender ? props.errors.province_id : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: {xs: "column", sm: "row"},
|
||||
alignItems: "start",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="navgan_id"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_navgan_id")}
|
||||
placeholder={t("LoanRequest.text_field_enter_your_navgan_id")}
|
||||
type={"text"}
|
||||
error={
|
||||
props.touched.navgan_id && props.errors.navgan_id
|
||||
? true
|
||||
: false
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.navgan_id ? props.errors.navgan_id : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="national_code"
|
||||
name="national_id"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
inputProps={{inputMode: 'numeric', pattern: '[0-9]*'}}
|
||||
type={'tel'}
|
||||
onChange={formik.handleChange}
|
||||
label={t("LoanRequest.text_field_national_code")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_national_code"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
props.touched.national_code && props.errors.national_code
|
||||
? true
|
||||
: false
|
||||
}
|
||||
onBlur={formik.handleBlur("national_id")}
|
||||
error={formik.touched.national_id && Boolean(formik.errors.national_id)}
|
||||
helperText={formik.touched.national_id && formik.errors.national_id}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.national_code
|
||||
? props.errors.national_code
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
<TextField
|
||||
sx={{width: "100%"}}
|
||||
name="shenasname_id"
|
||||
name="national_serial_number"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_shenasname_id")}
|
||||
label={t("LoanRequest.text_field_shenasname_serial")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_shenasname_id"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
props.touched.shenasname_id && props.errors.shenasname_id
|
||||
? true
|
||||
: false
|
||||
}
|
||||
"LoanRequest.text_field_enter_your_shenasname_serial")}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.shenasname_id
|
||||
? props.errors.shenasname_id
|
||||
: null
|
||||
}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur("national_serial_number")}
|
||||
error={formik.touched.national_serial_number && Boolean(formik.errors.national_serial_number)}
|
||||
helperText={formik.touched.national_serial_number && formik.errors.national_serial_number}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: {xs: "column", sm: "row"},
|
||||
alignItems: "center",
|
||||
justifyContent: "space-around",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<UploadSystem
|
||||
selectedImage={selectedImageShenasname}
|
||||
handleUploadChange={(e) =>
|
||||
handleUploadChangeShenasname(e, props.setFieldValue)
|
||||
}
|
||||
setselectedImage={setSelectedImageShenasname}
|
||||
setFieldValue={props.setFieldValue}
|
||||
fieldname="shenasname_img"
|
||||
fileType={fileTypeShenasname}
|
||||
fileName={fileNameShenasname}
|
||||
imageAlt={t("app_name")}
|
||||
imageSize={[300 /*width*/, 150 /*height*/]}
|
||||
label={t("LoanRequest.file_field_shenasname_image")}
|
||||
/>
|
||||
<UploadSystem
|
||||
selectedImage={selectedImageNationalCard}
|
||||
handleUploadChange={(e) =>
|
||||
handleUploadChangeNationalCard(e, props.setFieldValue)
|
||||
}
|
||||
setselectedImage={setSelectedImageNationalCard}
|
||||
setFieldValue={props.setFieldValue}
|
||||
fieldname="national_card_img"
|
||||
fileType={fileTypeNationalCard}
|
||||
fileName={fileNameNationalCard}
|
||||
imageAlt={t("app_name")}
|
||||
imageSize={[300 /*width*/, 150 /*height*/]}
|
||||
label={t("LoanRequest.file_field_national_card_image")}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<MuiDatePicker
|
||||
formik={formik}
|
||||
error={formik.touched.birthday && Boolean(formik.errors.birthday)}
|
||||
helperText={formik.touched.birthday && formik.errors.birthday}
|
||||
onBlur={formik.handleBlur("birthday")}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={2} sx={{padding: 2}}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
sx={{width: "100%"}}
|
||||
name="postal_code"
|
||||
variant="outlined"
|
||||
inputProps={{inputMode: 'numeric', pattern: '[0-9]*'}}
|
||||
type={'tel'}
|
||||
onChange={formik.handleChange}
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_postal_code")}
|
||||
placeholder={t("LoanRequest.text_field_enter_your_postal_code")}
|
||||
fullWidth
|
||||
onBlur={formik.handleBlur("postal_code")}
|
||||
error={formik.touched.postal_code && Boolean(formik.errors.postal_code)}
|
||||
helperText={formik.touched.postal_code && formik.errors.postal_code}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
sx={{width: "100%"}}
|
||||
name="telephone_number"
|
||||
variant="outlined"
|
||||
value={formik.values.telephone_number}
|
||||
inputProps={{inputMode: 'numeric', pattern: '[0-9]*'}}
|
||||
type={'tel'}
|
||||
size="small"
|
||||
onChange={(event) => {
|
||||
const inputValue = event.target.value;
|
||||
if (isNaN(Number(inputValue))) {
|
||||
return;
|
||||
}
|
||||
formik.handleChange({
|
||||
target: {
|
||||
name: "telephone_number",
|
||||
value: inputValue,
|
||||
},
|
||||
});
|
||||
}}
|
||||
label={t("LoanRequest.text_field_tel_number")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_tel_number"
|
||||
)}
|
||||
fullWidth
|
||||
onBlur={formik.handleBlur("telephone_number")}
|
||||
error={formik.touched.telephone_number && Boolean(formik.errors.telephone_number)}
|
||||
helperText={formik.touched.telephone_number && formik.errors.telephone_number}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={2} sx={{padding: 2}}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<SelectBox
|
||||
name="navgan_type"
|
||||
label={t("LoanRequest.text_field_navgan_type")}
|
||||
size="small"
|
||||
selectType="navgan_type"
|
||||
selectors={[
|
||||
{
|
||||
id: 1,
|
||||
value: "روستایی",
|
||||
name: "روستایی"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: "عمومی",
|
||||
name: "عمومی"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
value: "منطقه آزاد",
|
||||
name: "منطقه آزاد"
|
||||
}
|
||||
]}
|
||||
schema={{value: 'value', name: 'name'}}
|
||||
select={formik.values.navgan_type}
|
||||
handleChange={(event) => {
|
||||
formik.setFieldValue('navgan_type', event.target.value)
|
||||
}}
|
||||
setFieldTouched={formik.setFieldTouched}
|
||||
error={formik.touched.navgan_type && Boolean(formik.errors.navgan_type)}
|
||||
helperText={formik.touched.navgan_type && formik.errors.navgan_type}
|
||||
onBlur={formik.handleBlur("navgan_type")}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
sx={{width: "100%"}}
|
||||
name="navgan_id"
|
||||
variant="outlined"
|
||||
inputProps={{inputMode: 'numeric', pattern: '[0-9]*'}}
|
||||
type={'tel'}
|
||||
onChange={formik.handleChange}
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_navgan_id")}
|
||||
placeholder={t("LoanRequest.text_field_enter_your_navgan_id")}
|
||||
fullWidth
|
||||
onBlur={formik.handleBlur("navgan_id")}
|
||||
error={formik.touched.navgan_id && Boolean(formik.errors.navgan_id)}
|
||||
helperText={formik.touched.navgan_id && formik.errors.navgan_id}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={2} sx={{padding: 2}}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<SelectBox
|
||||
name="province_id"
|
||||
label={t("LoanRequest.text_field_province_id")}
|
||||
size="small"
|
||||
selectType="province_id"
|
||||
isLoading={isLoadingProvinceList}
|
||||
errorEcured={errorProvinceList}
|
||||
selectors={provinceList}
|
||||
schema={{value: 'value', name: 'name'}}
|
||||
select={formik.values.province_id}
|
||||
handleChange={(event) => {
|
||||
formik.setFieldValue('province_id', event.target.value);
|
||||
setProvinceID(event.target.value)
|
||||
formik.setFieldTouched("city_id", false, false);
|
||||
formik.setFieldValue("city_id", "")
|
||||
}}
|
||||
setFieldTouched={formik.setFieldTouched}
|
||||
error={formik.touched.province_id && Boolean(formik.errors.province_id)}
|
||||
helperText={formik.touched.province_id && formik.errors.province_id}
|
||||
onBlur={formik.handleBlur("province_id")}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<SelectBox
|
||||
name="city_id"
|
||||
label={isLoadingCityList ? `${t("LoanRequest.cityList_loading")}` : (cityList.length === 0 ? `${t("LoanRequest.cityList_empty")}` : cityTextField)}
|
||||
size="small"
|
||||
selectType="city_id"
|
||||
schema={{value: 'value', name: 'name'}}
|
||||
disabled={cityList.length === 0}
|
||||
selectors={cityList}
|
||||
select={formik.values.city_id}
|
||||
handleChange={(event) => formik.setFieldValue('city_id', event.target.value)}
|
||||
setFieldTouched={formik.setFieldTouched}
|
||||
error={formik.touched.city_id && Boolean(formik.errors.city_id)}
|
||||
helperText={formik.touched.city_id && formik.errors.city_id}
|
||||
onBlur={formik.handleBlur("city_id")}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={2} sx={{padding: 2}}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<SelectBox
|
||||
name="vehicle_type"
|
||||
label={t("LoanRequest.text_field_vehicle_type")}
|
||||
size="small"
|
||||
schema={{value: 'value', name: 'name'}}
|
||||
selectType="vehicle_type"
|
||||
selectors={[
|
||||
{
|
||||
id: 0,
|
||||
value: "اتوبوس",
|
||||
name: "اتوبوس"
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
value: "مینی بوس",
|
||||
name: "مینی بوس"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: "سواری",
|
||||
name: "سواری"
|
||||
}
|
||||
]}
|
||||
select={formik.values.vehicle_type}
|
||||
handleChange={(event) => formik.setFieldValue('vehicle_type', event.target.value)}
|
||||
error={formik.touched.vehicle_type && Boolean(formik.errors.vehicle_type)}
|
||||
helperText={formik.touched.vehicle_type && formik.errors.vehicle_type}
|
||||
onBlur={formik.handleBlur("vehicle_type")}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<PlateNumber formik={formik}/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={2} sx={{padding: 2}}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<SelectBox
|
||||
name="education_id"
|
||||
label={t("LoanRequest.text_field_education_id")}
|
||||
size="small"
|
||||
isLoading={isLoadingEducationsList}
|
||||
errorEcured={errorEducationsList}
|
||||
selectType="education_id"
|
||||
selectors={educationsList}
|
||||
select={formik.values.education_id}
|
||||
schema={{value: 'id', name: 'title'}}
|
||||
handleChange={(event) => {
|
||||
formik.setFieldValue('education_id', event.target.value)
|
||||
}}
|
||||
setFieldTouched={formik.setFieldTouched}
|
||||
error={formik.touched.education_id && Boolean(formik.errors.education_id)}
|
||||
helperText={formik.touched.education_id && formik.errors.education_id}
|
||||
onBlur={formik.handleBlur("education_id")}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<SelectBox
|
||||
name="occupation_id"
|
||||
label={t("LoanRequest.text_field_occupation_id")}
|
||||
size="small"
|
||||
isLoading={isLoadingOccupationsList}
|
||||
errorEcured={errorOccupationsList}
|
||||
selectType="occupation_id"
|
||||
schema={{value: 'id', name: 'title'}}
|
||||
selectors={occupationsList}
|
||||
select={formik.values.occupation_id}
|
||||
handleChange={(event) => {
|
||||
formik.setFieldValue('occupation_id', event.target.value)
|
||||
}}
|
||||
setFieldTouched={formik.setFieldTouched}
|
||||
error={formik.touched.occupation_id && Boolean(formik.errors.occupation_id)}
|
||||
helperText={formik.touched.occupation_id && formik.errors.occupation_id}
|
||||
onBlur={formik.handleBlur("occupation_id")}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={2} sx={{padding: 2}}>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
multiline
|
||||
rows={8}
|
||||
sx={{width: "100%"}}
|
||||
name="address"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_address")}
|
||||
placeholder={t("LoanRequest.text_field_enter_your_address")}
|
||||
fullWidth
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur("address")}
|
||||
error={formik.touched.address && Boolean(formik.errors.address)}
|
||||
helperText={formik.touched.address && formik.errors.address}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={2} sx={{padding: 2}}>
|
||||
<Grid item xs={12}>
|
||||
<FormControlLabel
|
||||
color={'error.main'}
|
||||
control={
|
||||
<Checkbox
|
||||
checked={formik.values.checkedBox}
|
||||
onChange={(event) => {
|
||||
formik.setFieldValue("checkedBox", event.target.checked)
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={`${t("LoanRequest.checkbox")}`}/>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
@@ -469,20 +477,23 @@ const AddFormComponent = () => {
|
||||
>
|
||||
<Button
|
||||
fullWidth
|
||||
onClick={formik.handleSubmit}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="large"
|
||||
sx={{mt: 2}}
|
||||
sx={{my: 4}}
|
||||
endIcon={<DataSaverOnIcon/>}
|
||||
disabled={props.isSubmitting ? true : false}
|
||||
disabled={formik.values.checkedBox ? (formik.isSubmitting || !formik.dirty || !formik.isValid) : true}
|
||||
>
|
||||
{t("LoanRequest.button_submit")}
|
||||
{formik.isSubmitting
|
||||
? t("LoanRequest.button_while_submit")
|
||||
: t("LoanRequest.button_submit")}
|
||||
</Button>
|
||||
</Box>
|
||||
</StyledForm>
|
||||
</Stack>
|
||||
)}
|
||||
</Formik>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,29 +1,21 @@
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
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/navgan/add-request-loan/forms/AddForm";
|
||||
|
||||
const LoanRequestComponent = () => {
|
||||
const t = useTranslations();
|
||||
const {user} = useUser();
|
||||
|
||||
return (
|
||||
<DashboardLayouts>
|
||||
<CenterLayout>
|
||||
<Box sx={{width: "80%", my: 2}}>
|
||||
<>
|
||||
<Box>
|
||||
<Divider>
|
||||
<Chip
|
||||
label={`${t("LoanRequest.loan_request_page")} | ${
|
||||
user.type_name
|
||||
}`}
|
||||
label={`${t("LoanRequest.loan_request_page")} | ${t("user_navy")} `}
|
||||
/>
|
||||
</Divider>
|
||||
</Box>
|
||||
<AddFormComponent/>
|
||||
</CenterLayout>
|
||||
</DashboardLayouts>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,25 +1,50 @@
|
||||
import {Card, CardContent, CardHeader, Grid, Typography} from "@mui/material";
|
||||
import SellIcon from '@mui/icons-material/Sell';
|
||||
import {Box, Button, Card, CardContent, Grid, Typography} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
|
||||
import moment from "jalali-moment";
|
||||
import {LinkRouting} from "@witel/webapp-builder";
|
||||
import AccessTimeFilledIcon from '@mui/icons-material/AccessTimeFilled';
|
||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
|
||||
const RequestCard = ({item}) => {
|
||||
const t = useTranslations();
|
||||
return (
|
||||
<Grid item xs={12} md={6} lg={4}>
|
||||
<Grid item xs={12} lg={6} xl={4}>
|
||||
<Card sx={{
|
||||
width: "100%",
|
||||
boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px"
|
||||
}}>
|
||||
<CardHeader
|
||||
avatar={<SellIcon color="primary"/>}
|
||||
title={`${t("LoanFollowUp.request_number")}: (${item.id})`}
|
||||
subheader={item.latest_history_created_at}
|
||||
/>
|
||||
<CardContent sx={{pt: 0}}>
|
||||
<Typography variant="button">
|
||||
{item.loan_state}
|
||||
<CardContent sx={{display: 'flex', flexDirection: 'column', alignItems: 'flex-start' , paddingBottom: '16px !important'}}>
|
||||
<Box
|
||||
sx={{
|
||||
borderLeft: '6px solid',
|
||||
borderColor: 'primary.main',
|
||||
borderRadius: '6px 0px 0px 6px',
|
||||
paddingLeft: '10px',
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6" sx={{lineHeight: 2 , fontWeight:'bold'}}>
|
||||
{`${t("LoanFollowUp.loan_unique_code")}: ${item.id}`}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Typography variant="body1" sx={{lineHeight: 2 , paddingLeft: '20px'}}>
|
||||
{`${t("LoanFollowUp.loan_date")}: ${moment(item.created_at).locale("fa").format("HH:mm | YYYY/MM/DD")}`}
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{lineHeight: 2 , paddingLeft: '20px'}}>
|
||||
{`${t("LoanFollowUp.loan_bank_branch")}: ${item.branch_info === null ? '-' : item.branch_info}`}
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{lineHeight: 2 , paddingLeft: '20px'}}>
|
||||
{`${t("LoanFollowUp.loan_status")}: `}
|
||||
{item.loan_state}
|
||||
{item.state_id >= 1 && item.state_id <= 6 && <AccessTimeFilledIcon sx={{verticalAlign: 'middle', marginLeft: '4px' , color: '#48a4df'}}/>}
|
||||
{item.state_id === 8 && <CheckCircleIcon sx={{verticalAlign: 'middle', marginLeft: '4px', color: 'green'}}/>}
|
||||
{item.state_id === 7 && <CancelIcon sx={{verticalAlign: 'middle', marginLeft: '4px', color: 'red'}}/>}
|
||||
</Typography>
|
||||
<Button variant="contained" color="primary" sx={{alignSelf: 'flex-end'}}>
|
||||
<LinkRouting underline="none" color="inherit" href={`/dashboard/navgan/${item.id}/show`}>
|
||||
{t("LoanFollowUp.loan_details")}
|
||||
</LinkRouting>
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
|
||||
@@ -1,59 +1,44 @@
|
||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||
import {
|
||||
Grid,
|
||||
Stack,
|
||||
} from "@mui/material";
|
||||
import { Grid } from "@mui/material";
|
||||
import {useEffect, useState} from "react";
|
||||
import {SHOW_LOAN_REQUEST_NAVGAN} 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/navgan/followUp-loan/RequestCard";
|
||||
import {FullPageLayout , useRequest} from "@witel/webapp-builder";
|
||||
|
||||
const LoanFollowUpComponent = () => {
|
||||
const requestServer = useRequest();
|
||||
const {setLoadingPage} = useLoading();
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [requestsList, setRequestsList] = useState([]);
|
||||
// get form data
|
||||
useEffect(() => {
|
||||
setLoadingPage(true)
|
||||
requestServer(SHOW_LOAN_REQUEST_NAVGAN, "get", {auth: true, notification: false})
|
||||
setIsLoading(true)
|
||||
requestServer(SHOW_LOAN_REQUEST_NAVGAN, "get", {
|
||||
auth: true,
|
||||
pending:false,
|
||||
success:{notification:{show:false}}
|
||||
})
|
||||
.then(function ({data}) {
|
||||
const items = data.data;
|
||||
const formattedData = items.map((item, index) => ({
|
||||
id: item.id,
|
||||
latest_history_created_at: moment(item.latest_history_created_at).locale("fa").format("HH:mm | YYYY/MM/DD"),
|
||||
state_id: item.state_id,
|
||||
loan_state: item.loan_state,
|
||||
}));
|
||||
setRequestsList(formattedData);
|
||||
setLoadingPage(false)
|
||||
setRequestsList(items);
|
||||
setIsLoading(false)
|
||||
})
|
||||
.catch(function (error) {
|
||||
})
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<DashboardLayouts>
|
||||
<Stack
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 4,
|
||||
width: "100%",
|
||||
}}
|
||||
<FullPageLayout>
|
||||
<Grid
|
||||
container
|
||||
columnSpacing={2}
|
||||
rowSpacing={2}
|
||||
sx={{alignItems: "start", justifyContent: "center", padding: "24px"}}
|
||||
>
|
||||
<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) => (
|
||||
<RequestCard item={item} key={item.id}/>
|
||||
))}
|
||||
</Grid>
|
||||
</FullPageLayout>
|
||||
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
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,439 +0,0 @@
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import UploadSystem from "@/core/components/UploadSystem";
|
||||
import {SEND_LOAN_REQUEST_WELFARE} from "@/core/data/apiRoutes";
|
||||
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
|
||||
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 * as Yup from "yup";
|
||||
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 requestServer = useRequest()
|
||||
const {provinceList, isLoadingProvinceList, errorProvinceList} = useProvince();
|
||||
const router = useRouter();
|
||||
|
||||
// initial values, validation and request action of form
|
||||
const initialValues = {
|
||||
name: "",
|
||||
phone_number: "",
|
||||
province_id: "",
|
||||
national_id: "",
|
||||
shenasname_id: "",
|
||||
sherkat_naft_doc: null,
|
||||
estate_doc: null,
|
||||
agreement_doc: null,
|
||||
national_card_image: null,
|
||||
shenasname_image: null,
|
||||
payan_khedmat_image: null,
|
||||
};
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
name: Yup.string().required(t("LoanRequest.error_message_name")),
|
||||
phone_number: Yup.string().required(
|
||||
t("LoanRequest.error_message_phone_number")
|
||||
),
|
||||
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")),
|
||||
agreement_doc: Yup.mixed().required(t("LoanRequest.error_message_agreement_doc")),
|
||||
national_card_image: Yup.mixed().required(t("LoanRequest.error_message_national_card_image")),
|
||||
shenasname_image: Yup.mixed().required(t("LoanRequest.error_message_shenasname_image")),
|
||||
payan_khedmat_image: Yup.mixed().required(t("LoanRequest.error_message_payan_khedmat_image")),
|
||||
});
|
||||
const handleSubmit = (values, props) => {
|
||||
const formData = new FormData();
|
||||
formData.append("name", values.name);
|
||||
formData.append("phone_number", values.phone_number);
|
||||
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);
|
||||
if (values.estate_doc != null)
|
||||
formData.append("estate_doc", values.estate_doc);
|
||||
if (values.agreement_doc != null)
|
||||
formData.append("agreement_doc", values.agreement_doc);
|
||||
if (values.shenasname_image != null)
|
||||
formData.append("shenasname_image", values.shenasname_image);
|
||||
if (values.national_card_image != null)
|
||||
formData.append("national_card_image", values.national_card_image);
|
||||
if (values.payan_khedmat_image != null)
|
||||
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) {
|
||||
})
|
||||
.finally(function () {
|
||||
props.setSubmitting(false);
|
||||
});
|
||||
};
|
||||
// end initial values, validation and request action of form
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validationSchema={validationSchema}
|
||||
>
|
||||
{(props) => (
|
||||
<Stack
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 1,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<StyledForm sx={{width: "100%"}}>
|
||||
<Box sx={{my: 1}}>
|
||||
<Divider>
|
||||
<Chip
|
||||
label={t("LoanRequest.personal_info")}
|
||||
/>
|
||||
</Divider>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: {xs: "column", sm: "row"},
|
||||
alignItems: "start",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="name"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_name")}
|
||||
placeholder={t("LoanRequest.text_field_enter_your_name")}
|
||||
type={"text"}
|
||||
error={!!(props.touched.name && props.errors.name)}
|
||||
fullWidth
|
||||
helperText={props.touched.name ? props.errors.name : null}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="phone_number"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_phone_number")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_phone_number"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
!!(props.touched.phone_number && props.errors.phone_number)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.phone_number
|
||||
? props.errors.phone_number
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
mt: 0,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<FormControl
|
||||
error={props.touched.province_id && !!props.errors.province_id}
|
||||
sx={{width: "100%", mt: 2}}
|
||||
size="small"
|
||||
>
|
||||
<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
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: {xs: "column", sm: "row"},
|
||||
alignItems: "start",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="national_id"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_national_id")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_national_id"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
!!(props.touched.national_id && props.errors.national_id)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.national_id
|
||||
? props.errors.national_id
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="shenasname_id"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_shenasname_id")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_shenasname_id"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
!!(props.touched.shenasname_id && props.errors.shenasname_id)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.shenasname_id
|
||||
? props.errors.shenasname_id
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={{my: 1}}>
|
||||
<Divider>
|
||||
<Chip
|
||||
label={t("LoanRequest.uploading_documents")}
|
||||
/>
|
||||
</Divider>
|
||||
</Box>
|
||||
<Stack spacing={{xs: 1, sm: 2}} direction="row" useFlexGap flexWrap="wrap"
|
||||
sx={{justifyContent: "center"}}>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
fieldName="sherkat_naft_doc"
|
||||
imageAlt={t("app_name")}
|
||||
label={t("LoanRequest.file_field_sherkat_naft_doc")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.sherkat_naft_doc && props.errors.sherkat_naft_doc)
|
||||
}
|
||||
helperText={
|
||||
props.touched.sherkat_naft_doc ? props.errors.sherkat_naft_doc : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
fieldName="estate_doc"
|
||||
imageAlt={t("app_name")}
|
||||
label={t("LoanRequest.file_field_estate_doc")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.estate_doc && props.errors.estate_doc)
|
||||
}
|
||||
helperText={
|
||||
props.touched.estate_doc ? props.errors.estate_doc : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
fieldName="agreement_doc"
|
||||
imageAlt={t("app_name")}
|
||||
label={t("LoanRequest.file_field_agreement_doc")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.agreement_doc && props.errors.agreement_doc)
|
||||
}
|
||||
helperText={
|
||||
props.touched.agreement_doc ? props.errors.agreement_doc : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
fieldName="shenasname_image"
|
||||
imageAlt={t("app_name")}
|
||||
label={t("LoanRequest.file_field_shenasname_image")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.shenasname_image && props.errors.shenasname_image)
|
||||
}
|
||||
helperText={
|
||||
props.touched.shenasname_image ? props.errors.shenasname_image : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
fieldName="payan_khedmat_image"
|
||||
imageAlt={t("app_name")}
|
||||
label={t("LoanRequest.file_field_payan_khedmat_image")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.payan_khedmat_image && props.errors.payan_khedmat_image)
|
||||
}
|
||||
helperText={
|
||||
props.touched.payan_khedmat_image ? props.errors.payan_khedmat_image : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
fieldName="national_card_image"
|
||||
imageAlt={t("app_name")}
|
||||
label={t("LoanRequest.file_field_national_card_image")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.national_card_image && props.errors.national_card_image)
|
||||
}
|
||||
helperText={
|
||||
props.touched.national_card_image ? props.errors.national_card_image : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: {xs: "column", sm: "row"},
|
||||
alignItems: "center",
|
||||
mx: "auto",
|
||||
my: 2,
|
||||
width: {xs: "100%", sm: "30%", md: "25%"},
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
fullWidth
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="large"
|
||||
sx={{mt: 2}}
|
||||
endIcon={<DataSaverOnIcon/>}
|
||||
disabled={props.isSubmitting}
|
||||
>
|
||||
{t("LoanRequest.button_submit")}
|
||||
</Button>
|
||||
</Box>
|
||||
</StyledForm>
|
||||
</Stack>
|
||||
)}
|
||||
</Formik>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddFormComponent;
|
||||
@@ -1,17 +0,0 @@
|
||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
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>
|
||||
{user.can_request_a_new_loan ? <AddFormComponent/> : <AccessibilityComponent/>}
|
||||
</DashboardLayouts>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoanRequestComponent;
|
||||
@@ -1,397 +0,0 @@
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import UploadSystem from "@/core/components/UploadSystem";
|
||||
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 {Field, Formik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
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 = ({provinceList, initialValues}) => {
|
||||
const t = useTranslations();
|
||||
const requestServer = useRequest();
|
||||
const router = useRouter();
|
||||
|
||||
|
||||
// validation and request action of form
|
||||
const validationSchema = Yup.object().shape({
|
||||
name: Yup.string().required(t("LoanRequest.error_message_name")),
|
||||
phone_number: Yup.string().required(
|
||||
t("LoanRequest.error_message_phone_number")
|
||||
),
|
||||
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")),
|
||||
agreement_doc: Yup.mixed().required(t("LoanRequest.error_message_agreement_doc")),
|
||||
national_card_image: Yup.mixed().required(t("LoanRequest.error_message_national_card_image")),
|
||||
shenasname_image: Yup.mixed().required(t("LoanRequest.error_message_shenasname_image")),
|
||||
payan_khedmat_image: Yup.mixed().required(t("LoanRequest.error_message_payan_khedmat_image")),
|
||||
});
|
||||
|
||||
const handleSubmit = (values, props) => {
|
||||
const formData = new FormData();
|
||||
formData.append("name", values.name);
|
||||
formData.append("phone_number", values.phone_number);
|
||||
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 != initialValues.sherkat_naft_doc)
|
||||
formData.append("sherkat_naft_doc", values.sherkat_naft_doc);
|
||||
if (values.estate_doc != initialValues.estate_doc)
|
||||
formData.append("estate_doc", values.estate_doc);
|
||||
if (values.agreement_doc != initialValues.agreement_doc)
|
||||
formData.append("agreement_doc", values.agreement_doc);
|
||||
if (values.shenasname_image != initialValues.shenasname_image)
|
||||
formData.append("shenasname_image", values.shenasname_image);
|
||||
if (values.national_card_image != initialValues.national_card_image)
|
||||
formData.append("national_card_image", values.national_card_image);
|
||||
if (values.payan_khedmat_image != initialValues.payan_khedmat_image)
|
||||
formData.append("payan_khedmat_image", values.payan_khedmat_image);
|
||||
|
||||
requestServer(UPDATE_LOAN_REQUEST_WELFARE + router.query.id, "post", {auth: true, data: formData})
|
||||
.then(function (response) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
})
|
||||
.finally(function () {
|
||||
props.setSubmitting(false);
|
||||
});
|
||||
};
|
||||
if (!initialValues) return "";
|
||||
return (
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validationSchema={validationSchema}
|
||||
>
|
||||
{(props) => (
|
||||
<Stack
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 1,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<StyledForm sx={{width: "100%"}}>
|
||||
<Box sx={{my: 1}}>
|
||||
<Divider>
|
||||
<Chip
|
||||
label={t("LoanRequest.personal_info")}
|
||||
/>
|
||||
</Divider>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: {xs: "column", sm: "row"},
|
||||
alignItems: "start",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="name"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_name")}
|
||||
placeholder={t("LoanRequest.text_field_enter_your_name")}
|
||||
type={"text"}
|
||||
error={!!(props.touched.name && props.errors.name)}
|
||||
fullWidth
|
||||
helperText={props.touched.name ? props.errors.name : null}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="phone_number"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_phone_number")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_phone_number"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
!!(props.touched.phone_number && props.errors.phone_number)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.phone_number
|
||||
? props.errors.phone_number
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
name="province_id"
|
||||
label={t("LoanRequest.text_field_province_id")} // t("LoanRequest.text_field_enter_your_province")
|
||||
size="small"
|
||||
selectType="province_id"
|
||||
component={SelectBox}
|
||||
selectors={provinceList}
|
||||
select={props.values.province_id}
|
||||
setFieldValue={props.setFieldValue}
|
||||
setFieldTouched={props.setFieldTouched}
|
||||
error={
|
||||
!!(props.touched.province_id && props.errors.province_id)
|
||||
}
|
||||
helperText={
|
||||
props.touched.province_id ? props.errors.province_id : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: {xs: "column", sm: "row"},
|
||||
alignItems: "start",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="national_id"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_national_id")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_national_id"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
!!(props.touched.national_id && props.errors.national_id)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.national_id
|
||||
? props.errors.national_id
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mx: {xs: 0, sm: 2},
|
||||
my: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
as={TextField}
|
||||
sx={{width: "100%"}}
|
||||
name="shenasname_id"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
label={t("LoanRequest.text_field_shenasname_id")}
|
||||
placeholder={t(
|
||||
"LoanRequest.text_field_enter_your_shenasname_id"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
!!(props.touched.shenasname_id && props.errors.shenasname_id)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.shenasname_id
|
||||
? props.errors.shenasname_id
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={{my: 1}}>
|
||||
<Divider>
|
||||
<Chip
|
||||
label={t("LoanRequest.uploading_documents")}
|
||||
/>
|
||||
</Divider>
|
||||
</Box>
|
||||
<Stack spacing={{xs: 1, sm: 2}} direction="row" useFlexGap flexWrap="wrap"
|
||||
sx={{justifyContent: "center"}}>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
default_image={initialValues.sherkat_naft_doc}
|
||||
fieldName="sherkat_naft_doc"
|
||||
imageAlt={t("LoanRequest.file_field_sherkat_naft_doc")}
|
||||
label={t("LoanRequest.file_field_sherkat_naft_doc")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.sherkat_naft_doc && props.errors.sherkat_naft_doc)
|
||||
}
|
||||
helperText={
|
||||
props.touched.sherkat_naft_doc ? props.errors.sherkat_naft_doc : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
default_image={initialValues.estate_doc}
|
||||
fieldName="estate_doc"
|
||||
imageAlt={t("LoanRequest.file_field_estate_doc")}
|
||||
label={t("LoanRequest.file_field_estate_doc")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.estate_doc && props.errors.estate_doc)
|
||||
}
|
||||
helperText={
|
||||
props.touched.estate_doc ? props.errors.estate_doc : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
default_image={initialValues.agreement_doc}
|
||||
fieldName="agreement_doc"
|
||||
imageAlt={t("LoanRequest.file_field_agreement_doc")}
|
||||
label={t("LoanRequest.file_field_agreement_doc")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.agreement_doc && props.errors.agreement_doc)
|
||||
}
|
||||
helperText={
|
||||
props.touched.agreement_doc ? props.errors.agreement_doc : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
default_image={initialValues.shenasname_image}
|
||||
fieldName="shenasname_image"
|
||||
imageAlt={t("LoanRequest.file_field_shenasname_image")}
|
||||
label={t("LoanRequest.file_field_shenasname_image")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.shenasname_image && props.errors.shenasname_image)
|
||||
}
|
||||
helperText={
|
||||
props.touched.shenasname_image ? props.errors.shenasname_image : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
default_image={initialValues.payan_khedmat_image}
|
||||
fieldName="payan_khedmat_image"
|
||||
imageAlt={t("LoanRequest.file_field_payan_khedmat_image")}
|
||||
label={t("LoanRequest.file_field_payan_khedmat_image")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.payan_khedmat_image && props.errors.payan_khedmat_image)
|
||||
}
|
||||
helperText={
|
||||
props.touched.payan_khedmat_image ? props.errors.payan_khedmat_image : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{
|
||||
mx: {xs: 0, sm: 1},
|
||||
maxWidth: "200px"
|
||||
}}>
|
||||
<UploadSystem
|
||||
setFieldValue={props.setFieldValue}
|
||||
default_image={initialValues.national_card_image}
|
||||
fieldName="national_card_image"
|
||||
imageAlt={t("app_name")}
|
||||
label={t("LoanRequest.file_field_national_card_image")}
|
||||
enableDelete={false}
|
||||
error={
|
||||
!!(props.touched.national_card_image && props.errors.national_card_image)
|
||||
}
|
||||
helperText={
|
||||
props.touched.national_card_image ? props.errors.national_card_image : null
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: {xs: "column", sm: "row"},
|
||||
alignItems: "center",
|
||||
mx: "auto",
|
||||
my: 2,
|
||||
width: {xs: "100%", sm: "30%", md: "25%"},
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
fullWidth
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="large"
|
||||
sx={{mt: 2}}
|
||||
endIcon={<DataSaverOnIcon/>}
|
||||
disabled={props.isSubmitting}
|
||||
>
|
||||
{t("LoanRequest.button_submit")}
|
||||
</Button>
|
||||
</Box>
|
||||
</StyledForm>
|
||||
</Stack>
|
||||
)}
|
||||
</Formik>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditFormComponent;
|
||||
@@ -1,81 +0,0 @@
|
||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||
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 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 provinceList={provinceList} initialValues={initialValues}/>
|
||||
</DashboardLayouts>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoanRequestComponent;
|
||||
@@ -1,52 +0,0 @@
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
Grid, IconButton, Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import SellIcon from '@mui/icons-material/Sell';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import {useTranslations} from "next-intl";
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
|
||||
|
||||
const RequestCard = ({item}) => {
|
||||
const t = useTranslations();
|
||||
return (
|
||||
<Grid item xs={12} md={6} lg={4}>
|
||||
<Card sx={{
|
||||
width: "100%",
|
||||
boxShadow: "rgba(0, 0, 0, 0.15) 0px 5px 15px 0px"
|
||||
}}>
|
||||
<CardHeader
|
||||
avatar={<SellIcon color="primary"/>}
|
||||
title={`${t("LoanFollowUp.request_number")}: (${item.id})`}
|
||||
subheader={item.latest_history_created_at}
|
||||
action={
|
||||
item.state_id === 7 ? ( // Use the ternary operator or if/else inside curly braces
|
||||
<Tooltip title={t("LoanFollowUp.loan_request_correction")}>
|
||||
<IconButton size="small"
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: `edit-request-loan/${item.id}`,
|
||||
}} aria-label="fingerprint">
|
||||
<EditIcon/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
) : null
|
||||
}
|
||||
/>
|
||||
<CardContent sx={{pt: 0}}>
|
||||
<Typography variant="button">
|
||||
{item.loan_state}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export default RequestCard;
|
||||
@@ -1,54 +0,0 @@
|
||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||
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(null);
|
||||
// get form data
|
||||
useEffect(() => {
|
||||
setLoadingPage(true)
|
||||
requestServer(SHOW_LOAN_REQUEST_WELFARE, "get", {auth: true, notification: false})
|
||||
.then(function ({data}) {
|
||||
const items = data.data;
|
||||
const formattedData = items.map((item, index) => ({
|
||||
id: item.id,
|
||||
latest_history_created_at: moment(item.latest_history_created_at).locale("fa").format("HH:mm | YYYY/MM/DD"),
|
||||
state_id: item.state_id,
|
||||
loan_state: item.loan_state,
|
||||
}));
|
||||
setRequestsList(formattedData);
|
||||
setLoadingPage(false)
|
||||
})
|
||||
.catch(function (error) {
|
||||
})
|
||||
}, []);
|
||||
|
||||
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"}}
|
||||
>
|
||||
{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;
|
||||
@@ -1,10 +1,8 @@
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import {Button, Typography} from "@mui/material";
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import {useTranslations} from "next-intl";
|
||||
import TitlePage from "@/core/components/TitlePage";
|
||||
import Svg403 from "@/core/components/svgs/Svg403";
|
||||
import {CenterLayout, FullPageLayout, NextLinkComposed} from "@witel/webapp-builder";
|
||||
|
||||
const UnAuthorizedComponent = () => {
|
||||
const t = useTranslations();
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import {Button, Typography} from "@mui/material";
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import {useTranslations} from "next-intl";
|
||||
import TitlePage from "@/core/components/TitlePage";
|
||||
import Svg404 from "@/core/components/svgs/Svg404";
|
||||
import {CenterLayout, FullPageLayout, NextLinkComposed} from "@witel/webapp-builder";
|
||||
|
||||
const NotFoundComponent = () => {
|
||||
const t = useTranslations();
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import {Button, Typography} from "@mui/material";
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import {useTranslations} from "next-intl";
|
||||
import TitlePage from "@/core/components/TitlePage";
|
||||
import Svg500 from "@/core/components/svgs/Svg500";
|
||||
import {CenterLayout, FullPageLayout, NextLinkComposed} from "@witel/webapp-builder";
|
||||
|
||||
const ServerErrorComponent = () => {
|
||||
const t = useTranslations();
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
import {Box, Button, Container, Grid, Stack, Typography} from "@mui/material";
|
||||
import LinkRouting from "@/core/components/LinkRouting";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {LinkRouting} from "@witel/webapp-builder";
|
||||
|
||||
const FooterDetails = () => {
|
||||
const t = useTranslations();
|
||||
return(
|
||||
<Box sx={{backgroundColor : 'black', color : 'white'}}>
|
||||
<Container sx={{py : 2}} maxWidth="xl">
|
||||
<Grid container sx={{py : 2}}>
|
||||
return (
|
||||
<Box sx={{backgroundColor: 'black', color: 'white'}}>
|
||||
<Container sx={{py: 2}} maxWidth="xl">
|
||||
<Grid container sx={{py: 2}}>
|
||||
<Grid item xs={12} md={8}>
|
||||
<Button disabled>
|
||||
<Typography color={'white'}>کلیه حقوق محفوظ و متعلق به سازمان راهداری و حمل و نقل جاده ای می باشد</Typography>
|
||||
<Typography color={'white'}>کلیه حقوق محفوظ و متعلق به سازمان راهداری و حمل و نقل جاده ای می
|
||||
باشد</Typography>
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={4}>
|
||||
<Stack direction="row" alignItems="center" justifyContent="center">
|
||||
<img src='/icons/logoLandingPage.png' width={25} alt="Your Alt Text" />
|
||||
<img src='/icons/logoLandingPage.png' width={25} alt="Your Alt Text"/>
|
||||
<LinkRouting
|
||||
sx={{margin: 0.5, fontSize: "20px", color : "white"}}
|
||||
sx={{margin: 0.5, fontSize: "20px", color: "white"}}
|
||||
href={process.env.NEXT_PUBLIC_POWERED_BY_URL}
|
||||
target="_blank"
|
||||
underline="hover"
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {Box, Button, Container, Grid} from "@mui/material";
|
||||
|
||||
const HeaderDetails = () => {
|
||||
return(
|
||||
return (
|
||||
<Box>
|
||||
<Container sx={{py : 3}} maxWidth="xl">
|
||||
<Container sx={{py: 3}} maxWidth="xl">
|
||||
<Grid container>
|
||||
<Grid item sx={12} md={8}>
|
||||
<Button startIcon={<img src='/icons/headerLogo.png' alt='icon'/>} />
|
||||
<Grid item xs={12} md={8}>
|
||||
<Button startIcon={<img src='/icons/headerLogo.png' alt='icon'/>}/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
|
||||
@@ -1,43 +1,48 @@
|
||||
import {Box, Button, Chip, Container, Grid, Link, Stack, Typography} from "@mui/material";
|
||||
import {Box, Button, Chip, Container, Grid, Link, Typography} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import DownloadIcon from '@mui/icons-material/Download';
|
||||
|
||||
const LoanCondition = () => {
|
||||
const t = useTranslations();
|
||||
return(
|
||||
return (
|
||||
<Box>
|
||||
<Container sx={{py : 3}} maxWidth="xl">
|
||||
<Typography sx={{my : 3}} variant={'h3'}>
|
||||
تخصیص وام
|
||||
</Typography>
|
||||
<Container sx={{py: 3}} maxWidth="xl">
|
||||
<Grid container>
|
||||
<Grid item xs={12} md={8}>
|
||||
<Box sx={{padding : 3}}>
|
||||
<Box sx={{padding: 3}}>
|
||||
<Typography variant={'h5'}>
|
||||
قوانین دریافت وام
|
||||
</Typography>
|
||||
<Grid item sx={{my : 2}} spacing={2}>
|
||||
<Chip sx={{m : 1}} label="1 . فقط به زوجین ایرانی تعلق میگیرد" />
|
||||
<Chip sx={{m : 1}} label="2 . فقط به زوجین ایرانی تعلق میگیرد" />
|
||||
<Chip sx={{m : 1}} label="3 . فقط به زوجین ایرانی تعلق میگیرد" />
|
||||
<Chip sx={{m : 1}} label="4 . فقط به زوجین ایرانی تعلق میگیرد" />
|
||||
<Grid item sx={{my: 2}}>
|
||||
<Chip sx={{m: 1}}
|
||||
label="1. ارایه کارت هوشمند ناوگان فعال توسط مالک ناوگان (صاحب سند و پلاک)"/>
|
||||
<Chip sx={{m: 1}} label="2. ارایه حداقل 140 صورت وضعیت در سال 1400 و 1401"/>
|
||||
<Chip sx={{m: 1}} label="3. نداشتن بدهی جاری"/>
|
||||
</Grid>
|
||||
<Typography textAlign={'justify'}> این یکی از محبوبترین انواع وام در ایران است. دلیل این محبوبیت سرعت آن در پرداخت و سود بسیار پایین آن است.
|
||||
تنها یک شرط برای اخذ این وام وجود دارد و آن این است که باید به تازگی ازدواج کرده باشید.
|
||||
همچنین فقط یک بار از این وام میتوانید استفاده کنید. یعنی این وام فقط یک بار به هر فرد تعلق میگیرد.
|
||||
محل تامین بودجه آن حسابهای قرض الحسنهایست که افراد در بانکها باز میکنند و مرجع اصلی آرائه آن، بانک مرکزی است.
|
||||
<Typography sx={{lineHeight: 2.4}} textAlign={'justify'}>
|
||||
این وام برای اتوبوس تا سقف <Typography sx={{color: "secondary.main"}}
|
||||
variant={'h6'}
|
||||
fontWeight={'bold'}
|
||||
component={'span'}>700</Typography> میلیون تومان
|
||||
و برای مینی بوس تا سقف <Typography sx={{color: "secondary.main"}}
|
||||
variant={'h6'}
|
||||
fontWeight={'bold'}
|
||||
component={'span'}>200</Typography> میلیون تومان در
|
||||
نظر گرفته شده است. مبلغ نهایی با توجه به امتیاز و روند کارشناسی در ادارات مربوطه مشخص
|
||||
میشود. برای اطلاع از شرایط کامل این وام فایل پیوست را مطالعه بفرمایید.
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid sx={{display : 'flex' , alignItems : "center", justifyContent : "center"}} item xs={12} md={4}>
|
||||
<Grid sx={{display: 'flex', alignItems: "center", justifyContent: "center"}} item xs={12} md={4}>
|
||||
<Box>
|
||||
<Button variant="contained" startIcon={<DownloadIcon />}>
|
||||
<Button variant="contained" startIcon={<DownloadIcon/>}>
|
||||
<Link
|
||||
variant="subtitle1"
|
||||
sx={{padding : 1}}
|
||||
sx={{padding: 1}}
|
||||
color={'white'}
|
||||
download
|
||||
underline="none"
|
||||
href={'/dist/images/modalrms/Asset%2010.apk'}
|
||||
href={'/files/راهنما.xlsx'}
|
||||
>
|
||||
دریافت فایل های راهنما
|
||||
</Link>
|
||||
|
||||
@@ -1,91 +1,52 @@
|
||||
import {useTranslations} from "next-intl";
|
||||
import {
|
||||
Timeline,
|
||||
TimelineConnector, TimelineContent,
|
||||
TimelineDot,
|
||||
TimelineItem,
|
||||
TimelineOppositeContent,
|
||||
TimelineSeparator
|
||||
} from "@mui/lab";
|
||||
import RepeatIcon from '@mui/icons-material/Repeat';
|
||||
import FastfoodIcon from '@mui/icons-material/Fastfood';
|
||||
import LaptopMacIcon from '@mui/icons-material/LaptopMac';
|
||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import CallMadeIcon from '@mui/icons-material/CallMade';
|
||||
import {CircularProgress, Typography} from "@mui/material";
|
||||
import HowToRegIcon from '@mui/icons-material/HowToReg';
|
||||
import DoneIcon from '@mui/icons-material/Done';
|
||||
import HotelIcon from '@mui/icons-material/Hotel';
|
||||
import {useEffect, useState} from "react";
|
||||
import TimelineManager from "@/core/components/timelines/timelineManager";
|
||||
import moment from "jalali-moment";
|
||||
import {Timeline} from "@mui/lab";
|
||||
import {useConfig} from "@witel/webapp-builder";
|
||||
|
||||
const TimeLineDetails = () => {
|
||||
const t = useTranslations();
|
||||
return(
|
||||
const {config} = useConfig()
|
||||
const [timeLineList, setTimeLineList] = useState([])
|
||||
|
||||
const deadlines = Object.keys(config.deadlines).map(key => ({
|
||||
type: key,
|
||||
...config.deadlines[key]
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
let tempArr = []
|
||||
for (const timeLine of deadlines) {
|
||||
let temp = {}
|
||||
temp['label'] = timeLine.timeline_label
|
||||
temp['date'] = moment(timeLine.date.from, 'jYYYY/jMM/jDD').locale('fa').format('jD jMMMM')
|
||||
const fromDate = moment(timeLine.date.from, 'jYYYY/jMM/jDD')
|
||||
const toDate = moment(timeLine.date.to, 'jYYYY/jMM/jDD')
|
||||
const today = moment()
|
||||
if (today.isBetween(fromDate, toDate, null, '[]')) {
|
||||
temp['status'] = 'in progress'
|
||||
} else if (today.isAfter(toDate, null)) {
|
||||
temp['status'] = 'done'
|
||||
} else if (today.isBefore(fromDate, null)) {
|
||||
temp['status'] = 'open'
|
||||
}
|
||||
tempArr.push(temp)
|
||||
}
|
||||
setTimeLineList(tempArr)
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Timeline position="alternate">
|
||||
<TimelineItem>
|
||||
<TimelineOppositeContent
|
||||
sx={{ m: 'auto 0' }}
|
||||
align="right"
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
>
|
||||
10 دی
|
||||
</TimelineOppositeContent>
|
||||
<TimelineSeparator>
|
||||
<TimelineDot color={'success'}>
|
||||
<DoneIcon/>
|
||||
</TimelineDot>
|
||||
<TimelineConnector sx={{ backgroundColor: 'green' }} />
|
||||
</TimelineSeparator>
|
||||
<TimelineContent sx={{ py: '12px', px: 2 }}>
|
||||
<Typography variant="h6" component="span">
|
||||
ثبت نام متقاضی
|
||||
</Typography>
|
||||
<Typography color={'gray'}>ثبت نام متقاضیان واجد شرایط</Typography>
|
||||
</TimelineContent>
|
||||
</TimelineItem>
|
||||
<TimelineItem>
|
||||
<TimelineOppositeContent
|
||||
sx={{ m: 'auto 0' }}
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
>
|
||||
10 بهمن
|
||||
</TimelineOppositeContent>
|
||||
<TimelineSeparator>
|
||||
<TimelineConnector sx={{ backgroundColor: 'green' }} />
|
||||
<TimelineDot color="primary">
|
||||
<CircularProgress color={'inherit'} size={40} />
|
||||
</TimelineDot>
|
||||
<TimelineConnector />
|
||||
</TimelineSeparator>
|
||||
<TimelineContent sx={{ py: '12px', px: 2 }}>
|
||||
<Typography variant="h6">
|
||||
صحت سنجی متقاضیان
|
||||
</Typography>
|
||||
<Typography color={'gray'}>بررسی و کارشناسی درخواست ها</Typography>
|
||||
</TimelineContent>
|
||||
</TimelineItem>
|
||||
<TimelineItem>
|
||||
<TimelineOppositeContent
|
||||
sx={{ m: 'auto 0' }}
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
>
|
||||
10 اسفند
|
||||
</TimelineOppositeContent>
|
||||
<TimelineSeparator>
|
||||
<TimelineConnector />
|
||||
<TimelineDot>
|
||||
<CallMadeIcon />
|
||||
</TimelineDot>
|
||||
</TimelineSeparator>
|
||||
<TimelineContent sx={{ py: '12px', px: 2 }}>
|
||||
<Typography variant="h6" component="span">
|
||||
ارجاع به بانک
|
||||
</Typography>
|
||||
<Typography color={'gray'}>فرآیند معرفی ضامن و پرداخت</Typography>
|
||||
</TimelineContent>
|
||||
</TimelineItem>
|
||||
{timeLineList.map((timeLine, index) => (
|
||||
<TimelineManager
|
||||
key={index}
|
||||
status={timeLine.status}
|
||||
date={timeLine.date}
|
||||
primaryLabel={timeLine.label.primary}
|
||||
secondaryLabel={timeLine.label.secondary}
|
||||
position={index === (timeLineList.length - 1) ? 'end' : ''}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Timeline>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,31 +1,41 @@
|
||||
import {Box, Container, Grid, Typography} from "@mui/material";
|
||||
import {Timeline, TimelineConnector, TimelineContent, TimelineDot, TimelineItem, TimelineSeparator} from "@mui/lab";
|
||||
import {useTranslations} from "next-intl";
|
||||
import TimeLineDetails from "@/components/first/LoanDescription/TimeLineDetails";
|
||||
|
||||
const LoanDescription = () => {
|
||||
const t = useTranslations();
|
||||
return(
|
||||
return (
|
||||
<Box>
|
||||
<Container sx={{py : 3}} maxWidth="xl">
|
||||
<Typography sx={{my : 3}} variant={'h3'}>
|
||||
توضیحات دریافت وام
|
||||
<Container sx={{py: 3}} maxWidth="xl">
|
||||
<Typography sx={{my: 3}} variant={'h3'}>
|
||||
وام نوسازی ناوگان
|
||||
</Typography>
|
||||
<Grid sx={{py : 2}} container spacing={2}>
|
||||
<Grid sx={{py: 2}} container spacing={2}>
|
||||
<Grid item xs={12} md={7}>
|
||||
<Typography variant={'subtitle1'} textAlign={'justify'}>
|
||||
وام خرید کالای مهر ایران یا کالا کارت با هدف خرید مایحتاج خانه و کالاهای ضروری زندگی داده میشود. سقف کالا کارت ۱۵۰ میلیون تومان و سود آن ۴ درصد است.
|
||||
با دریافت کالا کارت میتوانید وسایل موردنیازتان را از فروشگاههای طرف قرارداد
|
||||
این فروشگاهها با نام گلدیران در شهرهای تهران، شیراز، اهواز، نور، اصفهان، تبریز، ساری و رشت فعالیت میکنند.
|
||||
طبق قوانین جدید و در راستای حمایت از طرح افزایش جمیعت، مبلغ آن برای زوجینی که مرد زیر ۲۵ سال و زن زیر ۲۳ سال داشته باشد، <Typography sx={{color : "secondary.main"}} variant={'h5'} fontWeight={'bold'} component={'span'}>440</Typography> میلیون یا ۲۲۰ میلیون به ازای هر نفر است.
|
||||
در این قانون هریک از زوجین که شرایط آنها در این قانون نگنجد،
|
||||
مبلغ تغییر کرده و به زوج <Typography sx={{color : "secondary.main"}} variant={'h5'} fontWeight={'bold'} component={'span'}>400</Typography> میلیون وام تعلق خواهد گرفت.
|
||||
حداکثر زمان بازپرداخت وام خرید کالا ۲۴ ماه است و برای گرفتن آن به یک ضامن رسمی احتیاج دارید.
|
||||
<Typography sx={{lineHeight: 2.4}} variant={'subtitle1'} textAlign={'justify'}>
|
||||
این وام براساس <Typography sx={{color: "secondary.main"}} variant={'h5'}
|
||||
fontWeight={'bold'}
|
||||
component={'span'}>تبصره 18</Typography> قانون بودجه می باشد. در
|
||||
قانون
|
||||
بودجه این تبصره اینگونه بیان شده است:
|
||||
به منظور رشد و پیشرفت استان های کشور از طریق ارتقای بهره وری و توسعه، سرمایه گذاری ها،
|
||||
تکمیل واحدهای نیمه تمام و ظرفیت های خالی بنگاه های تولیدی بر پایه آمایش سرزمین و همچنین
|
||||
حمایت از طرح(پروژهای) دانش بنیان و پیشران و بسط و عدالت سرزمینی منابع زیر جهت ایجاد و افزایش
|
||||
تولید، اشتغال و کارآفرینی و ارتقای رشد اقتصادی اختصاص می یابد.
|
||||
</Typography>
|
||||
<Typography sx={{lineHeight: 2.4}} variant={'subtitle1'} textAlign={'justify'}>
|
||||
در این راستا سازمان راهداری و حمل و نقل جاده ای به منظور بهبود کیفیت حمل و نقل بین شهری و
|
||||
افزایش ظرفیت ترابری اقدام به اعطای وام به <Typography sx={{color: "secondary.main"}}
|
||||
variant={'h5'}
|
||||
fontWeight={'bold'}
|
||||
component={'span'}>ناوگان های
|
||||
مسافربری</Typography> برای
|
||||
بازسازی و تعمیرات میکند.
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={5}>
|
||||
<Box>
|
||||
<TimeLineDetails />
|
||||
<TimeLineDetails/>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
import {Box, Container, Grid, Stack, Typography} from "@mui/material";
|
||||
import LinkRouting from "@/core/components/LinkRouting";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {LinkRouting} from "@witel/webapp-builder";
|
||||
|
||||
const LoanRegister = () => {
|
||||
const t = useTranslations();
|
||||
return(
|
||||
<Box sx={{backgroundColor : "primary.light"}}>
|
||||
<Container sx={{padding : 3, color : "white"}} maxWidth="xl">
|
||||
<Typography sx={{my : 3}} variant={'h3'}>
|
||||
return (
|
||||
<Box sx={{backgroundSize: 'cover', backgroundImage: `url(/images/bg-firstpage-bus.png)`}}>
|
||||
<Container sx={{padding: 3, color: "white"}} maxWidth="xl">
|
||||
<Typography sx={{my: 3, textShadow: '1px 1px 2px #555555'}} variant={'h3'}>
|
||||
{t("app_name")}
|
||||
</Typography>
|
||||
<Stack sx={{color : "white"}}>
|
||||
<Grid sx={{py : 4}} container spacing={2}>
|
||||
<Stack sx={{color: "white"}}>
|
||||
<Grid sx={{py: 4}} container spacing={2}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Box sx={{paddingBottom : 4}}>
|
||||
<Typography>
|
||||
برای استفاده از تسهیلات این سامانه و دریافت وام می بایست ابتدا وارد سامانه شوید و یا اگر ثبت نام نکرده اید ثبت نام کنید
|
||||
<Box sx={{paddingBottom: 4}}>
|
||||
<Typography sx={{lineHeight: 2.7, textShadow: '1px 1px 2px black'}}>
|
||||
وام نوسازی ناوگان به هدف رشد و پیشرفت استان های کشور از طریق ارتقای بهره وری و توسعه
|
||||
اعطا میشود. برای استفاده از تسهیلات این سامانه و درخواست وام می بایست ابتدا وارد
|
||||
سامانه شوید.
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Stack spacing={3} alignItems={'center'} justifyContent={'center'}>
|
||||
<Container maxWidth={'xs'} sx={{backgroundColor : "primary.main", textAlign : "center", borderRadius : 2, padding : 1}}>
|
||||
<Container maxWidth={'xs'} sx={{
|
||||
backgroundColor: "primary.main",
|
||||
textAlign: "center",
|
||||
borderRadius: 2,
|
||||
padding: 1
|
||||
}}>
|
||||
<LinkRouting underline="none" color="inherit" href={'/login'}>
|
||||
<Typography variant="h6">
|
||||
{t("firstPage.login_button")}
|
||||
</Typography>
|
||||
</LinkRouting>
|
||||
</Container>
|
||||
<Container maxWidth={'xs'} sx={{backgroundColor : "primary.main", textAlign : "center", borderRadius : 2 ,padding : 1}}>
|
||||
<LinkRouting underline="none" color="inherit" href={'/register'}>
|
||||
<Typography variant="h6">
|
||||
{t("firstPage.register_button")}
|
||||
</Typography>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import {Stack} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import LoanRegister from "@/components/first/LoanRegister";
|
||||
@@ -6,6 +5,7 @@ import LoanCondition from "@/components/first/LoanCondition";
|
||||
import FooterDetails from "@/components/first/FooterDetails";
|
||||
import HeaderDetails from "@/components/first/HeaderDetails";
|
||||
import LoanDescription from "@/components/first/LoanDescription";
|
||||
import {FullPageLayout} from "@witel/webapp-builder";
|
||||
|
||||
const FirstComponent = () => {
|
||||
const t = useTranslations();
|
||||
@@ -13,11 +13,11 @@ const FirstComponent = () => {
|
||||
return (
|
||||
<FullPageLayout>
|
||||
<Stack>
|
||||
<HeaderDetails />
|
||||
<LoanRegister />
|
||||
<LoanDescription />
|
||||
<LoanCondition />
|
||||
<FooterDetails />
|
||||
<HeaderDetails/>
|
||||
<LoanRegister/>
|
||||
<LoanDescription/>
|
||||
<LoanCondition/>
|
||||
<FooterDetails/>
|
||||
</Stack>
|
||||
</FullPageLayout>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import ResendToken from "@/core/components/ResendToken";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import {LOGIN} from "@/core/data/apiRoutes";
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import ChangeCircleIcon from "@mui/icons-material/ChangeCircle";
|
||||
import LoginIcon from "@mui/icons-material/Login";
|
||||
import {Box, Button, Container, Grid, Paper, Stack, TextField, Typography,} from "@mui/material";
|
||||
@@ -11,8 +8,8 @@ import {Field, Formik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
import * as Yup from "yup";
|
||||
import SvgLogin from "@/core/components/svgs/SvgLogin";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
import AutoSubmit from "@/core/components/AutoSubmit";
|
||||
import {CenterLayout, FullPageLayout, useRequest, useUser} from "@witel/webapp-builder";
|
||||
|
||||
const SendTokenComponent = ({
|
||||
PhoneNumber,
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import LinkRouting from "@/core/components/LinkRouting";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import {SEND_OTP_TOKEN} from "@/core/data/apiRoutes";
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import FingerprintIcon from "@mui/icons-material/Fingerprint";
|
||||
import PersonAddIcon from "@mui/icons-material/PersonAdd";
|
||||
import {Button, Container, Grid, Paper, Stack, TextField, Typography,} from "@mui/material";
|
||||
import {Field, Formik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {useSearchParams} from "next/navigation";
|
||||
import * as Yup from "yup";
|
||||
import SvgLogin from "@/core/components/svgs/SvgLogin";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
import {CenterLayout, FullPageLayout, LinkRouting, useRequest} from "@witel/webapp-builder";
|
||||
|
||||
|
||||
const SendUserDataComponent = ({
|
||||
setOtpToken,
|
||||
@@ -97,32 +94,16 @@ const SendUserDataComponent = ({
|
||||
flexDirection: {xs: "column-reverse", sm: "row"},
|
||||
}}
|
||||
>
|
||||
<Grid item xs={12} sm={6} sx={{pr: {xs: 0, sm: 1}}}>
|
||||
<LinkRouting href={"/register"}>
|
||||
<Button
|
||||
fullWidth
|
||||
type="button"
|
||||
variant="outlined"
|
||||
size="large"
|
||||
endIcon={<PersonAddIcon/>}
|
||||
disabled={props.isSubmitting}
|
||||
>
|
||||
{t("LoginPage.button_make_account")}
|
||||
</Button>
|
||||
</LinkRouting>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6} sx={{pl: {xs: 0, sm: 1}}}>
|
||||
<Button
|
||||
fullWidth
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="large"
|
||||
endIcon={<FingerprintIcon/>}
|
||||
disabled={props.isSubmitting}
|
||||
>
|
||||
{t("LoginPage.button_request_verification")}
|
||||
</Button>
|
||||
</Grid>
|
||||
<Button
|
||||
fullWidth
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="large"
|
||||
endIcon={<FingerprintIcon/>}
|
||||
disabled={props.isSubmitting}
|
||||
>
|
||||
{t("LoginPage.button_request_verification")}
|
||||
</Button>
|
||||
</Grid>
|
||||
</Stack>
|
||||
</StyledForm>
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
import LinkRouting from "@/core/components/LinkRouting";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import {SEND_OTP_TOKEN} from "@/core/data/apiRoutes";
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import FingerprintIcon from "@mui/icons-material/Fingerprint";
|
||||
import {Button, Container, Paper, Stack, TextField, Typography,} from "@mui/material";
|
||||
import {Field, Formik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {useSearchParams} from "next/navigation";
|
||||
import * as Yup from "yup";
|
||||
import SvgLogin from "@/core/components/svgs/SvgLogin";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
|
||||
const RequestOtpComponent = ({
|
||||
setOtpToken,
|
||||
setPhoneNumber,
|
||||
PhoneNumber,
|
||||
setTimer,
|
||||
initialTimerValue,
|
||||
}) => {
|
||||
const t = useTranslations();
|
||||
const requestServer = useRequest();
|
||||
|
||||
const searchParams = useSearchParams();
|
||||
const backUrlDecodedPath = searchParams.get("back_url");
|
||||
|
||||
const initialValues = {
|
||||
phone_number: PhoneNumber,
|
||||
};
|
||||
const validationSchema = Yup.object().shape({
|
||||
phone_number: Yup.string().required(
|
||||
t("RegisterPage.error_message_phone_number")
|
||||
),
|
||||
});
|
||||
|
||||
const handleSubmit = (values, props) => {
|
||||
requestServer(SEND_OTP_TOKEN, "post", {
|
||||
auth: false, data: {
|
||||
phone_number: values.phone_number,
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
setPhoneNumber(values.phone_number);
|
||||
setOtpToken(true);
|
||||
setTimer(initialTimerValue);
|
||||
}).catch(function (error) {
|
||||
props.setSubmitting(false);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<FullPageLayout sx={{p: 1}}>
|
||||
<CenterLayout>
|
||||
<Container maxWidth="sm">
|
||||
<Paper elevation={0}>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validationSchema={validationSchema}
|
||||
>
|
||||
{(props) => (
|
||||
<Stack spacing={2} sx={{p: 2}}>
|
||||
<Stack
|
||||
sx={{width: "100%"}}
|
||||
alignItems='center'
|
||||
>
|
||||
<SvgLogin width={300} height={200}/>
|
||||
</Stack>
|
||||
<Typography margin={2} variant="h4" textAlign="center">
|
||||
{t("Titles.title_register_page")}
|
||||
</Typography>
|
||||
<StyledForm sx={{width: "100%"}}>
|
||||
<Stack spacing={3} sx={{p: 2}}>
|
||||
<Field
|
||||
as={TextField}
|
||||
name="phone_number"
|
||||
variant="outlined"
|
||||
label={t("RegisterPage.text_field_phone_number")}
|
||||
placeholder={t(
|
||||
"RegisterPage.text_field_enter_your_phone_number"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
!!(props.touched.phone_number && props.errors.phone_number)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.phone_number
|
||||
? props.errors.phone_number
|
||||
: null
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
fullWidth
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="large"
|
||||
endIcon={<FingerprintIcon/>}
|
||||
disabled={props.isSubmitting}
|
||||
>
|
||||
{t("RegisterPage.button_request_verification")}
|
||||
</Button>
|
||||
</Stack>
|
||||
</StyledForm>
|
||||
</Stack>
|
||||
)}
|
||||
</Formik>
|
||||
</Paper>
|
||||
</Container>
|
||||
</CenterLayout>
|
||||
<Stack direction="row" alignItems="center" justifyContent="center">
|
||||
<LinkRouting
|
||||
sx={{margin: 2}}
|
||||
href={
|
||||
backUrlDecodedPath
|
||||
? decodeURIComponent(backUrlDecodedPath)
|
||||
: "/register"
|
||||
}
|
||||
>
|
||||
{t("RegisterPage.link_routing_back_to")}{" "}
|
||||
{backUrlDecodedPath
|
||||
? t("RegisterPage.link_routing_previuos_page")
|
||||
: t("RegisterPage.link_routing_register")}
|
||||
</LinkRouting>
|
||||
</Stack>
|
||||
</FullPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default RequestOtpComponent;
|
||||
@@ -1,90 +0,0 @@
|
||||
import LinkRouting, {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import {Box, Button, Grid, Stack} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {useSearchParams} from "next/navigation";
|
||||
import SvgDashboard from "@/core/components/svgs/SvgDashboard";
|
||||
|
||||
const RegisterComponent = () => {
|
||||
const t = useTranslations();
|
||||
const {isAuth} = useUser();
|
||||
|
||||
const searchParams = useSearchParams();
|
||||
const backUrlDecodedPath = searchParams.get("back_url");
|
||||
|
||||
return (
|
||||
<FullPageLayout sx={{p: 1}}>
|
||||
<CenterLayout spacing={3}>
|
||||
<SvgDashboard width={300} height={200}/>
|
||||
{isAuth ? (
|
||||
<Button
|
||||
variant="contained"
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: "/dashboard",
|
||||
}}
|
||||
>
|
||||
{t("dashboard")}
|
||||
</Button>
|
||||
) : (
|
||||
<Box>
|
||||
<Grid
|
||||
container
|
||||
rowSpacing={{xs: 1, sm: 0}}
|
||||
sx={{
|
||||
flexDirection: {xs: "column", sm: "row"},
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Grid item xs={12} sm={6} sx={{px: {xs: 0, sm: 1}}}>
|
||||
<Button
|
||||
sx={{whiteSpace: "nowrap"}}
|
||||
variant="contained"
|
||||
size="large"
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: "register/navy",
|
||||
}}
|
||||
>
|
||||
{t("register_navy")}
|
||||
</Button>
|
||||
</Grid>
|
||||
{/*<Grid item xs={12} sm={6} sx={{px: {xs: 0, sm: 1}}}>*/}
|
||||
{/* <Button*/}
|
||||
{/* sx={{whiteSpace: "nowrap"}}*/}
|
||||
{/* variant="contained"*/}
|
||||
{/* size="large"*/}
|
||||
{/* component={NextLinkComposed}*/}
|
||||
{/* to={{*/}
|
||||
{/* pathname: "register/welfare-services",*/}
|
||||
{/* }}*/}
|
||||
{/* >*/}
|
||||
{/* {t("register_welfare_services")}*/}
|
||||
{/* </Button>*/}
|
||||
{/*</Grid>*/}
|
||||
</Grid>
|
||||
</Box>
|
||||
)}
|
||||
</CenterLayout>
|
||||
<Stack direction="row" alignItems="center" justifyContent="center">
|
||||
<LinkRouting
|
||||
sx={{margin: 2}}
|
||||
href={
|
||||
backUrlDecodedPath
|
||||
? decodeURIComponent(backUrlDecodedPath)
|
||||
: "/"
|
||||
}
|
||||
>
|
||||
{t("RegisterPage.link_routing_back_to")}{" "}
|
||||
{backUrlDecodedPath
|
||||
? t("RegisterPage.link_routing_previuos_page")
|
||||
: t("LoginPage.link_routing_main_page")}
|
||||
</LinkRouting>
|
||||
</Stack>
|
||||
</FullPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default RegisterComponent;
|
||||
@@ -1,176 +0,0 @@
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import {REGISTER} from "@/core/data/apiRoutes";
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import LoginIcon from "@mui/icons-material/Login";
|
||||
import ChangeCircleIcon from "@mui/icons-material/ChangeCircle";
|
||||
import {Box, Button, Chip, Container, Divider, Paper, Stack, TextField, Typography,} from "@mui/material";
|
||||
import {Field, Formik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
import * as Yup from "yup";
|
||||
import ResendToken from "@/core/components/ResendToken";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import SvgRegister from "@/core/components/svgs/SvgRegister";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
import AutoSubmit from "@/core/components/AutoSubmit";
|
||||
|
||||
const UserRegisterComponent = ({
|
||||
PhoneNumber,
|
||||
setOtpToken,
|
||||
initialTimerValue,
|
||||
timer,
|
||||
setTimer,
|
||||
}) => {
|
||||
const t = useTranslations();
|
||||
const {setToken} = useUser();
|
||||
const requestServer = useRequest();
|
||||
|
||||
const initialValues = {
|
||||
type_id: "1",
|
||||
verification_code: "",
|
||||
phone_number: PhoneNumber,
|
||||
national_id: "",
|
||||
};
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
verification_code: Yup.string().required(
|
||||
t("RegisterPage.error_message_verification_code")
|
||||
),
|
||||
national_id: Yup.string().required(
|
||||
t("RegisterPage.error_message_national_id")
|
||||
),
|
||||
});
|
||||
|
||||
const handleSubmit = (values, props) => {
|
||||
requestServer(REGISTER, "post", {
|
||||
auth: false, data: {
|
||||
type_id: values.type_id,
|
||||
national_id: values.national_id,
|
||||
phone_number: values.phone_number,
|
||||
verification_code: values.verification_code,
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
setOtpToken(true);
|
||||
setToken(response.data.token);
|
||||
}).catch(function (error) {
|
||||
props.setSubmitting(false);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<FullPageLayout sx={{p: 1}}>
|
||||
<CenterLayout>
|
||||
<Container maxWidth="sm">
|
||||
<Paper elevation={0}>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validationSchema={validationSchema}
|
||||
>
|
||||
{(props) => (
|
||||
<Stack spacing={2} sx={{p: 2}}>
|
||||
<Stack
|
||||
sx={{width: "100%"}}
|
||||
alignItems='center'
|
||||
>
|
||||
<SvgRegister width={300} height={200}/>
|
||||
</Stack>
|
||||
<Typography margin={2} variant="h4" textAlign="center">
|
||||
{t("register_navy")}
|
||||
</Typography>
|
||||
<StyledForm sx={{width: "100%"}}>
|
||||
<Stack spacing={3} sx={{p: 2}}>
|
||||
<Box
|
||||
sx={{
|
||||
display: {xs: "column", sm: "flex"},
|
||||
alignItems: "center",
|
||||
textAlign: {xs: "center", sm: "unset"},
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Typography variant="button" sx={{display: "block"}}>
|
||||
{t("LoginPage.sent_token_to")}: {PhoneNumber}
|
||||
</Typography>
|
||||
<Button
|
||||
size="small"
|
||||
startIcon={<ChangeCircleIcon/>}
|
||||
variant="outlined"
|
||||
sx={{whiteSpace: "nowrap", my: {xs: 1, sm: 0}}}
|
||||
onClick={() => setOtpToken(false)}
|
||||
>
|
||||
{t("LoginPage.change_phone_number")}
|
||||
</Button>
|
||||
</Box>
|
||||
<Field
|
||||
as={TextField}
|
||||
name="verification_code"
|
||||
variant="outlined"
|
||||
label={t("LoginPage.text_field_verification_code")}
|
||||
placeholder={t(
|
||||
"LoginPage.text_field_enter_your_verification_code"
|
||||
)}
|
||||
type={"number"}
|
||||
error={
|
||||
!!(props.touched.verification_code && props.errors.verification_code)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.verification_code
|
||||
? props.errors.verification_code
|
||||
: null
|
||||
}
|
||||
onChange={(e) => e.target.value.length <= 6 ? props.setFieldValue("verification_code", e.target.value) : ""}
|
||||
/>
|
||||
<AutoSubmit/>
|
||||
<ResendToken
|
||||
initialTimerValue={initialTimerValue}
|
||||
timer={timer}
|
||||
setTimer={setTimer}
|
||||
PhoneNumber={PhoneNumber}
|
||||
/>
|
||||
<Divider>
|
||||
<Chip label={t("RegisterPage.complete_information")}/>
|
||||
</Divider>
|
||||
<Field
|
||||
as={TextField}
|
||||
name="national_id"
|
||||
variant="outlined"
|
||||
label={t("RegisterPage.text_field_national_id")}
|
||||
placeholder={t(
|
||||
"RegisterPage.text_field_enter_your_national_id"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
!!(props.touched.national_id && props.errors.national_id)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.national_id
|
||||
? props.errors.national_id
|
||||
: null
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
fullWidth
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="large"
|
||||
endIcon={<LoginIcon/>}
|
||||
disabled={props.isSubmitting}
|
||||
>
|
||||
{t("RegisterPage.button_submit")}
|
||||
</Button>
|
||||
</Stack>
|
||||
</StyledForm>
|
||||
</Stack>
|
||||
)}
|
||||
</Formik>
|
||||
</Paper>
|
||||
</Container>
|
||||
</CenterLayout>
|
||||
</FullPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserRegisterComponent;
|
||||
@@ -1,37 +0,0 @@
|
||||
import {useState} from "react";
|
||||
import RequestOtpComponent from "../RequestOtp";
|
||||
import UserRegisterComponent from "./UserRegister";
|
||||
|
||||
const NavyComponent = () => {
|
||||
const [otpToken, setOtpToken] = useState(false);
|
||||
const [PhoneNumber, setPhoneNumber] = useState("");
|
||||
|
||||
// For Resend Token (read ResendToken Component Doc)
|
||||
const initialTimerValue = 30;
|
||||
const [timer, setTimer] = useState(initialTimerValue);
|
||||
// End For Resend Token
|
||||
|
||||
if (!otpToken) {
|
||||
return (
|
||||
<RequestOtpComponent
|
||||
setOtpToken={setOtpToken}
|
||||
PhoneNumber={PhoneNumber}
|
||||
setPhoneNumber={setPhoneNumber}
|
||||
setTimer={setTimer}
|
||||
initialTimerValue={initialTimerValue}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<UserRegisterComponent
|
||||
PhoneNumber={PhoneNumber}
|
||||
setOtpToken={setOtpToken}
|
||||
timer={timer}
|
||||
setTimer={setTimer}
|
||||
initialTimerValue={initialTimerValue}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default NavyComponent;
|
||||
@@ -1,174 +0,0 @@
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import {REGISTER} from "@/core/data/apiRoutes";
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import LoginIcon from "@mui/icons-material/Login";
|
||||
import ChangeCircleIcon from "@mui/icons-material/ChangeCircle";
|
||||
import {Box, Button, Chip, Container, Divider, Paper, Stack, TextField, Typography,} from "@mui/material";
|
||||
import {Field, Formik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
import * as Yup from "yup";
|
||||
import ResendToken from "@/core/components/ResendToken";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import SvgRegister from "@/core/components/svgs/SvgRegister";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
|
||||
const UserRegisterComponent = ({
|
||||
PhoneNumber,
|
||||
setOtpToken,
|
||||
initialTimerValue,
|
||||
timer,
|
||||
setTimer,
|
||||
}) => {
|
||||
const t = useTranslations();
|
||||
const {setToken} = useUser();
|
||||
const requestServer = useRequest();
|
||||
|
||||
const initialValues = {
|
||||
type_id: "2",
|
||||
verification_code: "",
|
||||
phone_number: PhoneNumber,
|
||||
national_id: "",
|
||||
};
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
verification_code: Yup.string().required(
|
||||
t("RegisterPage.error_message_verification_code")
|
||||
),
|
||||
national_id: Yup.string().required(
|
||||
t("RegisterPage.error_message_national_id")
|
||||
),
|
||||
});
|
||||
|
||||
const handleSubmit = (values, props) => {
|
||||
requestServer(REGISTER, "post", {
|
||||
auth: false, data: {
|
||||
type_id: values.type_id,
|
||||
national_id: values.national_id,
|
||||
phone_number: values.phone_number,
|
||||
verification_code: values.verification_code,
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
setOtpToken(true);
|
||||
setToken(response.data.token);
|
||||
}).catch(function (error) {
|
||||
props.setSubmitting(false);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<FullPageLayout sx={{p: 1}}>
|
||||
<CenterLayout>
|
||||
<Container maxWidth="sm">
|
||||
<Paper elevation={0}>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validationSchema={validationSchema}
|
||||
>
|
||||
{(props) => (
|
||||
<Stack spacing={2} sx={{p: 2}}>
|
||||
<Stack
|
||||
sx={{width: "100%"}}
|
||||
alignItems='center'
|
||||
>
|
||||
<SvgRegister width={300} height={200}/>
|
||||
</Stack>
|
||||
<Typography margin={2} variant="h4" textAlign="center">
|
||||
{t("register_welfare_services")}
|
||||
</Typography>
|
||||
<StyledForm sx={{width: "100%"}}>
|
||||
<Stack spacing={3} sx={{p: 2}}>
|
||||
<Box
|
||||
sx={{
|
||||
display: {xs: "column", sm: "flex"},
|
||||
alignItems: "center",
|
||||
textAlign: {xs: "center", sm: "unset"},
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Typography variant="button" sx={{display: "block"}}>
|
||||
{t("LoginPage.sent_token_to")}: {PhoneNumber}
|
||||
</Typography>
|
||||
<Button
|
||||
size="small"
|
||||
startIcon={<ChangeCircleIcon/>}
|
||||
variant="outlined"
|
||||
onClick={() => setOtpToken(false)}
|
||||
sx={{whiteSpace: "nowrap", my: {xs: 1, sm: 0}}}
|
||||
>
|
||||
{t("LoginPage.change_phone_number")}
|
||||
</Button>
|
||||
</Box>
|
||||
<Field
|
||||
as={TextField}
|
||||
name="verification_code"
|
||||
variant="outlined"
|
||||
label={t("LoginPage.text_field_verification_code")}
|
||||
placeholder={t(
|
||||
"LoginPage.text_field_enter_your_verification_code"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
!!(props.touched.verification_code && props.errors.verification_code)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.verification_code
|
||||
? props.errors.verification_code
|
||||
: null
|
||||
}
|
||||
/>
|
||||
<ResendToken
|
||||
initialTimerValue={initialTimerValue}
|
||||
timer={timer}
|
||||
setTimer={setTimer}
|
||||
PhoneNumber={PhoneNumber}
|
||||
disabled={props.isSubmitting}
|
||||
/>
|
||||
<Divider>
|
||||
<Chip label={t("RegisterPage.complete_information")}/>
|
||||
</Divider>
|
||||
<Field
|
||||
as={TextField}
|
||||
name="national_id"
|
||||
variant="outlined"
|
||||
label={t("RegisterPage.text_field_national_id")}
|
||||
placeholder={t(
|
||||
"RegisterPage.text_field_enter_your_national_id"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
!!(props.touched.national_id && props.errors.national_id)
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.national_id
|
||||
? props.errors.national_id
|
||||
: null
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
fullWidth
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="large"
|
||||
endIcon={<LoginIcon/>}
|
||||
disabled={props.isSubmitting}
|
||||
>
|
||||
{t("RegisterPage.button_submit")}
|
||||
</Button>
|
||||
</Stack>
|
||||
</StyledForm>
|
||||
</Stack>
|
||||
)}
|
||||
</Formik>
|
||||
</Paper>
|
||||
</Container>
|
||||
</CenterLayout>
|
||||
</FullPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserRegisterComponent;
|
||||
@@ -1,37 +0,0 @@
|
||||
import {useState} from "react";
|
||||
import RequestOtpComponent from "../RequestOtp";
|
||||
import UserRegisterComponent from "./UserRegister";
|
||||
|
||||
const WelfareServicesComponent = () => {
|
||||
const [otpToken, setOtpToken] = useState(false);
|
||||
const [PhoneNumber, setPhoneNumber] = useState("");
|
||||
|
||||
// For Resend Token (read ResendToken Component Doc)
|
||||
const initialTimerValue = 30;
|
||||
const [timer, setTimer] = useState(initialTimerValue);
|
||||
// End For Resend Token
|
||||
|
||||
if (!otpToken) {
|
||||
return (
|
||||
<RequestOtpComponent
|
||||
setOtpToken={setOtpToken}
|
||||
PhoneNumber={PhoneNumber}
|
||||
setPhoneNumber={setPhoneNumber}
|
||||
setTimer={setTimer}
|
||||
initialTimerValue={initialTimerValue}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<UserRegisterComponent
|
||||
PhoneNumber={PhoneNumber}
|
||||
setOtpToken={setOtpToken}
|
||||
timer={timer}
|
||||
setTimer={setTimer}
|
||||
initialTimerValue={initialTimerValue}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default WelfareServicesComponent;
|
||||
@@ -39,14 +39,6 @@ const GlobalHead = () => {
|
||||
/>
|
||||
<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>
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
import MuiLink from "@mui/material/Link";
|
||||
import {styled} from "@mui/material/styles";
|
||||
import clsx from "clsx";
|
||||
import NextLink from "next/link";
|
||||
import {useRouter} from "next/router";
|
||||
import * as React from "react";
|
||||
|
||||
// Add support for the sx prop for consistency with the other branches.
|
||||
const Anchor = styled("a")({});
|
||||
|
||||
export const NextLinkComposed = React.forwardRef(function NextLinkComposed(
|
||||
props,
|
||||
ref
|
||||
) {
|
||||
const {
|
||||
to,
|
||||
linkAs,
|
||||
replace,
|
||||
scroll,
|
||||
shallow,
|
||||
prefetch,
|
||||
legacyBehavior = true,
|
||||
locale,
|
||||
...other
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<NextLink
|
||||
href={to}
|
||||
prefetch={prefetch}
|
||||
as={linkAs}
|
||||
replace={replace}
|
||||
scroll={scroll}
|
||||
shallow={shallow}
|
||||
passHref
|
||||
locale={locale}
|
||||
legacyBehavior={legacyBehavior}
|
||||
>
|
||||
<Anchor ref={ref} {...other} />
|
||||
</NextLink>
|
||||
);
|
||||
});
|
||||
|
||||
// A styled version of the Next.js Link component:
|
||||
// https://nextjs.org/docs/api-reference/next/link
|
||||
const LinkRouting = React.forwardRef(function Link(props, ref) {
|
||||
const {
|
||||
activeClassName = "active",
|
||||
as,
|
||||
className: classNameProps,
|
||||
href,
|
||||
legacyBehavior,
|
||||
linkAs: linkAsProp,
|
||||
locale,
|
||||
noLinkStyle,
|
||||
prefetch,
|
||||
replace,
|
||||
role, // Link don't have roles.
|
||||
scroll,
|
||||
shallow,
|
||||
...other
|
||||
} = props;
|
||||
|
||||
const router = useRouter();
|
||||
const pathname = typeof href === "string" ? href : href.pathname;
|
||||
const className = clsx(classNameProps, {
|
||||
[activeClassName]: router.pathname === pathname && activeClassName,
|
||||
});
|
||||
|
||||
const isExternal =
|
||||
typeof href === "string" &&
|
||||
(href.indexOf("http") === 0 || href.indexOf("mailto:") === 0);
|
||||
|
||||
if (isExternal) {
|
||||
if (noLinkStyle) {
|
||||
return <Anchor className={className} href={href} ref={ref} {...other} />;
|
||||
}
|
||||
|
||||
return <MuiLink className={className} href={href} ref={ref} {...other} />;
|
||||
}
|
||||
|
||||
const linkAs = linkAsProp || as;
|
||||
const nextjsProps = {
|
||||
to: href,
|
||||
linkAs,
|
||||
replace,
|
||||
scroll,
|
||||
shallow,
|
||||
prefetch,
|
||||
legacyBehavior,
|
||||
locale,
|
||||
};
|
||||
|
||||
if (noLinkStyle) {
|
||||
return (
|
||||
<NextLinkComposed
|
||||
className={className}
|
||||
ref={ref}
|
||||
{...nextjsProps}
|
||||
{...other}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<MuiLink
|
||||
component={NextLinkComposed}
|
||||
className={className}
|
||||
ref={ref}
|
||||
{...nextjsProps}
|
||||
{...other}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
export default LinkRouting;
|
||||
@@ -1,44 +0,0 @@
|
||||
import {Backdrop, Box, Fade, styled} from "@mui/material";
|
||||
import SvgLoading from "@/core/components/svgs/SvgLoading";
|
||||
|
||||
const LoadingImage = styled(Box)({
|
||||
"@keyframes load": {
|
||||
"0%": {
|
||||
// opacity: 0,
|
||||
transform: "scale(1)",
|
||||
},
|
||||
"50%": {
|
||||
// opacity: 1,
|
||||
transform: "scale(2)",
|
||||
},
|
||||
"100%": {
|
||||
// opacity: 0,
|
||||
transform: "scale(1)",
|
||||
},
|
||||
},
|
||||
animation: "load 2s infinite",
|
||||
});
|
||||
|
||||
const LoadingHardPage = ({children, loading}) => {
|
||||
return (
|
||||
<>
|
||||
<Backdrop
|
||||
sx={{bgcolor: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1}}
|
||||
open={loading}
|
||||
>
|
||||
<Fade in={true}>
|
||||
<LoadingImage
|
||||
width={100}
|
||||
height={100}
|
||||
>
|
||||
<SvgLoading width={100}
|
||||
height={100}/>
|
||||
</LoadingImage>
|
||||
</Fade>
|
||||
</Backdrop>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoadingHardPage;
|
||||
@@ -1,18 +0,0 @@
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import SvgLoading from "@/core/components/svgs/SvgLoading";
|
||||
|
||||
const Message = ({text, actions}) => {
|
||||
return (
|
||||
<FullPageLayout sx={{p: 1}}>
|
||||
<CenterLayout spacing={3}>
|
||||
<SvgLoading width={100}
|
||||
height={100}/>
|
||||
{text}
|
||||
{actions}
|
||||
</CenterLayout>
|
||||
</FullPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default Message;
|
||||
87
src/core/components/MuiDatePicker.jsx
Normal file
87
src/core/components/MuiDatePicker.jsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import * as React from 'react';
|
||||
import {useState} from 'react';
|
||||
import Button from '@mui/material/Button';
|
||||
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
||||
import {LocalizationProvider} from '@mui/x-date-pickers/LocalizationProvider';
|
||||
import {DatePicker} from '@mui/x-date-pickers/DatePicker';
|
||||
import {useTranslations} from "next-intl";
|
||||
import moment from "jalali-moment";
|
||||
import {FormControl, FormHelperText} from "@mui/material";
|
||||
|
||||
function ButtonField(props) {
|
||||
const t = useTranslations();
|
||||
const {
|
||||
setOpen,
|
||||
label,
|
||||
id,
|
||||
disabled,
|
||||
InputProps: {ref} = {},
|
||||
inputProps: {'aria-label': ariaLabel} = {},
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Button
|
||||
sx={{width: "100%", padding: 0.8}}
|
||||
variant="outlined"
|
||||
color={props.slotProps.formik.touched.birthday && Boolean(props.slotProps.formik.errors.birthday) ? "error" : "primary"}
|
||||
id={id}
|
||||
disabled={disabled}
|
||||
ref={ref}
|
||||
aria-label={ariaLabel}
|
||||
onClick={() => setOpen?.((prev) => !prev)}
|
||||
>
|
||||
{label ? `${t("birthday")}: ${label}` : `${t("birthday")}`}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
function ButtonDatePicker(props) {
|
||||
const t = useTranslations();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<DatePicker
|
||||
slots={{field: ButtonField, ...props.slots}}
|
||||
disableFuture
|
||||
disabled={props.disabled}
|
||||
slotProps={{
|
||||
formik: props.formik,
|
||||
field: {setOpen},
|
||||
textField: {
|
||||
helperText: props.formik.errors.birthday ? `${t("birthday_error")}` : null
|
||||
}
|
||||
}}
|
||||
{...props}
|
||||
open={open}
|
||||
onClose={() => setOpen(false)}
|
||||
onOpen={() => setOpen(true)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default function PickerWithButtonField({formik, disabled}) {
|
||||
return (
|
||||
<FormControl
|
||||
variant={"outlined"}
|
||||
fullWidth
|
||||
size="small"
|
||||
error={true}
|
||||
>
|
||||
<LocalizationProvider dateAdapter={AdapterDateFnsJalali}>
|
||||
<ButtonDatePicker
|
||||
label={formik.values.birthday === "" ? null : formik.values.birthday
|
||||
.locale("fa")
|
||||
.format("YYYY/MM/DD")}
|
||||
value={formik.values.birthday === "" ? null : formik.values.birthday.toDate()}
|
||||
formik={formik}
|
||||
disabled={disabled}
|
||||
onChange={(newValue) => {
|
||||
formik.setFieldValue("birthday", moment(newValue))
|
||||
}}
|
||||
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
<FormHelperText>{formik.touched.birthday && formik.errors.birthday}</FormHelperText>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
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
|
||||
@@ -1,8 +0,0 @@
|
||||
import {NoSsr} from "@mui/material";
|
||||
|
||||
const NoSsrHandler = ({isBot, children}) => {
|
||||
if (isBot) return children;
|
||||
return <NoSsr>{children}</NoSsr>;
|
||||
};
|
||||
|
||||
export default NoSsrHandler;
|
||||
236
src/core/components/PlateNumber.jsx
Normal file
236
src/core/components/PlateNumber.jsx
Normal file
@@ -0,0 +1,236 @@
|
||||
import {Box, Button, Drawer, FormHelperText, Stack, TextField} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import AccessibleIcon from '@mui/icons-material/Accessible';
|
||||
import {useState} from "react";
|
||||
|
||||
const plate_words = [
|
||||
{
|
||||
id: 1,
|
||||
value: "الف",
|
||||
name: "الف"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: "ب",
|
||||
name: "ب"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
value: "پ",
|
||||
name: "پ"
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
value: "ت",
|
||||
name: "ت"
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
value: "ث",
|
||||
name: "ث"
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
value: "ج",
|
||||
name: "ج"
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
value: "د",
|
||||
name: "د"
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
value: "ز",
|
||||
name: "ز"
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
value: "س",
|
||||
name: "س"
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
value: "ش",
|
||||
name: "ش"
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
value: "ص",
|
||||
name: "ص"
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
value: "ط",
|
||||
name: "ط"
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
value: "ع",
|
||||
name: "ع"
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
value: "ف",
|
||||
name: "ف"
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
value: "ق",
|
||||
name: "ق"
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
value: "ک",
|
||||
name: "گ"
|
||||
},
|
||||
{
|
||||
id: 17,
|
||||
value: "ل",
|
||||
name: "ل"
|
||||
},
|
||||
{
|
||||
id: 18,
|
||||
value: "م",
|
||||
name: "م"
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
value: "ن",
|
||||
name: "ن"
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
value: "و",
|
||||
name: "و"
|
||||
},
|
||||
{
|
||||
id: 21,
|
||||
value: "ه",
|
||||
name: "ه"
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
value: "ی",
|
||||
name: "ی"
|
||||
},
|
||||
{
|
||||
id: 23,
|
||||
value: "*",
|
||||
name: <AccessibleIcon/>
|
||||
},
|
||||
]
|
||||
const PlateNumber = ({formik, disabled}) => {
|
||||
const t = useTranslations();
|
||||
const [plateDrawer, setPlateDrawer] = useState(false);
|
||||
const isErrorPlate = Boolean(formik.errors.plate_part1 || formik.errors.plate_part3 || formik.errors.plate_part4)
|
||||
const isTouched = (formik.touched.plate_part1 || formik.touched.plate_part3 || formik.touched.plate_part4)
|
||||
return (
|
||||
<>
|
||||
<Stack direction={'row'}
|
||||
sx={{
|
||||
border: 1,
|
||||
overflow: 'hidden',
|
||||
borderColor: (isTouched && isErrorPlate) ? 'error.main' : 'divider',
|
||||
borderRadius: 1
|
||||
}}>
|
||||
<TextField
|
||||
name={'plate_part4'}
|
||||
type={'tel'}
|
||||
value={formik.values.plate_part4}
|
||||
disabled={disabled}
|
||||
size={'small'}
|
||||
placeholder={'xx'} sx={{flexGrow: 2, "& fieldset": {border: 'none'}}}
|
||||
inputProps={{sx: {textAlign: 'center'}}}
|
||||
onChange={(event) => event.target.value.length <= 2 ? formik.setFieldValue("plate_part4", event.target.value) : null}
|
||||
onBlur={formik.handleBlur}
|
||||
error={formik.touched.plate_part4 && Boolean(formik.errors.plate_part4)}
|
||||
/>
|
||||
<TextField
|
||||
name={'plate_part3'}
|
||||
type={'tel'}
|
||||
value={formik.values.plate_part3}
|
||||
size={'small'}
|
||||
disabled={disabled}
|
||||
placeholder={'xxx'}
|
||||
sx={{
|
||||
flexGrow: 3,
|
||||
borderLeft: 1,
|
||||
borderRadius: 0,
|
||||
borderColor: 'divider',
|
||||
"& fieldset": {border: 'none'}
|
||||
}}
|
||||
inputProps={{sx: {textAlign: 'center'}}}
|
||||
onChange={(event) => event.target.value.length <= 3 ? formik.setFieldValue("plate_part3", event.target.value) : null}
|
||||
onBlur={formik.handleBlur}
|
||||
error={formik.touched.plate_part3 && Boolean(formik.errors.plate_part3)}
|
||||
/>
|
||||
<Box sx={{flexGrow: 1}}>
|
||||
<Button
|
||||
onClick={() => setPlateDrawer(true)}
|
||||
sx={{height: '100%', borderRadius: 0, borderColor: 'divider'}}
|
||||
size={'small'}
|
||||
data-selected-word={formik.values.plate_part2}
|
||||
disabled={disabled}
|
||||
fullWidth
|
||||
>
|
||||
{plate_words.find(p => p.value === formik.values.plate_part2).name}
|
||||
</Button>
|
||||
</Box>
|
||||
<Drawer
|
||||
anchor={"bottom"}
|
||||
open={plateDrawer}
|
||||
onClose={() => setPlateDrawer(false)}
|
||||
>
|
||||
<Box sx={{
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
mx: "auto",
|
||||
my: 2,
|
||||
gap: 2,
|
||||
width: "60%",
|
||||
justifyContent: "center"
|
||||
}}>
|
||||
{plate_words.map((item) => (
|
||||
<Button
|
||||
key={item.id}
|
||||
onClick={() => {
|
||||
formik.setFieldValue("plate_part2", item.value)
|
||||
setPlateDrawer(false);
|
||||
}}
|
||||
sx={{
|
||||
width: "fit-content"
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
{item.name}
|
||||
</Button>
|
||||
))}
|
||||
</Box>
|
||||
</Drawer>
|
||||
<TextField
|
||||
name={'plate_part1'}
|
||||
type={'tel'}
|
||||
disabled={disabled}
|
||||
value={formik.values.plate_part1}
|
||||
size={'small'}
|
||||
placeholder={'xx'}
|
||||
sx={{flexGrow: 2, "& fieldset": {border: 'none'}}}
|
||||
inputProps={{sx: {textAlign: 'center'}}}
|
||||
onChange={(event) => event.target.value.length <= 2 ? formik.setFieldValue("plate_part1", event.target.value) : null}
|
||||
onBlur={formik.handleBlur}
|
||||
error={true}
|
||||
/>
|
||||
<Stack sx={{width: 24, borderLeft: 1, borderColor: 'divider'}}>
|
||||
<Box sx={{flexGrow: 1, bgcolor: '#1ebc1e'}}></Box>
|
||||
<Box sx={{flexGrow: 1, bgcolor: 'white'}}></Box>
|
||||
<Box sx={{flexGrow: 1, bgcolor: '#f52121'}}></Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<FormHelperText
|
||||
error={(isTouched && isErrorPlate)}>{(isTouched && isErrorPlate) ? `${t("LoanRequest.error_message_plate_number")}` : null}</FormHelperText>
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
export default PlateNumber
|
||||
@@ -1,11 +1,8 @@
|
||||
import Notifications from "@/core/components/notifications";
|
||||
import useDirection from "@/lib/app/hooks/useDirection";
|
||||
import {Button} from "@mui/material";
|
||||
import axios from "axios";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {useEffect} from "react";
|
||||
import {LOGIN, SEND_OTP_TOKEN} from "../data/apiRoutes";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
import {useDirection, useRequest} from "@witel/webapp-builder";
|
||||
|
||||
const ResendToken = ({initialTimerValue, timer, setTimer, PhoneNumber, disabled}) => {
|
||||
const t = useTranslations();
|
||||
|
||||
@@ -1,48 +1,53 @@
|
||||
import {FormControl, FormHelperText, InputLabel, MenuItem, Select,} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
|
||||
function SelectBox({
|
||||
select,
|
||||
selectType,
|
||||
name,
|
||||
selectors,
|
||||
label,
|
||||
setFieldValue,
|
||||
setFieldTouched,
|
||||
handleChange,
|
||||
error,
|
||||
onBlur,
|
||||
schema,
|
||||
disabled,
|
||||
helperText,
|
||||
isLoading,
|
||||
errorEcured
|
||||
}) {
|
||||
const t = useTranslations();
|
||||
|
||||
const selectId = String(select);
|
||||
const handleChange = (event) => {
|
||||
setFieldValue(selectType, event.target.value);
|
||||
};
|
||||
const handleBlur = () => {
|
||||
setFieldTouched(select, true);
|
||||
};
|
||||
return (
|
||||
<FormControl
|
||||
variant="outlined"
|
||||
margin="normal"
|
||||
disabled={disabled || false}
|
||||
variant={"outlined"}
|
||||
fullWidth
|
||||
size="small"
|
||||
error={error}
|
||||
sx={{mt: 0}}
|
||||
>
|
||||
<InputLabel id="language-label">{label}</InputLabel>
|
||||
<InputLabel>{label}</InputLabel>
|
||||
<Select
|
||||
labelId="language-label"
|
||||
id={selectId}
|
||||
name={selectId}
|
||||
label={label}
|
||||
name={name}
|
||||
size="small"
|
||||
value={select}
|
||||
value={isLoading ? "" : select}
|
||||
onChange={handleChange}
|
||||
label="Language"
|
||||
onBlur={handleBlur}
|
||||
onBlur={onBlur}
|
||||
|
||||
>
|
||||
{selectors.map((selector) => (
|
||||
<MenuItem key={selector.id} value={selector.value}>
|
||||
{selector.name}
|
||||
{isLoading ? (
|
||||
<MenuItem sx={{color: "primary.main"}}>{t("text_field_loading")}</MenuItem>
|
||||
) : errorEcured ? (
|
||||
<MenuItem sx={{color: "secondary.main"}}>
|
||||
{t("text_field_error_fetching")}
|
||||
</MenuItem>
|
||||
))}
|
||||
) : (
|
||||
selectors.map((selector) => (
|
||||
<MenuItem key={selector.id} value={selector[schema.value]}>
|
||||
{selector[schema.name]}
|
||||
</MenuItem>
|
||||
))
|
||||
)}
|
||||
</Select>
|
||||
<FormHelperText>{helperText}</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import DangerousIcon from "@mui/icons-material/Dangerous";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const ErrorNotification = (t, status, message) => {
|
||||
toast(
|
||||
() => (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "start",
|
||||
justifyContent: "start",
|
||||
}}
|
||||
>
|
||||
<Box sx={{display: "flex", alignItems: "center"}}>
|
||||
<DangerousIcon color="error" sx={{mr: 1.6}}/>
|
||||
<Box sx={{display: "flex", flexDirection: "column"}}>
|
||||
<Typography color="error" variant="button">
|
||||
{t("notifications.error")} ({t("notifications.code")}: {status})
|
||||
</Typography>
|
||||
<Typography variant="caption">
|
||||
{message || t("notifications.error_static_text")}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
),
|
||||
{
|
||||
autoClose: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default ErrorNotification;
|
||||
@@ -1,12 +0,0 @@
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const PendingNotification = (t) => {
|
||||
toast(t("notifications.pending"), {
|
||||
autoClose: false,
|
||||
closeButton: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
});
|
||||
};
|
||||
|
||||
export default PendingNotification;
|
||||
@@ -1,42 +0,0 @@
|
||||
import BeenhereIcon from "@mui/icons-material/Beenhere";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const SuccessNotification = (t, status) => {
|
||||
toast(
|
||||
() => (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "start",
|
||||
justifyContent: "start",
|
||||
}}
|
||||
>
|
||||
<Box sx={{display: "flex", alignItems: "center"}}>
|
||||
<BeenhereIcon color="success" sx={{mr: 1.6}}/>
|
||||
<Box sx={{display: "flex", flexDirection: "column"}}>
|
||||
<Typography color="success.main" variant="button">
|
||||
{t("notifications.success")} ({t("notifications.code")}:{" "}
|
||||
{status})
|
||||
</Typography>
|
||||
<Typography variant="caption">
|
||||
{t("notifications.success_static_text")}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
),
|
||||
{
|
||||
autoClose: 3000,
|
||||
hideProgressBar: true,
|
||||
pauseOnHover: true,
|
||||
closeOnClick: false,
|
||||
draggable: true,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default SuccessNotification;
|
||||
@@ -1,40 +0,0 @@
|
||||
import ReportIcon from "@mui/icons-material/Report";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const WarningNotification = (t, status) => {
|
||||
toast(
|
||||
() => (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "start",
|
||||
justifyContent: "start",
|
||||
}}
|
||||
>
|
||||
<Box sx={{display: "flex", alignItems: "center"}}>
|
||||
<ReportIcon color="warning" sx={{mr: 1.6}}/>
|
||||
<Box sx={{display: "flex", flexDirection: "column"}}>
|
||||
<Typography color="warning.main" variant="button">
|
||||
{t("notifications.warning")} ({t("notifications.code")}:{" "}
|
||||
{status})
|
||||
</Typography>
|
||||
<Typography variant="caption">
|
||||
{t("notifications.warning_static_text")}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
),
|
||||
{
|
||||
autoClose: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default WarningNotification;
|
||||
@@ -1,54 +0,0 @@
|
||||
import {toast} from "react-toastify";
|
||||
import ErrorNotification from "./ErrorNotification";
|
||||
import SuccessNotification from "./SuccessNotification";
|
||||
import WarningNotification from "./WarningNotification";
|
||||
|
||||
const Notifications = async (t, response) => {
|
||||
const {status, data} = response != undefined ? response : ""
|
||||
toast.dismiss();
|
||||
switch (status) {
|
||||
case 200:
|
||||
SuccessNotification(t, status);
|
||||
break;
|
||||
case 400:
|
||||
ErrorNotification(t, status);
|
||||
break;
|
||||
case 401:
|
||||
ErrorNotification(t, status);
|
||||
break;
|
||||
case 403:
|
||||
ErrorNotification(t, status);
|
||||
break;
|
||||
case 422:
|
||||
ErrorNotification(t, status, data.message);
|
||||
break;
|
||||
case 500:
|
||||
WarningNotification(t, status);
|
||||
break;
|
||||
case 503:
|
||||
WarningNotification(t, status);
|
||||
break;
|
||||
case 504:
|
||||
WarningNotification(t, status);
|
||||
break;
|
||||
default:
|
||||
toast(t("pending"), {
|
||||
autoClose: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
});
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
export default Notifications;
|
||||
|
||||
/*
|
||||
usage document
|
||||
|
||||
** for pending use ( Notifications( t, undefined) ) this before your request.
|
||||
** for success use ( Notifications( t, response) ) this inside .then() of your request.
|
||||
** for Error and Warning use ( Notifications( t, error.response) ) this inside .catche() of your request.
|
||||
|
||||
end usage document
|
||||
*/
|
||||
96
src/core/components/svgs/SvgDone.jsx
Normal file
96
src/core/components/svgs/SvgDone.jsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import {useTheme} from "@mui/material";
|
||||
|
||||
const SvgDone = ({width, height}) => {
|
||||
const theme = useTheme()
|
||||
const fillColor = theme.palette.primary.main
|
||||
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width={width} height={height}
|
||||
viewBox="0 0 680.83858 584.23207">
|
||||
<path id="b9ccae5a-ffdd-4f5c-9c1e-05af9f0f3372-220" data-name="Path 438"
|
||||
d="M310.70569,694.02818a24.21459,24.21459,0,0,0,23.38269-4.11877c8.18977-6.87441,10.758-18.196,12.8467-28.68191l6.17973-31.01657-12.9377,8.90837c-9.30465,6.40641-18.81826,13.01866-25.26011,22.29785s-9.25223,21.94707-4.07792,31.988"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#e6e6e6"/>
|
||||
<path id="f4ad1d06-bd03-4ced-a5c4-c19a65ab4ee5-221" data-name="Path 439"
|
||||
d="M312.7034,733.73874c-1.62839-11.86368-3.30382-23.88078-2.15884-35.87167,1.01467-10.64932,4.26373-21.04881,10.87831-29.57938a49.20592,49.20592,0,0,1,12.62466-11.44039c1.26215-.79648,2.42409,1.20354,1.16733,1.997a46.77949,46.77949,0,0,0-18.50446,22.32562c-4.02857,10.24607-4.67545,21.41582-3.98154,32.3003.41944,6.58218,1.31074,13.1212,2.20588,19.65251a1.19817,1.19817,0,0,1-.808,1.42251,1.16348,1.16348,0,0,1-1.42253-.808Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#f2f2f2"/>
|
||||
<path id="baf785f8-b4c6-42cf-85bd-8a16037845f7-222" data-name="Path 442"
|
||||
d="M324.42443,714.70229a17.82513,17.82513,0,0,0,15.53141,8.01862c7.8644-.37318,14.41806-5.85973,20.31713-11.07027l17.452-15.4088-11.54987-.55281c-8.30619-.39784-16.82672-.771-24.73813,1.79338s-15.20758,8.72639-16.654,16.91541"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#e6e6e6"/>
|
||||
<path id="a14e4330-7125-4e03-a856-d6453c34f6cc-223" data-name="Path 443"
|
||||
d="M308.10042,740.55843c7.83972-13.87142,16.93234-29.28794,33.1808-34.21552a37.02609,37.02609,0,0,1,13.95545-1.441c1.48189.128,1.11179,2.41174-.367,2.28454a34.39833,34.39833,0,0,0-22.27164,5.89215c-6.27994,4.27453-11.16975,10.21755-15.30781,16.51907-2.53511,3.86051-4.80576,7.88445-7.07642,11.903C309.48824,742.78513,307.36641,741.85759,308.10042,740.55843Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#f2f2f2"/>
|
||||
<path id="ac20a106-7eb8-4a45-8835-674ef3bf3222-224" data-name="Path 141"
|
||||
d="M935.3957,569.31654H503.18092a5.03014,5.03014,0,0,1-5.02359-5.02359V162.90754a5.03017,5.03017,0,0,1,5.02359-5.02358H935.3957a5.03017,5.03017,0,0,1,5.02359,5.02358V564.292a5.02922,5.02922,0,0,1-5.02359,5.02359Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#fff"/>
|
||||
<path id="a8878079-c7cd-406f-a434-8b15b914b9b4-225" data-name="Path 141"
|
||||
d="M935.3957,569.31654H503.18092a5.03014,5.03014,0,0,1-5.02359-5.02359V162.90754a5.03017,5.03017,0,0,1,5.02359-5.02358H935.3957a5.03017,5.03017,0,0,1,5.02359,5.02358V564.292a5.02922,5.02922,0,0,1-5.02359,5.02359ZM503.18092,159.88944a3.01808,3.01808,0,0,0-3.01152,3.01151V564.292a3.01808,3.01808,0,0,0,3.01152,3.01152H935.3957a3.01717,3.01717,0,0,0,3.01153-3.01152V162.90754a3.01809,3.01809,0,0,0-3.01153-3.01151Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#cacaca"/>
|
||||
<path id="af64f961-e9a2-4c53-a333-5060c7f850d2-226" data-name="Path 142"
|
||||
d="M707.41023,262.18528a3.41053,3.41053,0,0,0,0,6.82105H894.55305a3.41053,3.41053,0,0,0,0-6.82105Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#e4e4e4"/>
|
||||
<path id="baad4cfb-158d-4439-9cc3-22475bf47b22-227" data-name="Path 143"
|
||||
d="M707.41023,282.65037a3.41054,3.41054,0,0,0,0,6.82106h95.54019a3.41054,3.41054,0,0,0,0-6.82106Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#e4e4e4"/>
|
||||
<path id="f3456279-91e5-49ad-aa43-9838b26fb6ca-228" data-name="Path 142"
|
||||
d="M543.84146,392.7046a3.41054,3.41054,0,0,0,0,6.82106h350.8937a3.41054,3.41054,0,0,0,0-6.82106Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#e4e4e4"/>
|
||||
<path id="a3288adf-49f8-485f-8ae9-1e4f1a13d849-229" data-name="Path 143"
|
||||
d="M543.84146,413.1697a3.41054,3.41054,0,0,0,0,6.82106H803.13254a3.41054,3.41054,0,0,0,0-6.82106Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#e4e4e4"/>
|
||||
<path id="e63a5b48-5a7d-40a2-b9b0-6adec326348a-230" data-name="Path 142"
|
||||
d="M543.84146,433.17177a3.41054,3.41054,0,0,0,0,6.82106h350.8937a3.41054,3.41054,0,0,0,0-6.82106Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#e4e4e4"/>
|
||||
<path id="a1c669b4-dfc3-4cfa-a7be-66b71399844d-231" data-name="Path 143"
|
||||
d="M543.84146,453.63687a3.41054,3.41054,0,0,0,0,6.82106H803.13254a3.41054,3.41054,0,0,0,0-6.82106Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#e4e4e4"/>
|
||||
<path id="bfec50d1-ffb1-4de6-a9ef-a1085e40e016-232" data-name="Path 142"
|
||||
d="M543.84146,474.17177a3.41054,3.41054,0,0,0,0,6.82106h350.8937a3.41054,3.41054,0,0,0,0-6.82106Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#e4e4e4"/>
|
||||
<path id="bc9696ec-ec99-41d5-9116-3ad9737a38ac-233" data-name="Path 143"
|
||||
d="M543.84146,494.63687a3.41054,3.41054,0,0,0,0,6.82106H803.13254a3.41054,3.41054,0,0,0,0-6.82106Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#e4e4e4"/>
|
||||
<path d="M599.41943,324.82812a49,49,0,1,1,48.99952-49A49.05567,49.05567,0,0,1,599.41943,324.82812Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill={fillColor}/>
|
||||
<path
|
||||
d="M450.67833,510.10041a12.24754,12.24754,0,0,0-14.953-11.36231l-16.19641-22.82521-16.27138,6.45945,23.32519,31.91237a12.31392,12.31392,0,0,0,24.09559-4.1843Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#a0616a"/>
|
||||
<path
|
||||
d="M419.11211,508.40888l-49.00774-63.57777L388.46714,387.12c1.34563-14.50936,10.425-18.56089,10.81135-18.72645l.5893-.25281,15.979,42.6119-11.73235,31.28625,28.79671,48.4319Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M589.30794,312.41993a12.24758,12.24758,0,0,0-10.17219,15.78672l-21.50463,17.91269,7.69816,15.72326,30.01343-25.72272a12.31392,12.31392,0,0,0-6.03477-23.69995Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#a0616a"/>
|
||||
<path
|
||||
d="M590.06206,344.02244l-59.59835,53.77665-58.95815-13.84578c-14.57-.21979-19.31136-8.9587-19.50629-9.33113l-.29761-.568,41.2489-19.22578,32.0997,9.27828,46.06046-32.45509Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#3f3d56"/>
|
||||
<polygon points="227.248 568.437 243.261 568.436 250.878 506.672 227.245 506.673 227.248 568.437"
|
||||
fill="#a0616a"/>
|
||||
<path
|
||||
d="M483.39733,721.74476h50.32614a0,0,0,0,1,0,0V741.189a0,0,0,0,1,0,0h-36.207a14.11914,14.11914,0,0,1-14.11914-14.11914v-5.32505A0,0,0,0,1,483.39733,721.74476Z"
|
||||
transform="translate(757.57348 1305.02654) rotate(179.99738)" fill="#2f2e41"/>
|
||||
<polygon points="163.247 568.437 179.26 568.436 186.878 506.672 163.245 506.673 163.247 568.437"
|
||||
fill="#a0616a"/>
|
||||
<path
|
||||
d="M419.397,721.74476H469.7231a0,0,0,0,1,0,0V741.189a0,0,0,0,1,0,0h-36.207A14.11914,14.11914,0,0,1,419.397,727.06981v-5.32505a0,0,0,0,1,0,0Z"
|
||||
transform="translate(629.57273 1305.02946) rotate(179.99738)" fill="#2f2e41"/>
|
||||
<polygon
|
||||
points="157.552 342.991 158.858 434.42 160.165 554.584 188.899 551.972 203.267 386.094 221.553 551.972 251.218 551.972 254.206 384.788 243.757 348.216 157.552 342.991"
|
||||
fill="#2f2e41"/>
|
||||
<path
|
||||
d="M473.37417,513.1531c-31.26533.00239-60.04471-14.14839-60.43319-14.34263l-.32273-.16136-2.62373-62.96637c-.76082-2.22509-15.74263-46.13091-18.28-60.08625-2.57083-14.13882,34.68842-26.54742,39.213-27.99853l1.02678-11.37405,41.75366-4.49918,5.292,14.5536,14.97942,5.6168a7.40924,7.40924,0,0,1,4.59212,8.7043l-8.32539,33.85619,20.33325,112.01266-4.37755.18946C495.709,511.39658,484.38425,513.1525,473.37417,513.1531Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#3f3d56"/>
|
||||
<circle cx="454.46738" cy="294.45965" r="30.06284"
|
||||
transform="matrix(0.87745, -0.47966, 0.47966, 0.87745, -345.12824, 96.19037)" fill="#a0616a"/>
|
||||
<path
|
||||
d="M430.1166,323.56132c5.72926,6.10289,16.36927,2.82672,17.1158-5.51069a10.07153,10.07153,0,0,0-.01268-1.94523c-.38544-3.69311-2.519-7.046-2.008-10.94542a5.73974,5.73974,0,0,1,1.05046-2.687c4.56548-6.11359,15.28263,2.73444,19.59138-2.8,2.642-3.39359-.46364-8.73664,1.56381-12.52956,2.67591-5.006,10.60183-2.53654,15.57222-5.27809,5.53017-3.05032,5.1994-11.53517,1.55907-16.6961-4.43955-6.294-12.22348-9.65241-19.91044-10.13643s-15.32094,1.59394-22.4974,4.39069c-8.15392,3.17767-16.23969,7.56925-21.25749,14.739-6.10218,8.71919-6.68942,20.44132-3.6376,30.63677C419.10222,311.0013,425.43805,318.57766,430.1166,323.56132Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#2f2e41"/>
|
||||
<path d="M641.58071,741.9626h-381a1,1,0,0,1,0-2h381a1,1,0,0,1,0,2Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#cacaca"/>
|
||||
<path
|
||||
d="M596.58984,294.33545a3.488,3.488,0,0,1-2.38134-.93555l-16.15723-15.00732a3.49994,3.49994,0,0,1,4.76367-5.12891l13.68555,12.71192,27.07666-27.07618a3.5,3.5,0,1,1,4.94922,4.9502l-29.46094,29.46094A3.49275,3.49275,0,0,1,596.58984,294.33545Z"
|
||||
transform="translate(-259.58071 -157.88396)" fill="#fff"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default SvgDone
|
||||
91
src/core/components/svgs/SvgMaintenance.jsx
Normal file
91
src/core/components/svgs/SvgMaintenance.jsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import {useTheme} from "@mui/material";
|
||||
|
||||
const SvgMaintenance = ({width, height}) => {
|
||||
const theme = useTheme()
|
||||
const fillColor = theme.palette.primary.main
|
||||
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width={width} height={height}
|
||||
viewBox="0 0 945 583.2243">
|
||||
<path id="b0cf38c7-358d-48dc-a444-e9782686dfa5-97" data-name="Path 438"
|
||||
d="M222.88482,693.5243a24.21463,24.21463,0,0,0,23.38269-4.11877c8.18977-6.87442,10.758-18.196,12.84671-28.68191l6.17972-31.01657-12.93769,8.90836c-9.30465,6.40641-18.81827,13.01866-25.26012,22.29785s-9.25222,21.94708-4.07792,31.988"
|
||||
transform="translate(-127.5 -158.38785)" fill="#e6e6e6"/>
|
||||
<path id="acbbaa8b-0bc2-4bc9-96d7-93dd88f90f19-98" data-name="Path 439"
|
||||
d="M224.88254,733.23486c-1.6284-11.86369-3.30382-23.88079-2.15885-35.87167,1.01467-10.64933,4.26374-21.04881,10.87831-29.57938a49.20592,49.20592,0,0,1,12.62466-11.44039c1.26216-.79648,2.4241,1.20354,1.16733,1.997A46.77938,46.77938,0,0,0,228.88954,680.666c-4.02858,10.24607-4.67546,21.41582-3.98154,32.30029.41943,6.58218,1.31074,13.12121,2.20587,19.65252a1.19817,1.19817,0,0,1-.808,1.4225,1.16348,1.16348,0,0,1-1.42253-.808Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#f2f2f2"/>
|
||||
<path id="bed63620-84ae-4c66-a7c8-0d9b30f8c1e7-99" data-name="Path 442"
|
||||
d="M236.60356,714.19841A17.82515,17.82515,0,0,0,252.135,722.217c7.8644-.37318,14.41806-5.85972,20.31713-11.07026l17.452-15.40881-11.54988-.5528c-8.30619-.39784-16.82672-.771-24.73813,1.79338s-15.20758,8.72639-16.654,16.9154"
|
||||
transform="translate(-127.5 -158.38785)" fill="#e6e6e6"/>
|
||||
<path id="fc4eb8ca-daad-4589-b224-2c71eec1c546-100" data-name="Path 443"
|
||||
d="M220.27955,740.05454c7.83972-13.87142,16.93235-29.28794,33.1808-34.21551A37.02589,37.02589,0,0,1,267.4158,704.398c1.4819.128,1.1118,2.41174-.367,2.28454a34.39824,34.39824,0,0,0-22.27164,5.89215c-6.27994,4.27453-11.16975,10.21755-15.30781,16.51907-2.5351,3.8605-4.80576,7.88445-7.07642,11.903C221.66738,742.28125,219.54555,741.35371,220.27955,740.05454Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#f2f2f2"/>
|
||||
<path id="ec83fa9a-7bb4-4b90-a90b-e1cec4444963-101" data-name="Path 442"
|
||||
d="M1008.35714,710.03894a17.82515,17.82515,0,0,1-17.065,3.78282c-7.50783-2.37076-12.4416-9.35006-16.813-15.89522l-12.93426-19.3574,11.30757,2.41744c8.132,1.73826,16.46493,3.55513,23.45819,8.05635s12.47224,12.32329,11.77771,20.61"
|
||||
transform="translate(-127.5 -158.38785)" fill="#e6e6e6"/>
|
||||
<path id="e32935a9-e392-46b4-9a67-68c65f1cc9fa-102" data-name="Path 443"
|
||||
d="M1017.53074,739.20841c-4.03412-15.41439-8.88464-32.64277-23.33408-41.55944a37.026,37.026,0,0,0-13.12367-4.9599c-1.46539-.255-1.69126,2.04749-.22905,2.30247a34.39822,34.39822,0,0,1,20.02606,11.3886c4.9789,5.73758,8.18741,12.733,10.57751,19.88279,1.46425,4.38021,2.63106,8.85084,3.79926,13.31624C1015.61991,741.00647,1017.90833,740.652,1017.53074,739.20841Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#f2f2f2"/>
|
||||
<path
|
||||
d="M858.65906,513.48057H594.33494a7.97081,7.97081,0,0,1-7.96157-7.96157V416.34942a7.97081,7.97081,0,0,1,7.96157-7.96157H858.65906a7.9707,7.9707,0,0,1,7.96157,7.96157V505.519A7.9707,7.9707,0,0,1,858.65906,513.48057Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#f1f1f1"/>
|
||||
<rect x="500.27353" y="273.88471" width="70.06181" height="7.96157" fill={fillColor}/>
|
||||
<circle cx="662.68956" cy="278.66165" r="4.77694" fill={fillColor}/>
|
||||
<circle cx="678.6127" cy="278.66165" r="4.77694" fill={fillColor}/>
|
||||
<circle cx="694.53583" cy="278.66165" r="4.77694" fill={fillColor}/>
|
||||
<path
|
||||
d="M858.65906,626.53486H594.33494a7.97081,7.97081,0,0,1-7.96157-7.96157V529.40371a7.97081,7.97081,0,0,1,7.96157-7.96157H858.65906a7.9707,7.9707,0,0,1,7.96157,7.96157v89.16958A7.9707,7.9707,0,0,1,858.65906,626.53486Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#f1f1f1"/>
|
||||
<rect x="500.27353" y="386.939" width="70.06181" height="7.96157" fill={fillColor}/>
|
||||
<circle cx="662.68956" cy="391.71594" r="4.77694" fill={fillColor}/>
|
||||
<circle cx="678.6127" cy="391.71594" r="4.77694" fill={fillColor}/>
|
||||
<circle cx="694.53583" cy="391.71594" r="4.77694" fill={fillColor}/>
|
||||
<path
|
||||
d="M858.65906,739.58915H594.33494a7.97081,7.97081,0,0,1-7.96157-7.96156V642.458a7.97081,7.97081,0,0,1,7.96157-7.96157H858.65906a7.9707,7.9707,0,0,1,7.96157,7.96157v89.16959A7.97069,7.97069,0,0,1,858.65906,739.58915Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#f1f1f1"/>
|
||||
<rect x="500.27353" y="499.99329" width="70.06181" height="7.96157" fill={fillColor}/>
|
||||
<circle cx="662.68956" cy="504.77024" r="4.77694" fill={fillColor}/>
|
||||
<circle cx="678.6127" cy="504.77024" r="4.77694" fill={fillColor}/>
|
||||
<circle cx="694.53583" cy="504.77024" r="4.77694" fill={fillColor}/>
|
||||
<path
|
||||
d="M759.01179,321.31453l-.29232-.216-.007-.00528a3.57626,3.57626,0,0,0-5.00334.73888L694.21319,401.9379h-6.54562v-1.53783a1.43056,1.43056,0,0,0-1.43052-1.43052h-3.90531a1.43056,1.43056,0,0,0-1.43052,1.43052v1.53783h-2.26034v-1.53783a1.43056,1.43056,0,0,0-1.43052-1.43052h-3.9053a1.43057,1.43057,0,0,0-1.43053,1.43052v1.53783h-2.253v-1.53783a1.43057,1.43057,0,0,0-1.43053-1.43052h-3.9053a1.43056,1.43056,0,0,0-1.43052,1.43052v1.53783h-2.26034v-1.53783a1.43056,1.43056,0,0,0-1.43052-1.43052H655.259a1.43057,1.43057,0,0,0-1.43053,1.43052v1.53783h-2.253v-1.53783a1.43057,1.43057,0,0,0-1.43053-1.43052h-3.9053a1.43034,1.43034,0,0,0-1.43052,1.43052v1.53783H642.5488v-1.53783a1.43056,1.43056,0,0,0-1.43052-1.43052H637.213a1.43057,1.43057,0,0,0-1.43053,1.43052v1.53783h-2.26034v-1.53783a1.43056,1.43056,0,0,0-1.43052-1.43052h-3.9053a1.43057,1.43057,0,0,0-1.43053,1.43052v1.53783h-2.253v-1.53783a1.43056,1.43056,0,0,0-1.43052-1.43052h-3.9053a1.43057,1.43057,0,0,0-1.43053,1.43052v1.53783h-2.26034v-1.53783a1.43056,1.43056,0,0,0-1.43052-1.43052h-3.9053a1.43057,1.43057,0,0,0-1.43053,1.43052v1.53783h-2.253v-1.53783a1.43056,1.43056,0,0,0-1.43052-1.43052h-3.90531a1.43056,1.43056,0,0,0-1.43052,1.43052v1.53783H596.858a3.57618,3.57618,0,0,0-3.57631,3.57631V408.926a3.57618,3.57618,0,0,0,3.57631,3.57631h96.76151a5.32944,5.32944,0,0,0,5.21778-4.24744l.037.02751L759.74521,326.325l.00559-.00707A3.57671,3.57671,0,0,0,759.01179,321.31453Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#3f3d56"/>
|
||||
<polygon points="255.504 550.825 267.523 556.976 296.966 513.544 279.228 504.466 255.504 550.825"
|
||||
fill="#ffb7b7"/>
|
||||
<path
|
||||
d="M381.94612,703.72021l23.66983,12.113.001.00049a16.94563,16.94563,0,0,1,7.3641,22.8037l-.25087.49017-38.75427-19.83265Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#2f2e41"/>
|
||||
<polygon points="394.317 567.652 407.819 567.652 414.242 515.575 394.315 515.575 394.317 567.652"
|
||||
fill="#ffb7b7"/>
|
||||
<path
|
||||
d="M518.37323,721.632l26.58922-.00107h.00107a16.94563,16.94563,0,0,1,16.94473,16.94446v.55063l-43.53421.00162Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#2f2e41"/>
|
||||
<path
|
||||
d="M458.66285,301.26058s-9.0412-6.9268-9.0412,9.99291l-1.42756,55.91271,15.94107,52.81966,9.27913-17.1307-3.80682-37.11652Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#2f2e41"/>
|
||||
<path
|
||||
d="M555.37734,454.19165s10.48418,51.058-2.79579,92.95976l-7.33892,161.10695-26.90941-2.09684-9.43576-119.51969-9.0863-59.41037-18.87153,54.16828L418.73348,696.02681l-28.65677-22.36625s31.75629-86.64916,55.2167-104.84184l11.76615-134.011Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#2f2e41"/>
|
||||
<circle cx="523.48018" cy="202.31369" r="30.68251"
|
||||
transform="translate(-32.63308 406.2144) rotate(-61.33685)" fill="#ffb7b7"/>
|
||||
<path
|
||||
d="M521.30883,208.82157c3.67807.47856,6.45254-3.28467,7.73937-6.76336s2.2673-7.5286,5.46514-9.40772c4.36891-2.56725,9.95872.52048,14.95479-.32655,5.64211-.95654,9.31053-6.93607,9.598-12.65146s-1.987-11.21239-4.21862-16.48193l-.77911,6.54884a12.98679,12.98679,0,0,0-5.67512-11.35154l1.00419,9.60941A10.199,10.199,0,0,0,537.6641,159.558l.15814,5.72564c-6.51663-.77489-13.09021-1.55087-19.62615-.96052s-13.11751,2.65828-18.0712,6.96269c-7.40994,6.43874-10.11621,17.04088-9.20765,26.81529s4.94341,18.95675,9.14865,27.827c1.058,2.23177,2.52146,4.75016,4.97491,5.03445,2.20445.25544,4.22155-1.58732,4.90683-3.698a13.40422,13.40422,0,0,0-.0595-6.58474c-.62-3.2946-1.40155-6.6621-.81863-9.96346s2.9579-6.56372,6.28582-6.96831,6.73322,3.3994,5.13321,6.34537Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#2f2e41"/>
|
||||
<polygon points="429.776 309.458 327.357 302.85 335.066 270.913 428.674 291.838 429.776 309.458"
|
||||
fill="#cbcbcb"/>
|
||||
<path
|
||||
d="M494.11389,244.15824l6.424-8.91878s7.18028,2.44014,26.40983,12.01183l1.35857,8.35615L561.685,460.9092,501.01375,458.292l-16.5219-.35153-5.4068-12.12-6.66725,11.86313-16.13421-.34328-16.41693-9.51706,16.179-49.48869,5.23438-45.206-8.0895-42.58883s-10.17937-39.10848,29.027-60.19538Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#2f2e41"/>
|
||||
<path
|
||||
d="M630.86271,399.57305a10.48605,10.48605,0,0,1-13.04108-9.40577L581.82654,380.526l14.48005-12.85707,31.9616,11.12669a10.54289,10.54289,0,0,1,2.59452,20.77747Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#ffb7b7"/>
|
||||
<path
|
||||
d="M614.74112,394.13009a6.14221,6.14221,0,0,1-4.987.39563l-59.21317-22.47383a63.2273,63.2273,0,0,1-34.03214-28.68449l-24.6929-44.04893a19.76509,19.76509,0,1,1,29.49118-26.323L564.04672,340.737l53.7869,31.53448a6.15547,6.15547,0,0,1,2.61747,6.54608l-2.67464,11.33426a6.1431,6.1431,0,0,1-1.86626,3.15032A6.07364,6.07364,0,0,1,614.74112,394.13009Z"
|
||||
transform="translate(-127.5 -158.38785)" fill="#2f2e41"/>
|
||||
<path d="M1071.5,741.38785h-943a1,1,0,0,1,0-2h943a1,1,0,0,1,0,2Z" transform="translate(-127.5 -158.38785)"
|
||||
fill="#cbcbcb"/>
|
||||
</svg>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default SvgMaintenance
|
||||
35
src/core/components/timelines/DoneTimeLine.jsx
Normal file
35
src/core/components/timelines/DoneTimeLine.jsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import {
|
||||
TimelineConnector,
|
||||
TimelineContent,
|
||||
TimelineDot,
|
||||
TimelineItem,
|
||||
TimelineOppositeContent,
|
||||
TimelineSeparator
|
||||
} from "@mui/lab";
|
||||
import DoneIcon from "@mui/icons-material/Done";
|
||||
import {Typography} from "@mui/material";
|
||||
|
||||
const DoneTimeLine = ({date, primaryLabel, secondaryLabel, position}) => {
|
||||
return (
|
||||
<TimelineItem>
|
||||
<TimelineOppositeContent
|
||||
sx={{m: 'auto 0'}}
|
||||
align="right"
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
>{date}</TimelineOppositeContent>
|
||||
<TimelineSeparator>
|
||||
<TimelineDot color={'success'}>
|
||||
<DoneIcon/>
|
||||
</TimelineDot>
|
||||
{position !== 'end' && <TimelineConnector/>}
|
||||
</TimelineSeparator>
|
||||
<TimelineContent sx={{py: '12px', px: 2}}>
|
||||
<Typography variant="h6" component="span">{primaryLabel}</Typography>
|
||||
<Typography variant="body2" color={'gray'}>{secondaryLabel}</Typography>
|
||||
</TimelineContent>
|
||||
</TimelineItem>
|
||||
)
|
||||
}
|
||||
|
||||
export default DoneTimeLine
|
||||
33
src/core/components/timelines/InProgressTimeLine.jsx
Normal file
33
src/core/components/timelines/InProgressTimeLine.jsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import {
|
||||
TimelineConnector,
|
||||
TimelineContent,
|
||||
TimelineDot,
|
||||
TimelineItem,
|
||||
TimelineOppositeContent,
|
||||
TimelineSeparator
|
||||
} from "@mui/lab";
|
||||
import {CircularProgress, Typography} from "@mui/material";
|
||||
|
||||
const InProgressTimeLine = ({date, primaryLabel, secondaryLabel, position}) => {
|
||||
return (
|
||||
<TimelineItem sx={{minHeight: 90}}>
|
||||
<TimelineOppositeContent
|
||||
sx={{m: 'auto 0'}}
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
>{date}</TimelineOppositeContent>
|
||||
<TimelineSeparator>
|
||||
<TimelineDot color="primary">
|
||||
<CircularProgress color={'inherit'} size={40}/>
|
||||
</TimelineDot>
|
||||
{position !== 'end' && <TimelineConnector/>}
|
||||
</TimelineSeparator>
|
||||
<TimelineContent sx={{py: '12px', px: 2}}>
|
||||
<Typography variant="h6" component="span">{primaryLabel}</Typography>
|
||||
<Typography variant="body2" color={'gray'}>{secondaryLabel}</Typography>
|
||||
</TimelineContent>
|
||||
</TimelineItem>
|
||||
)
|
||||
}
|
||||
|
||||
export default InProgressTimeLine
|
||||
34
src/core/components/timelines/OpenTimeLine.jsx
Normal file
34
src/core/components/timelines/OpenTimeLine.jsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import {
|
||||
TimelineConnector,
|
||||
TimelineContent,
|
||||
TimelineDot,
|
||||
TimelineItem,
|
||||
TimelineOppositeContent,
|
||||
TimelineSeparator
|
||||
} from "@mui/lab";
|
||||
import CallMadeIcon from "@mui/icons-material/CallMade";
|
||||
import {Typography} from "@mui/material";
|
||||
|
||||
const OpenTimeLine = ({date, primaryLabel, secondaryLabel, position}) => {
|
||||
return (
|
||||
<TimelineItem>
|
||||
<TimelineOppositeContent
|
||||
sx={{m: 'auto 0'}}
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
>{date}</TimelineOppositeContent>
|
||||
<TimelineSeparator>
|
||||
<TimelineDot>
|
||||
<CallMadeIcon/>
|
||||
</TimelineDot>
|
||||
{position !== 'end' && <TimelineConnector/>}
|
||||
</TimelineSeparator>
|
||||
<TimelineContent sx={{py: '12px', px: 2}}>
|
||||
<Typography variant="h6" component="span">{primaryLabel}</Typography>
|
||||
<Typography variant="body2" color={'gray'}>{secondaryLabel}</Typography>
|
||||
</TimelineContent>
|
||||
</TimelineItem>
|
||||
)
|
||||
}
|
||||
|
||||
export default OpenTimeLine
|
||||
16
src/core/components/timelines/timelineManager.jsx
Normal file
16
src/core/components/timelines/timelineManager.jsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import OpenTimeLine from "@/core/components/timelines/OpenTimeLine";
|
||||
import InProgressTimeLine from "@/core/components/timelines/InProgressTimeLine";
|
||||
import DoneTimeLine from "@/core/components/timelines/DoneTimeLine";
|
||||
|
||||
const TimelineManager = (props) => {
|
||||
switch (props.status) {
|
||||
case 'open':
|
||||
return <OpenTimeLine {...props} />
|
||||
case 'in progress':
|
||||
return <InProgressTimeLine {...props} />
|
||||
case 'done':
|
||||
return <DoneTimeLine {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
export default TimelineManager
|
||||
@@ -5,7 +5,8 @@ export const LOGIN = BASE_URL + "/login";
|
||||
// export const REGISTER_SEND_OTP_TOKEN = BASE_URL + "/register/send_otp";
|
||||
export const SEND_OTP_TOKEN = BASE_URL + "/otp";
|
||||
export const REGISTER = BASE_URL + "/register";
|
||||
export const USER_INFO = BASE_URL + "/profile/info";
|
||||
export const GET_USER = BASE_URL + "/profile/info";
|
||||
export const GET_SIDEBAR_NOTIFICATION = "";
|
||||
export const SHOW_LOAN_REQUEST_NAVGAN = BASE_URL + "/navgan/loan/index";
|
||||
export const SEND_LOAN_REQUEST_NAVGAN = BASE_URL + "/navgan/loan/store";
|
||||
export const SHOW_LOAN_REQUEST_WELFARE = BASE_URL + "/refahi/loan/index";
|
||||
@@ -13,5 +14,8 @@ export const SEND_LOAN_REQUEST_WELFARE = BASE_URL + "/refahi/loan/store";
|
||||
export const UPDATE_LOAN_REQUEST_WELFARE = BASE_URL + "/refahi/loan/update/";
|
||||
export const DETAILS_LOAN_REQUEST_WELFARE = BASE_URL + "/refahi/loan/details/";
|
||||
export const GET_PROVINCE_LIST = BASE_URL + "/provinces";
|
||||
export const GET_CITIES_LIST = BASE_URL + "/cities";
|
||||
export const GET_EDUCATIONS_LIST = BASE_URL + "/education";
|
||||
export const GET_OCCUPATIONS_LIST = BASE_URL + "/occupations";
|
||||
|
||||
|
||||
|
||||
14
src/core/data/languageList.js
Normal file
14
src/core/data/languageList.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import {FA_DATATABLE_LOCALIZATION} from "&/locales/fa/datatable";
|
||||
|
||||
const languageList = [
|
||||
{
|
||||
key: "fa",
|
||||
dir: 'rtl',
|
||||
name: "فارسی",
|
||||
fontFamily: `IRANSans, sans-serif`,
|
||||
tableLocalization: FA_DATATABLE_LOCALIZATION,
|
||||
chartLocalization: null
|
||||
}
|
||||
];
|
||||
|
||||
export default languageList;
|
||||
37
src/core/data/sidebarMenu.js
Normal file
37
src/core/data/sidebarMenu.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import SpaceDashboardIcon from "@mui/icons-material/SpaceDashboard";
|
||||
import BookmarkAddedIcon from "@mui/icons-material/BookmarkAdded";
|
||||
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
|
||||
|
||||
const sidebarMenu = [
|
||||
[
|
||||
{
|
||||
key: "sidebar.dashboard",
|
||||
name: "sidebar.dashboard",
|
||||
type: "page",
|
||||
route: "/dashboard",
|
||||
icon: <SpaceDashboardIcon sx={{width: 'inherit', height: 'inherit'}}/>,
|
||||
selected: false,
|
||||
permission: "all"
|
||||
},
|
||||
{
|
||||
key: "sidebar.add-request-loan",
|
||||
name: "sidebar.add-request-loan",
|
||||
type: "page",
|
||||
route: "/dashboard/navgan/add-request-loan",
|
||||
icon: <DataSaverOnIcon sx={{width: 'inherit', height: 'inherit'}}/>,
|
||||
selected: false,
|
||||
permission: "can_request_navgan_loan"
|
||||
},
|
||||
{
|
||||
key: "sidebar.followUp-loan",
|
||||
name: "sidebar.followUp-loan",
|
||||
type: "page",
|
||||
route: "/dashboard/navgan/followUp-loan",
|
||||
icon: <BookmarkAddedIcon sx={{width: 'inherit', height: 'inherit'}}/>,
|
||||
selected: false,
|
||||
permission: "all"
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
export default sidebarMenu;
|
||||
@@ -1,55 +0,0 @@
|
||||
import SpaceDashboardIcon from "@mui/icons-material/SpaceDashboard";
|
||||
import BookmarkAddedIcon from "@mui/icons-material/BookmarkAdded";
|
||||
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
|
||||
|
||||
const sidebarMenu = [
|
||||
[
|
||||
{
|
||||
key: "sidebar.dashboard",
|
||||
type: "page",
|
||||
route: "/dashboard",
|
||||
icon: <SpaceDashboardIcon/>,
|
||||
userType: 0,
|
||||
selected: false,
|
||||
permission_name: "all"
|
||||
},
|
||||
{
|
||||
key: "sidebar.add-request-loan",
|
||||
type: "page",
|
||||
route: "/dashboard/navgan/add-request-loan",
|
||||
icon: <DataSaverOnIcon/>,
|
||||
userType: 1,
|
||||
selected: false,
|
||||
permission_name: "can_request_a_new_loan"
|
||||
},
|
||||
{
|
||||
key: "sidebar.followUp-loan",
|
||||
type: "page",
|
||||
route: "/dashboard/navgan/followUp-loan",
|
||||
icon: <BookmarkAddedIcon/>,
|
||||
userType: 1,
|
||||
selected: false,
|
||||
permission_name: "all"
|
||||
},
|
||||
{
|
||||
key: "sidebar.add-request-loan",
|
||||
type: "page",
|
||||
route: "/dashboard/refahi/add-request-loan",
|
||||
icon: <DataSaverOnIcon/>,
|
||||
userType: 2,
|
||||
selected: false,
|
||||
permission_name: "can_request_a_new_loan"
|
||||
},
|
||||
{
|
||||
key: "sidebar.followUp-loan",
|
||||
type: "page",
|
||||
route: "/dashboard/refahi/followUp-loan",
|
||||
icon: <BookmarkAddedIcon/>,
|
||||
userType: 2,
|
||||
selected: false,
|
||||
permission_name: "all"
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
export default sidebarMenu;
|
||||
@@ -1,38 +0,0 @@
|
||||
import createCache from "@emotion/cache";
|
||||
import {prefixer} from "stylis";
|
||||
import stylisRTLPlugin from "stylis-plugin-rtl";
|
||||
|
||||
const isBrowser = typeof document !== "undefined";
|
||||
|
||||
export const createEmotionCacheLtr = () => {
|
||||
let insertionPoint;
|
||||
|
||||
if (isBrowser) {
|
||||
const emotionInsertionPoint = document.querySelector(
|
||||
'meta[name="emotion-insertion-point"]'
|
||||
);
|
||||
insertionPoint = emotionInsertionPoint ?? undefined;
|
||||
}
|
||||
|
||||
return createCache({
|
||||
key: "mui-style",
|
||||
insertionPoint,
|
||||
});
|
||||
};
|
||||
|
||||
export const createEmotionCacheRtl = () => {
|
||||
let insertionPoint;
|
||||
|
||||
if (isBrowser) {
|
||||
const emotionInsertionPoint = document.querySelector(
|
||||
'meta[name="emotion-insertion-point"]'
|
||||
);
|
||||
insertionPoint = emotionInsertionPoint ?? undefined;
|
||||
}
|
||||
|
||||
return createCache({
|
||||
key: "muirtl",
|
||||
stylisPlugins: [prefixer, stylisRTLPlugin],
|
||||
insertionPoint,
|
||||
});
|
||||
};
|
||||
@@ -1,62 +0,0 @@
|
||||
import ErrorNotification from "@/core/components/notifications/ErrorNotification";
|
||||
import WarningNotification from "@/core/components/notifications/WarningNotification";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
export const errorSetting = (t, notification) => {
|
||||
if (notification) toast.dismiss();
|
||||
}
|
||||
|
||||
export const errorRequest = (t, notification) => {
|
||||
if (notification) toast.dismiss();
|
||||
}
|
||||
|
||||
export const errorResponse = (response, clearToken, t, notification) => {
|
||||
if (notification) toast.dismiss();
|
||||
if (isServerError(response.status)) {
|
||||
errorServer(response, t, notification)
|
||||
} else if (isClientError(response.status)) {
|
||||
errorClient(response, clearToken, t, notification)
|
||||
}
|
||||
}
|
||||
|
||||
const errorServer = (response, t, notification) => {
|
||||
if (notification) WarningNotification(t, response.status);
|
||||
}
|
||||
const errorClient = (response, clearToken, t, notification) => {
|
||||
switch (response.status) {
|
||||
case 401:
|
||||
clearToken()
|
||||
if (notification) ErrorNotification(t, response.status)
|
||||
break;
|
||||
case 422:
|
||||
if ('type' in response.data) {
|
||||
errorLogic(response, t, notification)
|
||||
break;
|
||||
}
|
||||
errorValidation(response, t, notification)
|
||||
break;
|
||||
case 429:
|
||||
if (notification) ErrorNotification(t, response.status)
|
||||
break
|
||||
default:
|
||||
if (notification) ErrorNotification(t, response.status)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const isServerError = status => status >= 500 && status <= 599;
|
||||
const isClientError = status => status >= 400 && status <= 499;
|
||||
|
||||
const errorLogic = (response, t, notification) => {
|
||||
if (notification) ErrorNotification(t, response.status, response.data.message)
|
||||
}
|
||||
const errorValidation = (response, t, notification) => {
|
||||
if (notification) {
|
||||
const errorsMap = Object.keys(response.data.errors)
|
||||
const errorsArray = response.data.errors
|
||||
|
||||
errorsMap.map((item, index) => {
|
||||
ErrorNotification(t, response.status, errorsArray[item][0]);
|
||||
})
|
||||
}
|
||||
}
|
||||
12
src/core/utils/globalServerProps.js
Normal file
12
src/core/utils/globalServerProps.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import {parse} from "next-useragent";
|
||||
|
||||
export const globalServerProps = async ({req, locale}) => {
|
||||
const {isBot} = parse(req.headers["user-agent"]);
|
||||
|
||||
return {
|
||||
config: (await import(`&/config.json`)).default,
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
isBot,
|
||||
locale,
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import SuccessNotification from "@/core/components/notifications/SuccessNotification";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
export const successRequest = (response, t, options) => {
|
||||
if (options.notification && options.success.notification.show) {
|
||||
toast.dismiss();
|
||||
SuccessNotification(t, response.status)
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
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 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();
|
||||
const {setLoadingPage} = useLoading();
|
||||
const {userChangedLanguage, token, isAuth} = useUser();
|
||||
const {directionApp} = useDirection();
|
||||
|
||||
useEffect(() => {
|
||||
if (languageIsReady) {
|
||||
if (token) {
|
||||
if (isAuth) {
|
||||
if (userChangedLanguage) {
|
||||
setLoadingPage(true);
|
||||
return;
|
||||
}
|
||||
setLoadingPage(false);
|
||||
return;
|
||||
}
|
||||
setLoadingPage(true);
|
||||
return;
|
||||
}
|
||||
setLoadingPage(false);
|
||||
return;
|
||||
}
|
||||
setLoadingPage(true);
|
||||
}, [languageIsReady, token, isAuth, userChangedLanguage]);
|
||||
|
||||
if (!isBot) {
|
||||
if (userChangedLanguage) return;
|
||||
if (!languageIsReady) return;
|
||||
}
|
||||
|
||||
return (<>
|
||||
<GlobalHead/>
|
||||
<NextNProgress
|
||||
color={theme.palette.secondary.dark}
|
||||
options={{showSpinner: false}}
|
||||
/>
|
||||
<ToastContainer position={directionApp === "ltr" ? "top-left" : "top-right"} rtl={directionApp === 'rtl'}/>
|
||||
<NetworkComponent/>
|
||||
{children}
|
||||
</>);
|
||||
}
|
||||
|
||||
export default AppLayout;
|
||||
@@ -1,18 +0,0 @@
|
||||
import {Fade, Stack} from "@mui/material";
|
||||
|
||||
const CenterLayout = (props) => {
|
||||
return (
|
||||
<Fade in={true}>
|
||||
<Stack
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
spacing={props?.spacing}
|
||||
sx={{flex: 1, ...props?.sx, py: 3}}
|
||||
>
|
||||
{props.children}
|
||||
</Stack>
|
||||
</Fade>
|
||||
);
|
||||
};
|
||||
|
||||
export default CenterLayout;
|
||||
@@ -1,21 +0,0 @@
|
||||
import {Stack} from "@mui/material";
|
||||
|
||||
const FullPageLayout = (props) => {
|
||||
return (
|
||||
<Stack
|
||||
spacing={props?.spacing}
|
||||
direction={props?.direction}
|
||||
sx={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
overflowY: "scroll",
|
||||
overflowX: "scroll",
|
||||
...props?.sx,
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default FullPageLayout;
|
||||
@@ -1,75 +0,0 @@
|
||||
import NoSsrHandler from "@/core/components/NoSsrHandler";
|
||||
import {createEmotionCacheRtl} from "@/core/utils/createEmotionCache";
|
||||
import themeRtl from "@/core/utils/theme-rtl";
|
||||
import {CacheProvider} from "@emotion/react";
|
||||
import {GlobalStyles} from "@mui/material";
|
||||
import CssBaseline from "@mui/material/CssBaseline";
|
||||
import {ThemeProvider} from "@mui/material/styles";
|
||||
import Head from "next/head";
|
||||
|
||||
const clientSideEmotionCacheRtl = createEmotionCacheRtl();
|
||||
|
||||
const MuiLayout = ({children, isBot}) => {
|
||||
|
||||
const emotionCache = clientSideEmotionCacheRtl;
|
||||
|
||||
const theme = themeRtl;
|
||||
|
||||
return (
|
||||
<NoSsrHandler isBot={isBot}>
|
||||
<CacheProvider value={emotionCache}>
|
||||
<Head>
|
||||
<meta name="viewport" content="initial-scale=1, width=device-width"/>
|
||||
</Head>
|
||||
<ThemeProvider theme={theme}>
|
||||
<GlobalStyles
|
||||
styles={{
|
||||
"*:not(.MuiTableContainer-root)::-webkit-scrollbar": {
|
||||
display: "none",
|
||||
},
|
||||
"*::-webkit-scrollbar": {
|
||||
height: "8px",
|
||||
},
|
||||
"*::-webkit-scrollbar-thumb": {
|
||||
background: `${theme.palette.primary.light}80`,
|
||||
borderRadius: "3px",
|
||||
},
|
||||
"*:not(.MuiTableContainer-root)": {
|
||||
scrollbarWidth: "thin",
|
||||
scrollbarColor: "transparent transparent",
|
||||
},
|
||||
|
||||
"*": {
|
||||
scrollbarWidth: "thin",
|
||||
scrollbarColor: `${theme.palette.primary.light}80 transparent`,
|
||||
},
|
||||
|
||||
"*::-moz-scrollbar-thumb": {
|
||||
backgroundColor: `${theme.palette.primary.light}80`,
|
||||
},
|
||||
[`@media (max-width: ${theme.breakpoints.values.sm}px)`]: {
|
||||
"*::-webkit-scrollbar": {
|
||||
height: "4px",
|
||||
},
|
||||
},
|
||||
|
||||
body: {
|
||||
width: "100vw",
|
||||
height: "100vh",
|
||||
},
|
||||
"#__next": {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
<CssBaseline/>
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
</CacheProvider>
|
||||
</NoSsrHandler>
|
||||
);
|
||||
};
|
||||
|
||||
export default MuiLayout;
|
||||
@@ -1,25 +0,0 @@
|
||||
import {Box, Fade} from "@mui/material";
|
||||
|
||||
const ScrollableLayout = (props) => {
|
||||
const overflowY = props?.y || "hidden";
|
||||
const overflowX = props?.x || "hidden";
|
||||
|
||||
return (
|
||||
<Fade in={true}>
|
||||
<Box
|
||||
spacing={props?.spacing}
|
||||
sx={{
|
||||
width: "auto",
|
||||
height: "auto",
|
||||
overflowY: overflowY,
|
||||
overflowX: overflowX,
|
||||
...props?.sx,
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</Box>
|
||||
</Fade>
|
||||
);
|
||||
};
|
||||
|
||||
export default ScrollableLayout;
|
||||
29
src/layouts/dashboard.jsx
Normal file
29
src/layouts/dashboard.jsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import {DashboardLayout as DashboardLayoutPure, useUser} from "@witel/webapp-builder";
|
||||
import headerProfileItems from "@/core/data/headerProfileItems";
|
||||
import sidebarMenu from "@/core/data/sidebarMenu";
|
||||
import {GET_SIDEBAR_NOTIFICATION} from "@/core/data/apiRoutes";
|
||||
import UserInfo from "@/middlewares/UserInfo";
|
||||
import {useTranslations} from "next-intl";
|
||||
import moment from "jalali-moment";
|
||||
|
||||
const DashboardLayout = (props) => {
|
||||
const {user} = useUser()
|
||||
const middlewaresProps = props.middlewaresProps || {}
|
||||
const t = useTranslations()
|
||||
return (
|
||||
<>
|
||||
<DashboardLayoutPure
|
||||
middlewares={{list: [UserInfo], props: {...middlewaresProps,loginUrl:'/login'}}}
|
||||
user_introduction={user.phone_number}
|
||||
headerProfileItems={headerProfileItems}
|
||||
headerSubtitle={`${t('today')} ${moment().locale('fa').format('LL')}`}
|
||||
sidebarMenu={sidebarMenu}
|
||||
urlNotification={GET_SIDEBAR_NOTIFICATION}
|
||||
BC_segmentsToRemove={['navgan']}
|
||||
{...props}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default DashboardLayout
|
||||
@@ -1,19 +0,0 @@
|
||||
import LinkRouting from "@/core/components/LinkRouting";
|
||||
import {Typography} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
|
||||
export default function BreadcrumbItem(props) {
|
||||
const t = useTranslations();
|
||||
const isLast = props.index === props.RouterArray.length - 1;
|
||||
const url = `/${props.RouterArray.slice(0, props.index + 1).join("/")}`;
|
||||
|
||||
return isLast ? (
|
||||
<Typography variant="body2" color="primary">
|
||||
{t("sidebar." + props.label)}
|
||||
</Typography>
|
||||
) : (
|
||||
<LinkRouting underline="hover" color="inherit" passHref href={url}>
|
||||
<Typography variant="body2">{t("sidebar." + props.label)}</Typography>
|
||||
</LinkRouting>
|
||||
);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
import {useRouter} from "next/router";
|
||||
import {Box, Breadcrumbs} from "@mui/material";
|
||||
import {useTheme} from "@mui/material/styles";
|
||||
import {NavigateBefore, NavigateNext} from "@mui/icons-material";
|
||||
import BreadcrumbItem from "./BreadcrumbItem";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
|
||||
const BreadCrumbs = (props) => {
|
||||
const {isVisible} = props;
|
||||
const theme = useTheme();
|
||||
const router = useRouter();
|
||||
const {user} = useUser();
|
||||
|
||||
if (!isVisible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {pathname} = router;
|
||||
const RouterArray = pathname.split("/").filter((segment) => segment !== "");
|
||||
|
||||
// every part of your router you want to remove add it to this array
|
||||
const segmentsToRemove = ["navgan", "refahi", "[id]"];
|
||||
|
||||
segmentsToRemove.forEach((segmentToRemove) => {
|
||||
const index = RouterArray.indexOf(segmentToRemove);
|
||||
if (index !== -1) {
|
||||
RouterArray.splice(index, 1);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (RouterArray.length === 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box p={3} component="span">
|
||||
<Breadcrumbs
|
||||
maxItems={2}
|
||||
separator={
|
||||
theme.direction === "ltr" ? (
|
||||
<NavigateNext fontSize="small"/>
|
||||
) : (
|
||||
<NavigateBefore fontSize="small"/>
|
||||
)
|
||||
}
|
||||
aria-label="breadcrumb"
|
||||
>
|
||||
{RouterArray.map((segment, index) => (
|
||||
<BreadcrumbItem
|
||||
RouterArray={RouterArray}
|
||||
label={segment}
|
||||
key={segment}
|
||||
index={index}
|
||||
/>
|
||||
))}
|
||||
</Breadcrumbs>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default BreadCrumbs;
|
||||
@@ -1,15 +0,0 @@
|
||||
import {Avatar, Stack} from "@mui/material";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
|
||||
export default function ProfileData() {
|
||||
const {user} = useUser();
|
||||
return (
|
||||
<Stack alignItems="center" spacing={2} sx={{p: 3}}>
|
||||
<Avatar
|
||||
sx={{width: "80px", height: "80px"}}
|
||||
alt="User Image"
|
||||
src={user.user_avatar}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
import {Avatar, IconButton, Menu, Tooltip} from "@mui/material";
|
||||
import {useState} from "react";
|
||||
import ProfileData from "./ProfileData";
|
||||
import ProfileOptions from "./ProfileOptions";
|
||||
import {useTranslations} from "next-intl";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
|
||||
function ProfileMenu() {
|
||||
const t = useTranslations();
|
||||
const [anchorElUser, setAnchorElUser] = useState(null);
|
||||
const {user} = useUser();
|
||||
|
||||
const handleOpenUserMenu = (event) => {
|
||||
setAnchorElUser(event.currentTarget);
|
||||
};
|
||||
const handleCloseUserMenu = () => {
|
||||
setAnchorElUser(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title={t("header.open_profile")} arrow>
|
||||
<IconButton onClick={handleOpenUserMenu} sx={{p: 0}}>
|
||||
<Avatar
|
||||
sx={{
|
||||
width: 24,
|
||||
height: 24,
|
||||
backgroundColor: "#fff",
|
||||
color: "primary.main",
|
||||
}}
|
||||
alt="User Image"
|
||||
src={user.user_avatar}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Menu
|
||||
MenuListProps={{sx: {py: 0}}}
|
||||
sx={{
|
||||
mt: 6,
|
||||
}}
|
||||
id="menu-appbar"
|
||||
anchorEl={anchorElUser}
|
||||
anchorOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
keepMounted
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
open={Boolean(anchorElUser)}
|
||||
onClose={handleCloseUserMenu}
|
||||
>
|
||||
<ProfileData/>
|
||||
<ProfileOptions handleCloseUserMenu={handleCloseUserMenu}/>
|
||||
</Menu>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProfileMenu;
|
||||
@@ -1,49 +0,0 @@
|
||||
import {Box, Button, MenuItem, Typography} from "@mui/material";
|
||||
import MeetingRoomIcon from "@mui/icons-material/MeetingRoom";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import {useTranslations} from "next-intl";
|
||||
|
||||
export default function ProfileOptionLogOut({handleCloseUserMenu}) {
|
||||
const t = useTranslations();
|
||||
const {clearToken} = useUser();
|
||||
const handleClickLogOut = () => {
|
||||
handleCloseUserMenu();
|
||||
clearToken();
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<MenuItem
|
||||
component={Button}
|
||||
to={{
|
||||
pathname: "/dashboard/logout",
|
||||
}}
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
borderTop: 1,
|
||||
px: 3,
|
||||
py: 1.5,
|
||||
borderColor: "#e1e1e1",
|
||||
textTransform: "unset",
|
||||
}}
|
||||
onClick={handleClickLogOut}
|
||||
>
|
||||
<Box sx={{display: "flex", alignItems: "center", flex: 1}}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
color: "primary.main",
|
||||
pr: 2,
|
||||
}}
|
||||
>
|
||||
<MeetingRoomIcon/>
|
||||
</Box>
|
||||
<Typography sx={{flex: 1}} textAlign="start">
|
||||
{t("header.logout")}
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import {Box, MenuItem, Typography} from "@mui/material";
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import {useTranslations} from "next-intl";
|
||||
import headerProfileItems from "@/core/data/headerProfileItems";
|
||||
import ProfileOptionLogOut from "./ProfileOptionLogOut";
|
||||
|
||||
export default function ProfileOptions({handleCloseUserMenu}) {
|
||||
const t = useTranslations();
|
||||
|
||||
return (
|
||||
<>
|
||||
{headerProfileItems.map((profile_item) => (
|
||||
<MenuItem
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: profile_item.route,
|
||||
}}
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
borderTop: 1,
|
||||
px: 3,
|
||||
py: 1.5,
|
||||
borderColor: "#e1e1e1",
|
||||
}}
|
||||
key={profile_item.key}
|
||||
onClick={handleCloseUserMenu}
|
||||
>
|
||||
<Box sx={{display: "flex", alignItems: "center", flex: 1}}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
color: "primary.main",
|
||||
pr: 2,
|
||||
}}
|
||||
>
|
||||
{profile_item.icon}
|
||||
</Box>
|
||||
<Typography sx={{flex: 1}} textAlign="start">
|
||||
{t(profile_item.name)}
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
<ProfileOptionLogOut handleCloseUserMenu={handleCloseUserMenu}/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
import MenuIcon from "@mui/icons-material/Menu";
|
||||
import {AppBar, Box, Container, CssBaseline, IconButton, Stack, Toolbar, useTheme} from "@mui/material";
|
||||
import ProfileMenu from "./ProfileMenu";
|
||||
|
||||
function Header({drawerWidth, handleDrawerToggle}) {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<>
|
||||
<CssBaseline/>
|
||||
<AppBar
|
||||
position="fixed"
|
||||
sx={{
|
||||
width: {md: `calc(100% - ${drawerWidth}px)`},
|
||||
ml: {md: `${drawerWidth}px`},
|
||||
}}
|
||||
>
|
||||
<Container maxWidth="xxl">
|
||||
<Toolbar
|
||||
disableGutters
|
||||
sx={{
|
||||
display: "flex",
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" justifyContent="flex-start" sx={{flex: 1}}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
aria-label="open drawer"
|
||||
onClick={handleDrawerToggle}
|
||||
edge="start"
|
||||
sx={{display: {md: "none"}, m: 0}}
|
||||
>
|
||||
<MenuIcon/>
|
||||
</IconButton>
|
||||
</Stack>
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="center"
|
||||
sx={{
|
||||
flex: 1,
|
||||
position: "relative",
|
||||
...theme.mixins.toolbar,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: "relative",
|
||||
my: 1,
|
||||
width: 56,
|
||||
height: 56,
|
||||
"@media (min-width:600px)": {maxWidth: 64, maxHeight: 64},
|
||||
"@media (min-width:0px)": {
|
||||
"@media (orientation: landscape)": {
|
||||
width: 48,
|
||||
height: 48,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Stack direction="row" justifyContent="flex-end" sx={{flex: 1}}>
|
||||
<ProfileMenu/>
|
||||
</Stack>
|
||||
</Toolbar>
|
||||
</Container>
|
||||
</AppBar>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default Header;
|
||||
@@ -1,49 +0,0 @@
|
||||
import {useState} from "react";
|
||||
import FullPageLayout from "../FullPageLayout";
|
||||
import Header from "./header";
|
||||
import Sidebar from "./sidebar";
|
||||
import {Toolbar} from "@mui/material";
|
||||
import BreadCrumbs from "./breadcrumbs";
|
||||
import {ToastContainer} from "react-toastify";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
import useDirection from "@/lib/app/hooks/useDirection";
|
||||
|
||||
const drawerWidth = 240;
|
||||
|
||||
const DashboardLayouts = (props) => {
|
||||
const {directionApp} = useDirection();
|
||||
const {window} = props;
|
||||
const [mobileOpen, setMobileOpen] = useState(false);
|
||||
const container =
|
||||
window !== undefined ? () => window().document.body : undefined;
|
||||
|
||||
const handleDrawerToggle = () => {
|
||||
setMobileOpen(!mobileOpen);
|
||||
};
|
||||
return (
|
||||
<FullPageLayout direction="row">
|
||||
<Header
|
||||
handleDrawerToggle={handleDrawerToggle}
|
||||
drawerWidth={drawerWidth}
|
||||
/>
|
||||
<Sidebar
|
||||
container={container}
|
||||
mobileOpen={mobileOpen}
|
||||
handleDrawerToggle={handleDrawerToggle}
|
||||
drawerWidth={drawerWidth}
|
||||
/>
|
||||
<FullPageLayout
|
||||
component="main"
|
||||
sx={{flexGrow: 1, width: {sm: `calc(100% - ${drawerWidth}px)`}}}
|
||||
>
|
||||
<Toolbar/>
|
||||
<FullPageLayout sx={{mt: 3}}>
|
||||
<BreadCrumbs isVisible={true}/>
|
||||
{props.children}
|
||||
</FullPageLayout>
|
||||
</FullPageLayout>
|
||||
</FullPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default DashboardLayouts;
|
||||
@@ -1,26 +0,0 @@
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import {Divider, Stack, Toolbar, Typography} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import SidebarList from "./SidebarList";
|
||||
|
||||
const SidebarDrawer = ({handleDrawerToggle}) => {
|
||||
const {user} = useUser();
|
||||
const t = useTranslations();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Toolbar>
|
||||
<Stack>
|
||||
<Typography variant="h6" sx={{color: "primary.main"}}>
|
||||
{t("app_short_name")}
|
||||
</Typography>
|
||||
<Typography variant="caption">{user.type_name}</Typography>
|
||||
</Stack>
|
||||
</Toolbar>
|
||||
<Divider/>
|
||||
<SidebarList handleDrawerToggle={handleDrawerToggle}/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SidebarDrawer;
|
||||
@@ -1,69 +0,0 @@
|
||||
import {Divider, List} from "@mui/material";
|
||||
import {Fragment, useEffect, useReducer} from "react";
|
||||
import SidebarListItem from "./SidebarListItem";
|
||||
import sidebarMenu from "@/core/data/sidebarMenu";
|
||||
import {useRouter} from "next/router";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
|
||||
function reducer(state, action) {
|
||||
switch (action.type) {
|
||||
case "COLLAPSE_MENU":
|
||||
return state.map((itemsArr) =>
|
||||
itemsArr.map((item) =>
|
||||
action.key == item.key
|
||||
? {...item, showSubItem: !item.showSubItem}
|
||||
: item
|
||||
)
|
||||
);
|
||||
case "SELECTED":
|
||||
return state.map((itemsArr) =>
|
||||
itemsArr.map((item) =>
|
||||
action.route == item.route
|
||||
? {...item, selected: true}
|
||||
: {...item, selected: false}
|
||||
)
|
||||
);
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
export default function SidebarList({handleDrawerToggle}) {
|
||||
const [itemMenu, dispatch] = useReducer(reducer, sidebarMenu);
|
||||
const {user} = useUser();
|
||||
|
||||
// activate current page in menu
|
||||
const router = useRouter();
|
||||
useEffect(() => {
|
||||
dispatch({type: "SELECTED", route: router.pathname});
|
||||
}, [router.pathname]);
|
||||
|
||||
return (
|
||||
<List>
|
||||
{itemMenu.map((itemArr, index) => (
|
||||
<Fragment key={index}>
|
||||
{itemArr.map((item) => {
|
||||
if (
|
||||
(item.userType === user.type_id || item.userType === 0) &&
|
||||
(user[item.permission_name] || item.permission_name === "all")
|
||||
) {
|
||||
return (
|
||||
<SidebarListItem
|
||||
item={item}
|
||||
dispatch={dispatch}
|
||||
key={item.key}
|
||||
handleDrawerToggle={handleDrawerToggle}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
<Divider/>
|
||||
</Fragment>
|
||||
)
|
||||
)}
|
||||
</List>
|
||||
)
|
||||
;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import ExpandLess from "@mui/icons-material/ExpandLess";
|
||||
import ExpandMore from "@mui/icons-material/ExpandMore";
|
||||
import {ListItem, ListItemButton, ListItemIcon, ListItemText,} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {Fragment} from "react";
|
||||
import SidebarListSubItem from "./SidebarListSubItem";
|
||||
|
||||
const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
|
||||
const t = useTranslations();
|
||||
|
||||
return (
|
||||
<Fragment key={item.key}>
|
||||
<ListItem disablePadding sx={{display: "block"}}>
|
||||
<ListItemButton
|
||||
selected={item.selected}
|
||||
{...(item.type == "page" && {
|
||||
component: NextLinkComposed,
|
||||
to: {
|
||||
pathname: item.route,
|
||||
},
|
||||
})}
|
||||
onClick={() => {
|
||||
if (item.type == "menu") {
|
||||
dispatch({type: "COLLAPSE_MENU", key: item.key});
|
||||
}
|
||||
handleDrawerToggle();
|
||||
}}
|
||||
sx={{
|
||||
minHeight: 48,
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
justifyContent: "center",
|
||||
color: "primary.main",
|
||||
pr: 2,
|
||||
}}
|
||||
>
|
||||
{item.icon}
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={t(item.key)}/>
|
||||
|
||||
{item.type == "menu" &&
|
||||
(item.showSubItem ? <ExpandLess/> : <ExpandMore/>)}
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
{item.subItem && (
|
||||
<SidebarListSubItem
|
||||
item={item}
|
||||
handleDrawerToggle={handleDrawerToggle}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default SidebarListItem;
|
||||
@@ -1,48 +0,0 @@
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import InboxIcon from "@mui/icons-material/MoveToInbox";
|
||||
import {Collapse, List, ListItemButton, ListItemIcon, ListItemText,} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {Fragment} from "react";
|
||||
|
||||
const SidebarListSubItem = ({item, handleDrawerToggle}) => {
|
||||
const t = useTranslations();
|
||||
|
||||
return (
|
||||
<Collapse in={item.showSubItem} timeout="auto" unmountOnExit>
|
||||
<List component="div" disablePadding sx={{bgcolor: "#f6f6f6"}}>
|
||||
{item.subItem.map((subitem, index) => (
|
||||
<Fragment key={subitem.key}>
|
||||
<ListItemButton
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: subitem.route,
|
||||
}}
|
||||
sx={{
|
||||
minHeight: 48,
|
||||
}}
|
||||
onClick={(event) => {
|
||||
if (item.type == "menu") {
|
||||
dispatch({type: "COLLAPSE_MENU", key: item.key});
|
||||
}
|
||||
handleDrawerToggle();
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
justifyContent: "center",
|
||||
pr: 2,
|
||||
}}
|
||||
>
|
||||
<InboxIcon/>
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={t(subitem.key)}/>
|
||||
</ListItemButton>
|
||||
</Fragment>
|
||||
))}
|
||||
</List>
|
||||
</Collapse>
|
||||
);
|
||||
};
|
||||
|
||||
export default SidebarListSubItem;
|
||||
@@ -1,46 +0,0 @@
|
||||
import {Box, Drawer} from "@mui/material";
|
||||
import SidebarDrawer from "./SidebarDrawer";
|
||||
|
||||
const Sidebar = (props) => {
|
||||
return (
|
||||
<Box
|
||||
component="nav"
|
||||
sx={{width: {md: props.drawerWidth}, flexShrink: {sm: 0}}}
|
||||
aria-label="mailbox folders"
|
||||
>
|
||||
<Drawer
|
||||
container={props.container}
|
||||
variant="temporary"
|
||||
open={props.mobileOpen}
|
||||
onClose={props.handleDrawerToggle}
|
||||
ModalProps={{
|
||||
keepMounted: true,
|
||||
}}
|
||||
sx={{
|
||||
display: {xs: "block", md: "none"},
|
||||
"& .MuiDrawer-paper": {
|
||||
boxSizing: "border-box",
|
||||
width: props.drawerWidth,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle}/>
|
||||
</Drawer>
|
||||
<Drawer
|
||||
variant="permanent"
|
||||
sx={{
|
||||
display: {xs: "none", md: "block"},
|
||||
"& .MuiDrawer-paper": {
|
||||
boxSizing: "border-box",
|
||||
width: props.drawerWidth,
|
||||
},
|
||||
}}
|
||||
open
|
||||
>
|
||||
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle}/>
|
||||
</Drawer>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
16
src/layouts/index.jsx
Normal file
16
src/layouts/index.jsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import {Fragment} from "react";
|
||||
|
||||
const layoutList = (await import('./list'))
|
||||
|
||||
const Layout = ({layout, children}) => {
|
||||
const Component = layoutList[layout?.name] || Fragment
|
||||
const props = layout?.props || {}
|
||||
|
||||
return (
|
||||
<Component {...props}>
|
||||
{children}
|
||||
</Component>
|
||||
)
|
||||
}
|
||||
|
||||
export default Layout
|
||||
3
src/layouts/list.jsx
Normal file
3
src/layouts/list.jsx
Normal file
@@ -0,0 +1,3 @@
|
||||
import DashboardLayout from './dashboard'
|
||||
|
||||
export {DashboardLayout}
|
||||
@@ -1,99 +0,0 @@
|
||||
import {FA_DATATABLE_LOCALIZATION} from "&/locales/fa/datatable";
|
||||
import {useRouter} from "next/router";
|
||||
import {createContext, useEffect, useState} from "react";
|
||||
import useUser from "../hooks/useUser";
|
||||
|
||||
export const LanguageContext = createContext();
|
||||
|
||||
export const LanguageProvider = ({children}) => {
|
||||
const router = useRouter();
|
||||
const languageList = [
|
||||
{
|
||||
key: "fa",
|
||||
dir: "rtl",
|
||||
name: "فارسی",
|
||||
fontFamily: `IRANSans, sans-serif`,
|
||||
tableLocalization: FA_DATATABLE_LOCALIZATION,
|
||||
}
|
||||
];
|
||||
const {user, userChangedLanguage, changeLanguageState} = useUser();
|
||||
const [languageIsReady, setLanguageIsReady] = useState(false);
|
||||
const [languageApp, setLanguageApp] = useState();
|
||||
const [directionApp, setDirectionApp] = useState(
|
||||
process.env.NEXT_PUBLIC_DEFAULT_DIRECTION
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const lang = localStorage.getItem("_language");
|
||||
|
||||
if (!lang && !languageApp) {
|
||||
setLanguageApp(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE);
|
||||
} else if (lang) {
|
||||
setLanguageApp(lang);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!languageApp) return;
|
||||
|
||||
const lang = localStorage.getItem("_language");
|
||||
|
||||
if (!lang) {
|
||||
localStorage.setItem("_language", languageApp);
|
||||
} else {
|
||||
if (languageApp != lang) {
|
||||
localStorage.setItem("_language", languageApp);
|
||||
}
|
||||
}
|
||||
}, [languageApp]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!router.isReady) return;
|
||||
if (user.user_language) {
|
||||
if (user.user_language != languageApp) {
|
||||
setLanguageApp(user.user_language);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (languageApp != router.locale) {
|
||||
router.replace(
|
||||
{pathname: router.pathname, query: router.query},
|
||||
router.asPath,
|
||||
{
|
||||
locale: languageApp,
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
for (const lang of languageList) {
|
||||
if (languageApp != lang.key) continue;
|
||||
setDirectionApp(lang.dir);
|
||||
document.dir = lang.dir;
|
||||
}
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
changeLanguageState(false);
|
||||
setLanguageIsReady(true);
|
||||
}, 1000);
|
||||
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
};
|
||||
}, [router.locale, router.isReady, userChangedLanguage, languageApp]);
|
||||
|
||||
return (
|
||||
<LanguageContext.Provider
|
||||
value={{
|
||||
languageApp,
|
||||
setLanguageApp,
|
||||
directionApp,
|
||||
languageIsReady,
|
||||
setLanguageIsReady,
|
||||
languageList,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</LanguageContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
import LoadingHardPage from "@/core/components/LoadingHardPage";
|
||||
import {createContext, useState} from "react";
|
||||
|
||||
export const LoadingContext = createContext();
|
||||
|
||||
export const LoadingProvider = ({children}) => {
|
||||
const [loadingPage, setLoadingPage] = useState(false);
|
||||
return (
|
||||
<LoadingContext.Provider value={{loadingPage, setLoadingPage}}>
|
||||
<LoadingHardPage loading={loadingPage}/>
|
||||
{children}
|
||||
</LoadingContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -1,133 +0,0 @@
|
||||
import {USER_INFO} from "@/core/data/apiRoutes";
|
||||
import axios from "axios";
|
||||
import {createContext, useCallback, useEffect, useReducer} from "react";
|
||||
import {errorRequest, errorResponse, errorSetting} from "@/core/utils/errorHandler";
|
||||
|
||||
const initialUser = {
|
||||
isAuth: false,
|
||||
userChangedLanguage: false,
|
||||
token: null,
|
||||
user: {},
|
||||
};
|
||||
|
||||
const reducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case "CLEAR_USER":
|
||||
return {...state, user: {}};
|
||||
case "CHANGE_USER":
|
||||
return {...state, user: action.user};
|
||||
case "CHANGE_USER_LANGUAGE":
|
||||
return {
|
||||
...state,
|
||||
user: {...state.user, user_language: action.language},
|
||||
};
|
||||
case "CHANGE_AUTH_STATE":
|
||||
return {...state, isAuth: action.isAuth};
|
||||
case "CHANGE_LANGUAGE_STATE":
|
||||
return {...state, userChangedLanguage: action.userChangedLanguage};
|
||||
case "CLEAR_TOKEN":
|
||||
localStorage.removeItem("_token");
|
||||
return {...state, token: null};
|
||||
case "SET_TOKEN":
|
||||
localStorage.setItem("_token", action.token);
|
||||
return {...state, token: action.token};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export const UserContext = createContext();
|
||||
|
||||
export const UserProvider = ({children}) => {
|
||||
const [state, dispatch] = useReducer(reducer, initialUser);
|
||||
|
||||
const clearUser = useCallback(() => {
|
||||
dispatch({type: "CLEAR_USER"});
|
||||
}, []);
|
||||
|
||||
const changeUser = useCallback((user) => {
|
||||
dispatch({type: "CHANGE_USER", user});
|
||||
}, []);
|
||||
|
||||
const changeUserLanguage = useCallback(/* for multi language app */);
|
||||
|
||||
const changeAuthState = useCallback((isAuth) => {
|
||||
dispatch({type: "CHANGE_AUTH_STATE", isAuth});
|
||||
}, []);
|
||||
|
||||
const changeLanguageState = useCallback((userChangedLanguage) => {
|
||||
dispatch({type: "CHANGE_LANGUAGE_STATE", userChangedLanguage});
|
||||
}, []);
|
||||
|
||||
const clearToken = useCallback(() => {
|
||||
dispatch({type: "CLEAR_TOKEN"});
|
||||
}, []);
|
||||
|
||||
const setToken = useCallback((token) => {
|
||||
dispatch({type: "SET_TOKEN", token});
|
||||
}, []);
|
||||
|
||||
const getUser = useCallback(
|
||||
(callback = () => {
|
||||
}) => {
|
||||
axios
|
||||
.get(USER_INFO, {
|
||||
headers: {authorization: `Bearer ${state.token}`},
|
||||
})
|
||||
.then(({data}) => {
|
||||
if (typeof callback === "function") callback(data);
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.response) {
|
||||
errorResponse(error.response, clearToken, null, false)
|
||||
} else if (error.request) {
|
||||
errorRequest(null, false)
|
||||
} else {
|
||||
errorSetting(null, false)
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
[state.token]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const localToken = localStorage.getItem("_token");
|
||||
if (localToken) dispatch({type: "SET_TOKEN", token: localToken});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!state.token) {
|
||||
clearUser();
|
||||
changeAuthState(false);
|
||||
changeLanguageState(false);
|
||||
return;
|
||||
}
|
||||
getUser((data) => {
|
||||
changeUser(data);
|
||||
changeAuthState(true);
|
||||
changeLanguageState(true);
|
||||
});
|
||||
}, [state.token]);
|
||||
|
||||
return (
|
||||
<UserContext.Provider
|
||||
value={{
|
||||
isAuth: state.isAuth,
|
||||
userChangedLanguage: state.userChangedLanguage,
|
||||
token: state.token,
|
||||
user: state.user,
|
||||
getUser,
|
||||
clearUser,
|
||||
changeUser,
|
||||
changeUserLanguage,
|
||||
changeAuthState,
|
||||
changeLanguageState,
|
||||
clearToken,
|
||||
setToken,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</UserContext.Provider>
|
||||
);
|
||||
};
|
||||
38
src/lib/app/hooks/useCities.jsx
Normal file
38
src/lib/app/hooks/useCities.jsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import {useRequest} from "@witel/webapp-builder";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {GET_CITIES_LIST} from "@/core/data/apiRoutes";
|
||||
|
||||
const useCities = () => {
|
||||
const t = useTranslations();
|
||||
const [provinceID, setProvinceID] = useState(null)
|
||||
const [cityList, setCityList] = useState([]);
|
||||
const [cityTextField, setCityTextField] = useState(t("text_field_city_id"));
|
||||
const [isLoadingCityList, setIsLoadingCityList] = useState(false)
|
||||
const requestServer = useRequest({auth: true, notification: false})
|
||||
|
||||
useEffect(() => {
|
||||
if (provinceID === null) return
|
||||
setIsLoadingCityList(true)
|
||||
setCityTextField(t("text_field_loading_cities_list"))
|
||||
requestServer(`${GET_CITIES_LIST}?province_id=${provinceID}`, "get", {auth: true, notification: false})
|
||||
.then(({data}) => {
|
||||
const result = data.data;
|
||||
const formattedData = result.map((city, index) => ({
|
||||
id: index,
|
||||
name: city.name,
|
||||
value: city.id,
|
||||
}));
|
||||
setCityList(formattedData);
|
||||
setIsLoadingCityList(false)
|
||||
setCityTextField(t("text_field_city_id"))
|
||||
}).catch(() => {
|
||||
setIsLoadingCityList(false)
|
||||
setCityTextField(t("text_field_error_fetching_cities"))
|
||||
});
|
||||
}, [provinceID])
|
||||
|
||||
|
||||
return {cityTextField, cityList, setProvinceID, isLoadingCityList}
|
||||
}
|
||||
export default useCities
|
||||
@@ -1,10 +0,0 @@
|
||||
import {useContext} from "react";
|
||||
import {LanguageContext} from "../contexts/language";
|
||||
|
||||
const useDirection = () => {
|
||||
const {directionApp} = useContext(LanguageContext);
|
||||
|
||||
return {directionApp};
|
||||
};
|
||||
|
||||
export default useDirection;
|
||||
29
src/lib/app/hooks/useEducations.jsx
Normal file
29
src/lib/app/hooks/useEducations.jsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import {GET_EDUCATIONS_LIST} from "@/core/data/apiRoutes";
|
||||
import {useRequest} from "@witel/webapp-builder";
|
||||
import {useEffect, useState} from "react";
|
||||
|
||||
const useEducations = () => {
|
||||
const [isLoadingEducationsList, setIsLoadingEducationsList] = useState(false)
|
||||
const [errorEducationsList, setErrorEducationsList] = useState(false)
|
||||
const [educationsList, setEducationsList] = useState([])
|
||||
const requestServer = useRequest({auth: true, notification: false})
|
||||
|
||||
useEffect(() => {
|
||||
setIsLoadingEducationsList(true)
|
||||
requestServer(GET_EDUCATIONS_LIST, 'get', {auth: true, notification: false}).then(({data}) => {
|
||||
setIsLoadingEducationsList(false)
|
||||
setEducationsList(data.data);
|
||||
}).catch(() => {
|
||||
setIsLoadingEducationsList(false)
|
||||
setErrorEducationsList(true)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return {
|
||||
educationsList,
|
||||
isLoadingEducationsList,
|
||||
errorEducationsList
|
||||
}
|
||||
};
|
||||
|
||||
export default useEducations;
|
||||
@@ -1,28 +0,0 @@
|
||||
import {useContext} from "react";
|
||||
import {LanguageContext} from "../contexts/language";
|
||||
import useUser from "./useUser";
|
||||
|
||||
const useLanguage = () => {
|
||||
const {isAuth, changeUserLanguage} = useUser();
|
||||
const {
|
||||
languageApp,
|
||||
setLanguageApp,
|
||||
languageIsReady,
|
||||
setLanguageIsReady,
|
||||
languageList,
|
||||
} = useContext(LanguageContext);
|
||||
|
||||
const changeLanguage = (lang) => {
|
||||
if (lang == languageApp) return;
|
||||
|
||||
setLanguageIsReady(false);
|
||||
setLanguageApp(lang);
|
||||
if (isAuth) {
|
||||
changeUserLanguage(lang);
|
||||
}
|
||||
};
|
||||
|
||||
return {languageApp, changeLanguage, languageIsReady, languageList};
|
||||
};
|
||||
|
||||
export default useLanguage;
|
||||
@@ -1,10 +0,0 @@
|
||||
import {useContext} from "react";
|
||||
import {LoadingContext} from "../contexts/loading";
|
||||
|
||||
const useLoading = () => {
|
||||
const {setLoadingPage} = useContext(LoadingContext);
|
||||
|
||||
return {setLoadingPage};
|
||||
};
|
||||
|
||||
export default useLoading;
|
||||
@@ -1,58 +0,0 @@
|
||||
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;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user