diff --git a/.gitignore b/.gitignore index ccfafdc..a59383e 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,6 @@ cypress/screenshots .env .idea package-lock.json -ecosystem.config \ No newline at end of file +ecosystem.config + +public/config.json \ No newline at end of file diff --git a/example.env.local b/example.env.local index 65a9824..8e07b04 100644 --- a/example.env.local +++ b/example.env.local @@ -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" diff --git a/next.config.js b/next.config.js index db2124f..5c809d9 100644 --- a/next.config.js +++ b/next.config.js @@ -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', diff --git a/package.json b/package.json index 5305c99..35ba316 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/public/config.json.example b/public/config.json.example new file mode 100644 index 0000000..bf732fa --- /dev/null +++ b/public/config.json.example @@ -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": "فرآیند معرفی ضامن و پرداخت" + } + } + } +} \ No newline at end of file diff --git a/public/files/راهنما.xlsx b/public/files/راهنما.xlsx new file mode 100644 index 0000000..efbd0bf Binary files /dev/null and b/public/files/راهنما.xlsx differ diff --git a/public/global.scss b/public/global.scss new file mode 100644 index 0000000..a4a3158 --- /dev/null +++ b/public/global.scss @@ -0,0 +1,2 @@ +@import "fontiran"; +@import 'react-toastify/dist/ReactToastify.css'; \ No newline at end of file diff --git a/public/images/bg-firstpage-bus.png b/public/images/bg-firstpage-bus.png new file mode 100644 index 0000000..276d67b Binary files /dev/null and b/public/images/bg-firstpage-bus.png differ diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 2eeb753..c6999fb 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -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": { diff --git a/public/manifest.json b/public/manifest.json index 32bacd5..1fd43e4 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -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", diff --git a/src/components/dashboard/first/index.jsx b/src/components/dashboard/first/index.jsx index 3d1c29e..0e3c800 100644 --- a/src/components/dashboard/first/index.jsx +++ b/src/components/dashboard/first/index.jsx @@ -1,7 +1,5 @@ -import DashboardLayouts from "@/layouts/dashboardLayouts"; - const FirstComponent = () => { - return ; + return <>; }; export default FirstComponent; diff --git a/src/components/dashboard/navgan/add-request-loan/forms/AddForm.jsx b/src/components/dashboard/navgan/add-request-loan/forms/AddForm.jsx index df79a4c..6d9f9bc 100644 --- a/src/components/dashboard/navgan/add-request-loan/forms/AddForm.jsx +++ b/src/components/dashboard/navgan/add-request-loan/forms/AddForm.jsx @@ -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 ( - - {(props) => ( - - - + {finishLoanRequest ? + ( + + + + {t("LoanRequest.finish_loan_request")} + + + + + ) : ( + <> + - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - 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")} - /> - - 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")} - /> - + + + + + + + + + + + { + 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} + /> + + + + + { + 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")} + /> + + + + + + + + { + 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")} + /> + + + 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")} + /> + + + + + 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")} + /> + + + + + + + + { + 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")} + /> + + + { + 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")} + /> + + + + + + + + + + { + formik.setFieldValue("checkedBox", event.target.checked) + }} + /> + } + label={`${t("LoanRequest.checkbox")}`}/> + + + { > - - - )} - + + ) + } + ); }; diff --git a/src/components/dashboard/navgan/add-request-loan/index.jsx b/src/components/dashboard/navgan/add-request-loan/index.jsx index cd9d359..395ede7 100644 --- a/src/components/dashboard/navgan/add-request-loan/index.jsx +++ b/src/components/dashboard/navgan/add-request-loan/index.jsx @@ -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 ( - - - + <> + - - + ); }; diff --git a/src/components/dashboard/navgan/followUp-loan/RequestCard.jsx b/src/components/dashboard/navgan/followUp-loan/RequestCard.jsx index 6e5dfd3..54695db 100644 --- a/src/components/dashboard/navgan/followUp-loan/RequestCard.jsx +++ b/src/components/dashboard/navgan/followUp-loan/RequestCard.jsx @@ -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 ( - + - } - title={`${t("LoanFollowUp.request_number")}: (${item.id})`} - subheader={item.latest_history_created_at} - /> - - - {item.loan_state} + + + + {`${t("LoanFollowUp.loan_unique_code")}: ${item.id}`} + + + + {`${t("LoanFollowUp.loan_date")}: ${moment(item.created_at).locale("fa").format("HH:mm | YYYY/MM/DD")}`} + + {`${t("LoanFollowUp.loan_bank_branch")}: ${item.branch_info === null ? '-' : item.branch_info}`} + + + {`${t("LoanFollowUp.loan_status")}: `} + {item.loan_state} + {item.state_id >= 1 && item.state_id <= 6 && } + {item.state_id === 8 && } + {item.state_id === 7 && } + + diff --git a/src/components/dashboard/navgan/followUp-loan/index.jsx b/src/components/dashboard/navgan/followUp-loan/index.jsx index de3176c..aa031a6 100644 --- a/src/components/dashboard/navgan/followUp-loan/index.jsx +++ b/src/components/dashboard/navgan/followUp-loan/index.jsx @@ -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 ( - - + - - {requestsList.map((item, index) => ( - - ))} - - - + {requestsList.map((item) => ( + + ))} + + + + ); }; diff --git a/src/components/dashboard/refahi/add-request-loan/accessibility/index.jsx b/src/components/dashboard/refahi/add-request-loan/accessibility/index.jsx deleted file mode 100644 index 3618d0b..0000000 --- a/src/components/dashboard/refahi/add-request-loan/accessibility/index.jsx +++ /dev/null @@ -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 ( - - - {t("LoanRequest.add_loan_request_permission")} - - - - ); -}; - -export default AccessibilityComponent; diff --git a/src/components/dashboard/refahi/add-request-loan/forms/AddForm.jsx b/src/components/dashboard/refahi/add-request-loan/forms/AddForm.jsx deleted file mode 100644 index 4051854..0000000 --- a/src/components/dashboard/refahi/add-request-loan/forms/AddForm.jsx +++ /dev/null @@ -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 ( - - {(props) => ( - - - - - - - - - - - - - - - - - {t("LoanRequest.text_field_province_id")} - - - {props.touched.province_id && props.errors.province_id ? props.errors.province_id : ""} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - )} - - ); -}; - -export default AddFormComponent; \ No newline at end of file diff --git a/src/components/dashboard/refahi/add-request-loan/index.jsx b/src/components/dashboard/refahi/add-request-loan/index.jsx deleted file mode 100644 index bc82ac7..0000000 --- a/src/components/dashboard/refahi/add-request-loan/index.jsx +++ /dev/null @@ -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 ( - - {user.can_request_a_new_loan ? : } - - ); -}; - -export default LoanRequestComponent; diff --git a/src/components/dashboard/refahi/edit-request-loan/forms/EditForm.jsx b/src/components/dashboard/refahi/edit-request-loan/forms/EditForm.jsx deleted file mode 100644 index 36f5aa0..0000000 --- a/src/components/dashboard/refahi/edit-request-loan/forms/EditForm.jsx +++ /dev/null @@ -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 ( - - {(props) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - )} - - ); -}; - -export default EditFormComponent; \ No newline at end of file diff --git a/src/components/dashboard/refahi/edit-request-loan/index.jsx b/src/components/dashboard/refahi/edit-request-loan/index.jsx deleted file mode 100644 index 89de937..0000000 --- a/src/components/dashboard/refahi/edit-request-loan/index.jsx +++ /dev/null @@ -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 && ( - - - - )} - - ); -}; - -export default LoanRequestComponent; \ No newline at end of file diff --git a/src/components/dashboard/refahi/followUp-loan/RequestCard.jsx b/src/components/dashboard/refahi/followUp-loan/RequestCard.jsx deleted file mode 100644 index 799d296..0000000 --- a/src/components/dashboard/refahi/followUp-loan/RequestCard.jsx +++ /dev/null @@ -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 ( - - - } - 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 - - - - - - ) : null - } - /> - - - {item.loan_state} - - - - - ); -}; - -export default RequestCard; \ No newline at end of file diff --git a/src/components/dashboard/refahi/followUp-loan/index.jsx b/src/components/dashboard/refahi/followUp-loan/index.jsx deleted file mode 100644 index 32b121d..0000000 --- a/src/components/dashboard/refahi/followUp-loan/index.jsx +++ /dev/null @@ -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 ( - - {requestsList == null ? '' : requestsList.length ? ( - {requestsList.map((item, index) => ())} - ) : ({t('LoanFollowUp.no_request_found')})} - - ); -}; - -export default LoanFollowUpComponent; diff --git a/src/components/errors/403.jsx b/src/components/errors/403.jsx index ce91443..8d410ed 100644 --- a/src/components/errors/403.jsx +++ b/src/components/errors/403.jsx @@ -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(); diff --git a/src/components/errors/404.jsx b/src/components/errors/404.jsx index acfd418..15a394c 100644 --- a/src/components/errors/404.jsx +++ b/src/components/errors/404.jsx @@ -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(); diff --git a/src/components/errors/500.jsx b/src/components/errors/500.jsx index 5a19eda..5527a39 100644 --- a/src/components/errors/500.jsx +++ b/src/components/errors/500.jsx @@ -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(); diff --git a/src/components/first/FooterDetails.jsx b/src/components/first/FooterDetails.jsx index bb8fe01..7c0eb2c 100644 --- a/src/components/first/FooterDetails.jsx +++ b/src/components/first/FooterDetails.jsx @@ -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( - - - + return ( + + + - Your Alt Text + Your Alt Text { - return( + return ( - + - - - - - - - + diff --git a/src/components/register/RequestOtp.jsx b/src/components/register/RequestOtp.jsx deleted file mode 100644 index a24aa4f..0000000 --- a/src/components/register/RequestOtp.jsx +++ /dev/null @@ -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 ( - - - - - - {(props) => ( - - - - - - {t("Titles.title_register_page")} - - - - - - - - - )} - - - - - - - {t("RegisterPage.link_routing_back_to")}{" "} - {backUrlDecodedPath - ? t("RegisterPage.link_routing_previuos_page") - : t("RegisterPage.link_routing_register")} - - - - ); -}; - -export default RequestOtpComponent; diff --git a/src/components/register/index.jsx b/src/components/register/index.jsx deleted file mode 100644 index eb11ad0..0000000 --- a/src/components/register/index.jsx +++ /dev/null @@ -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 ( - - - - {isAuth ? ( - - ) : ( - - - - - - {/**/} - {/* */} - {/* {t("register_welfare_services")}*/} - {/* */} - {/**/} - - - )} - - - - {t("RegisterPage.link_routing_back_to")}{" "} - {backUrlDecodedPath - ? t("RegisterPage.link_routing_previuos_page") - : t("LoginPage.link_routing_main_page")} - - - - ); -}; - -export default RegisterComponent; diff --git a/src/components/register/navy/UserRegister.jsx b/src/components/register/navy/UserRegister.jsx deleted file mode 100644 index 9714636..0000000 --- a/src/components/register/navy/UserRegister.jsx +++ /dev/null @@ -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 ( - - - - - - {(props) => ( - - - - - - {t("register_navy")} - - - - - - {t("LoginPage.sent_token_to")}: {PhoneNumber} - - - - e.target.value.length <= 6 ? props.setFieldValue("verification_code", e.target.value) : ""} - /> - - - - - - - - - - - )} - - - - - - ); -}; - -export default UserRegisterComponent; diff --git a/src/components/register/navy/index.jsx b/src/components/register/navy/index.jsx deleted file mode 100644 index 9296f78..0000000 --- a/src/components/register/navy/index.jsx +++ /dev/null @@ -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 ( - - ); - } else { - return ( - - ); - } -}; - -export default NavyComponent; diff --git a/src/components/register/welfare-services/UserRegister.jsx b/src/components/register/welfare-services/UserRegister.jsx deleted file mode 100644 index a043a53..0000000 --- a/src/components/register/welfare-services/UserRegister.jsx +++ /dev/null @@ -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 ( - - - - - - {(props) => ( - - - - - - {t("register_welfare_services")} - - - - - - {t("LoginPage.sent_token_to")}: {PhoneNumber} - - - - - - - - - - - - - - )} - - - - - - ); -}; - -export default UserRegisterComponent; diff --git a/src/components/register/welfare-services/index.jsx b/src/components/register/welfare-services/index.jsx deleted file mode 100644 index 322490f..0000000 --- a/src/components/register/welfare-services/index.jsx +++ /dev/null @@ -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 ( - - ); - } else { - return ( - - ); - } -}; - -export default WelfareServicesComponent; diff --git a/src/core/components/GlobalHead.jsx b/src/core/components/GlobalHead.jsx index 9036b85..002199d 100644 --- a/src/core/components/GlobalHead.jsx +++ b/src/core/components/GlobalHead.jsx @@ -39,14 +39,6 @@ const GlobalHead = () => { /> - diff --git a/src/core/components/LinkRouting.jsx b/src/core/components/LinkRouting.jsx deleted file mode 100644 index f8fac0a..0000000 --- a/src/core/components/LinkRouting.jsx +++ /dev/null @@ -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 ( - - - - ); -}); - -// 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 ; - } - - return ; - } - - const linkAs = linkAsProp || as; - const nextjsProps = { - to: href, - linkAs, - replace, - scroll, - shallow, - prefetch, - legacyBehavior, - locale, - }; - - if (noLinkStyle) { - return ( - - ); - } - - return ( - - ); -}); - -export default LinkRouting; diff --git a/src/core/components/LoadingHardPage.jsx b/src/core/components/LoadingHardPage.jsx deleted file mode 100644 index 3f558cd..0000000 --- a/src/core/components/LoadingHardPage.jsx +++ /dev/null @@ -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 ( - <> - theme.zIndex.drawer + 1}} - open={loading} - > - - - - - - - {children} - - ); -}; - -export default LoadingHardPage; diff --git a/src/core/components/Messages.jsx b/src/core/components/Messages.jsx deleted file mode 100644 index 8a5cfc9..0000000 --- a/src/core/components/Messages.jsx +++ /dev/null @@ -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 ( - - - - {text} - {actions} - - - ); -}; - -export default Message; diff --git a/src/core/components/MuiDatePicker.jsx b/src/core/components/MuiDatePicker.jsx new file mode 100644 index 0000000..accc7af --- /dev/null +++ b/src/core/components/MuiDatePicker.jsx @@ -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 ( + + ); +} + +function ButtonDatePicker(props) { + const t = useTranslations(); + const [open, setOpen] = useState(false); + + return ( + setOpen(false)} + onOpen={() => setOpen(true)} + /> + ); +} + +export default function PickerWithButtonField({formik, disabled}) { + return ( + + + { + formik.setFieldValue("birthday", moment(newValue)) + }} + + /> + + {formik.touched.birthday && formik.errors.birthday} + + ); +} \ No newline at end of file diff --git a/src/core/components/NetworkComponent.jsx b/src/core/components/NetworkComponent.jsx deleted file mode 100644 index 8ebbb68..0000000 --- a/src/core/components/NetworkComponent.jsx +++ /dev/null @@ -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: - }); - return - } - toast.dismiss() - toastId.current = toast.warn(t('offline_message'), { - autoClose: false, closeButton: false, closeOnClick: false, icon: - }) - }, [network.online]); - - return '' -} - -export default NetworkComponent \ No newline at end of file diff --git a/src/core/components/NoSsrHandler.jsx b/src/core/components/NoSsrHandler.jsx deleted file mode 100644 index 5a4c4e1..0000000 --- a/src/core/components/NoSsrHandler.jsx +++ /dev/null @@ -1,8 +0,0 @@ -import {NoSsr} from "@mui/material"; - -const NoSsrHandler = ({isBot, children}) => { - if (isBot) return children; - return {children}; -}; - -export default NoSsrHandler; diff --git a/src/core/components/PlateNumber.jsx b/src/core/components/PlateNumber.jsx new file mode 100644 index 0000000..5d28fcb --- /dev/null +++ b/src/core/components/PlateNumber.jsx @@ -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: + }, +] +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 ( + <> + + 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)} + /> + 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)} + /> + + + + setPlateDrawer(false)} + > + + {plate_words.map((item) => ( + + ))} + + + event.target.value.length <= 2 ? formik.setFieldValue("plate_part1", event.target.value) : null} + onBlur={formik.handleBlur} + error={true} + /> + + + + + + + {(isTouched && isErrorPlate) ? `${t("LoanRequest.error_message_plate_number")}` : null} + + + ) +} +export default PlateNumber \ No newline at end of file diff --git a/src/core/components/ResendToken.jsx b/src/core/components/ResendToken.jsx index 906581c..2216c99 100644 --- a/src/core/components/ResendToken.jsx +++ b/src/core/components/ResendToken.jsx @@ -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(); diff --git a/src/core/components/SelectBox.jsx b/src/core/components/SelectBox.jsx index a24484c..0ee7a47 100644 --- a/src/core/components/SelectBox.jsx +++ b/src/core/components/SelectBox.jsx @@ -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 ( - {label} + {label} {helperText} diff --git a/src/core/components/notifications/ErrorNotification.jsx b/src/core/components/notifications/ErrorNotification.jsx deleted file mode 100644 index 05e2fb9..0000000 --- a/src/core/components/notifications/ErrorNotification.jsx +++ /dev/null @@ -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( - () => ( - <> - - - - - - {t("notifications.error")} ({t("notifications.code")}: {status}) - - - {message || t("notifications.error_static_text")} - - - - - - ), - { - autoClose: false, - closeOnClick: false, - draggable: false, - } - ); -}; - -export default ErrorNotification; \ No newline at end of file diff --git a/src/core/components/notifications/PendingNotification.jsx b/src/core/components/notifications/PendingNotification.jsx deleted file mode 100644 index 6183f6b..0000000 --- a/src/core/components/notifications/PendingNotification.jsx +++ /dev/null @@ -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; \ No newline at end of file diff --git a/src/core/components/notifications/SuccessNotification.jsx b/src/core/components/notifications/SuccessNotification.jsx deleted file mode 100644 index 3507cef..0000000 --- a/src/core/components/notifications/SuccessNotification.jsx +++ /dev/null @@ -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( - () => ( - <> - - - - - - {t("notifications.success")} ({t("notifications.code")}:{" "} - {status}) - - - {t("notifications.success_static_text")} - - - - - - ), - { - autoClose: 3000, - hideProgressBar: true, - pauseOnHover: true, - closeOnClick: false, - draggable: true, - } - ); -}; - -export default SuccessNotification; \ No newline at end of file diff --git a/src/core/components/notifications/WarningNotification.jsx b/src/core/components/notifications/WarningNotification.jsx deleted file mode 100644 index 19d6a2f..0000000 --- a/src/core/components/notifications/WarningNotification.jsx +++ /dev/null @@ -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( - () => ( - <> - - - - - - {t("notifications.warning")} ({t("notifications.code")}:{" "} - {status}) - - - {t("notifications.warning_static_text")} - - - - - - ), - { - autoClose: false, - closeOnClick: false, - draggable: false, - } - ); -}; - -export default WarningNotification; \ No newline at end of file diff --git a/src/core/components/notifications/index.jsx b/src/core/components/notifications/index.jsx deleted file mode 100644 index 9425aef..0000000 --- a/src/core/components/notifications/index.jsx +++ /dev/null @@ -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 -*/ diff --git a/src/core/components/svgs/SvgDone.jsx b/src/core/components/svgs/SvgDone.jsx new file mode 100644 index 0000000..9042c27 --- /dev/null +++ b/src/core/components/svgs/SvgDone.jsx @@ -0,0 +1,96 @@ +import {useTheme} from "@mui/material"; + +const SvgDone = ({width, height}) => { + const theme = useTheme() + const fillColor = theme.palette.primary.main + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export default SvgDone \ No newline at end of file diff --git a/src/core/components/svgs/SvgMaintenance.jsx b/src/core/components/svgs/SvgMaintenance.jsx new file mode 100644 index 0000000..47fcc0f --- /dev/null +++ b/src/core/components/svgs/SvgMaintenance.jsx @@ -0,0 +1,91 @@ +import {useTheme} from "@mui/material"; + +const SvgMaintenance = ({width, height}) => { + const theme = useTheme() + const fillColor = theme.palette.primary.main + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) + +} + +export default SvgMaintenance \ No newline at end of file diff --git a/src/core/components/timelines/DoneTimeLine.jsx b/src/core/components/timelines/DoneTimeLine.jsx new file mode 100644 index 0000000..c2e2b3e --- /dev/null +++ b/src/core/components/timelines/DoneTimeLine.jsx @@ -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 ( + + {date} + + + + + {position !== 'end' && } + + + {primaryLabel} + {secondaryLabel} + + + ) +} + +export default DoneTimeLine \ No newline at end of file diff --git a/src/core/components/timelines/InProgressTimeLine.jsx b/src/core/components/timelines/InProgressTimeLine.jsx new file mode 100644 index 0000000..2b210d9 --- /dev/null +++ b/src/core/components/timelines/InProgressTimeLine.jsx @@ -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 ( + + {date} + + + + + {position !== 'end' && } + + + {primaryLabel} + {secondaryLabel} + + + ) +} + +export default InProgressTimeLine \ No newline at end of file diff --git a/src/core/components/timelines/OpenTimeLine.jsx b/src/core/components/timelines/OpenTimeLine.jsx new file mode 100644 index 0000000..b203ea2 --- /dev/null +++ b/src/core/components/timelines/OpenTimeLine.jsx @@ -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 ( + + {date} + + + + + {position !== 'end' && } + + + {primaryLabel} + {secondaryLabel} + + + ) +} + +export default OpenTimeLine \ No newline at end of file diff --git a/src/core/components/timelines/timelineManager.jsx b/src/core/components/timelines/timelineManager.jsx new file mode 100644 index 0000000..292c3d1 --- /dev/null +++ b/src/core/components/timelines/timelineManager.jsx @@ -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 + case 'in progress': + return + case 'done': + return + } +} + +export default TimelineManager \ No newline at end of file diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index 64cbc59..49d5c4a 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -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"; diff --git a/src/core/data/headerProfileItems.jsx b/src/core/data/headerProfileItems.js similarity index 100% rename from src/core/data/headerProfileItems.jsx rename to src/core/data/headerProfileItems.js diff --git a/src/core/data/languageList.js b/src/core/data/languageList.js new file mode 100644 index 0000000..101debc --- /dev/null +++ b/src/core/data/languageList.js @@ -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; \ No newline at end of file diff --git a/src/core/data/sidebarMenu.js b/src/core/data/sidebarMenu.js new file mode 100644 index 0000000..ef2c7d8 --- /dev/null +++ b/src/core/data/sidebarMenu.js @@ -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: , + selected: false, + permission: "all" + }, + { + key: "sidebar.add-request-loan", + name: "sidebar.add-request-loan", + type: "page", + route: "/dashboard/navgan/add-request-loan", + icon: , + selected: false, + permission: "can_request_navgan_loan" + }, + { + key: "sidebar.followUp-loan", + name: "sidebar.followUp-loan", + type: "page", + route: "/dashboard/navgan/followUp-loan", + icon: , + selected: false, + permission: "all" + }, + ], +]; + +export default sidebarMenu; diff --git a/src/core/data/sidebarMenu.jsx b/src/core/data/sidebarMenu.jsx deleted file mode 100644 index a78ed6c..0000000 --- a/src/core/data/sidebarMenu.jsx +++ /dev/null @@ -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: , - userType: 0, - selected: false, - permission_name: "all" - }, - { - key: "sidebar.add-request-loan", - type: "page", - route: "/dashboard/navgan/add-request-loan", - icon: , - userType: 1, - selected: false, - permission_name: "can_request_a_new_loan" - }, - { - key: "sidebar.followUp-loan", - type: "page", - route: "/dashboard/navgan/followUp-loan", - icon: , - userType: 1, - selected: false, - permission_name: "all" - }, - { - key: "sidebar.add-request-loan", - type: "page", - route: "/dashboard/refahi/add-request-loan", - icon: , - userType: 2, - selected: false, - permission_name: "can_request_a_new_loan" - }, - { - key: "sidebar.followUp-loan", - type: "page", - route: "/dashboard/refahi/followUp-loan", - icon: , - userType: 2, - selected: false, - permission_name: "all" - }, - ], -]; - -export default sidebarMenu; diff --git a/src/core/utils/createEmotionCache.jsx b/src/core/utils/createEmotionCache.jsx deleted file mode 100644 index 413fafe..0000000 --- a/src/core/utils/createEmotionCache.jsx +++ /dev/null @@ -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, - }); -}; diff --git a/src/core/utils/errorHandler.js b/src/core/utils/errorHandler.js deleted file mode 100644 index 8dbd364..0000000 --- a/src/core/utils/errorHandler.js +++ /dev/null @@ -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]); - }) - } -} \ No newline at end of file diff --git a/src/core/utils/globalServerProps.js b/src/core/utils/globalServerProps.js new file mode 100644 index 0000000..ef8e1b8 --- /dev/null +++ b/src/core/utils/globalServerProps.js @@ -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, + } +} \ No newline at end of file diff --git a/src/core/utils/succesHandler.js b/src/core/utils/succesHandler.js deleted file mode 100644 index a61ac85..0000000 --- a/src/core/utils/succesHandler.js +++ /dev/null @@ -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) - } -} \ No newline at end of file diff --git a/src/layouts/AppLayout.jsx b/src/layouts/AppLayout.jsx deleted file mode 100644 index 2b4593b..0000000 --- a/src/layouts/AppLayout.jsx +++ /dev/null @@ -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 (<> - - - - - {children} - ); -} - -export default AppLayout; \ No newline at end of file diff --git a/src/layouts/CenterLayout.jsx b/src/layouts/CenterLayout.jsx deleted file mode 100644 index 1e1b8bf..0000000 --- a/src/layouts/CenterLayout.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import {Fade, Stack} from "@mui/material"; - -const CenterLayout = (props) => { - return ( - - - {props.children} - - - ); -}; - -export default CenterLayout; diff --git a/src/layouts/FullPageLayout.jsx b/src/layouts/FullPageLayout.jsx deleted file mode 100644 index d6ed61e..0000000 --- a/src/layouts/FullPageLayout.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import {Stack} from "@mui/material"; - -const FullPageLayout = (props) => { - return ( - - {props.children} - - ); -}; - -export default FullPageLayout; diff --git a/src/layouts/MuiLayout.jsx b/src/layouts/MuiLayout.jsx deleted file mode 100644 index 1c9e9b9..0000000 --- a/src/layouts/MuiLayout.jsx +++ /dev/null @@ -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 ( - - - - - - - - - - {children} - - - - ); -}; - -export default MuiLayout; diff --git a/src/layouts/ScrollableLayout.jsx b/src/layouts/ScrollableLayout.jsx deleted file mode 100644 index 583edd7..0000000 --- a/src/layouts/ScrollableLayout.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import {Box, Fade} from "@mui/material"; - -const ScrollableLayout = (props) => { - const overflowY = props?.y || "hidden"; - const overflowX = props?.x || "hidden"; - - return ( - - - {props.children} - - - ); -}; - -export default ScrollableLayout; diff --git a/src/layouts/dashboard.jsx b/src/layouts/dashboard.jsx new file mode 100644 index 0000000..a814c9a --- /dev/null +++ b/src/layouts/dashboard.jsx @@ -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 ( + <> + + + ) +} + +export default DashboardLayout \ No newline at end of file diff --git a/src/layouts/dashboardLayouts/breadcrumbs/BreadcrumbItem.jsx b/src/layouts/dashboardLayouts/breadcrumbs/BreadcrumbItem.jsx deleted file mode 100644 index c233be3..0000000 --- a/src/layouts/dashboardLayouts/breadcrumbs/BreadcrumbItem.jsx +++ /dev/null @@ -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 ? ( - - {t("sidebar." + props.label)} - - ) : ( - - {t("sidebar." + props.label)} - - ); -} diff --git a/src/layouts/dashboardLayouts/breadcrumbs/index.jsx b/src/layouts/dashboardLayouts/breadcrumbs/index.jsx deleted file mode 100644 index 310323e..0000000 --- a/src/layouts/dashboardLayouts/breadcrumbs/index.jsx +++ /dev/null @@ -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 ( - - - ) : ( - - ) - } - aria-label="breadcrumb" - > - {RouterArray.map((segment, index) => ( - - ))} - - - ); -}; - -export default BreadCrumbs; diff --git a/src/layouts/dashboardLayouts/header/ProfileData.jsx b/src/layouts/dashboardLayouts/header/ProfileData.jsx deleted file mode 100644 index 13ceda1..0000000 --- a/src/layouts/dashboardLayouts/header/ProfileData.jsx +++ /dev/null @@ -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 ( - - - - ); -} diff --git a/src/layouts/dashboardLayouts/header/ProfileMenu.jsx b/src/layouts/dashboardLayouts/header/ProfileMenu.jsx deleted file mode 100644 index e628e52..0000000 --- a/src/layouts/dashboardLayouts/header/ProfileMenu.jsx +++ /dev/null @@ -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 ( - <> - - - - - - - - - - - ); -} - -export default ProfileMenu; diff --git a/src/layouts/dashboardLayouts/header/ProfileOptionLogOut.jsx b/src/layouts/dashboardLayouts/header/ProfileOptionLogOut.jsx deleted file mode 100644 index 2a6cf85..0000000 --- a/src/layouts/dashboardLayouts/header/ProfileOptionLogOut.jsx +++ /dev/null @@ -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 ( - <> - - - - - - - {t("header.logout")} - - - - - ); -} diff --git a/src/layouts/dashboardLayouts/header/ProfileOptions.jsx b/src/layouts/dashboardLayouts/header/ProfileOptions.jsx deleted file mode 100644 index 6e7bdba..0000000 --- a/src/layouts/dashboardLayouts/header/ProfileOptions.jsx +++ /dev/null @@ -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) => ( - - - - {profile_item.icon} - - - {t(profile_item.name)} - - - - ))} - - - ); -} diff --git a/src/layouts/dashboardLayouts/header/index.jsx b/src/layouts/dashboardLayouts/header/index.jsx deleted file mode 100644 index 8760960..0000000 --- a/src/layouts/dashboardLayouts/header/index.jsx +++ /dev/null @@ -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 ( - <> - - - - - - - - - - - - - - - - - - - - - ); -} - -export default Header; diff --git a/src/layouts/dashboardLayouts/index.jsx b/src/layouts/dashboardLayouts/index.jsx deleted file mode 100644 index c32c09b..0000000 --- a/src/layouts/dashboardLayouts/index.jsx +++ /dev/null @@ -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 ( - -
- - - - - - {props.children} - - - - ); -}; - -export default DashboardLayouts; diff --git a/src/layouts/dashboardLayouts/sidebar/SidebarDrawer.jsx b/src/layouts/dashboardLayouts/sidebar/SidebarDrawer.jsx deleted file mode 100644 index 5eff37a..0000000 --- a/src/layouts/dashboardLayouts/sidebar/SidebarDrawer.jsx +++ /dev/null @@ -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 ( - <> - - - - {t("app_short_name")} - - {user.type_name} - - - - - - ); -}; - -export default SidebarDrawer; diff --git a/src/layouts/dashboardLayouts/sidebar/SidebarList.jsx b/src/layouts/dashboardLayouts/sidebar/SidebarList.jsx deleted file mode 100644 index 6cd6847..0000000 --- a/src/layouts/dashboardLayouts/sidebar/SidebarList.jsx +++ /dev/null @@ -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 ( - - {itemMenu.map((itemArr, index) => ( - - {itemArr.map((item) => { - if ( - (item.userType === user.type_id || item.userType === 0) && - (user[item.permission_name] || item.permission_name === "all") - ) { - return ( - - ); - } else { - return null; - } - })} - - - ) - )} - - ) - ; -} diff --git a/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx b/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx deleted file mode 100644 index f663413..0000000 --- a/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx +++ /dev/null @@ -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 ( - - - { - if (item.type == "menu") { - dispatch({type: "COLLAPSE_MENU", key: item.key}); - } - handleDrawerToggle(); - }} - sx={{ - minHeight: 48, - }} - > - - {item.icon} - - - - {item.type == "menu" && - (item.showSubItem ? : )} - - - {item.subItem && ( - - )} - - ); -}; - -export default SidebarListItem; diff --git a/src/layouts/dashboardLayouts/sidebar/SidebarListSubItem.jsx b/src/layouts/dashboardLayouts/sidebar/SidebarListSubItem.jsx deleted file mode 100644 index 3407081..0000000 --- a/src/layouts/dashboardLayouts/sidebar/SidebarListSubItem.jsx +++ /dev/null @@ -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 ( - - - {item.subItem.map((subitem, index) => ( - - { - if (item.type == "menu") { - dispatch({type: "COLLAPSE_MENU", key: item.key}); - } - handleDrawerToggle(); - }} - > - - - - - - - ))} - - - ); -}; - -export default SidebarListSubItem; diff --git a/src/layouts/dashboardLayouts/sidebar/index.jsx b/src/layouts/dashboardLayouts/sidebar/index.jsx deleted file mode 100644 index 2498dfd..0000000 --- a/src/layouts/dashboardLayouts/sidebar/index.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import {Box, Drawer} from "@mui/material"; -import SidebarDrawer from "./SidebarDrawer"; - -const Sidebar = (props) => { - return ( - - - - - - - - - ); -}; - -export default Sidebar; diff --git a/src/layouts/index.jsx b/src/layouts/index.jsx new file mode 100644 index 0000000..96f3f26 --- /dev/null +++ b/src/layouts/index.jsx @@ -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 ( + + {children} + + ) +} + +export default Layout \ No newline at end of file diff --git a/src/layouts/list.jsx b/src/layouts/list.jsx new file mode 100644 index 0000000..2cf15f0 --- /dev/null +++ b/src/layouts/list.jsx @@ -0,0 +1,3 @@ +import DashboardLayout from './dashboard' + +export {DashboardLayout} \ No newline at end of file diff --git a/src/lib/app/contexts/language.jsx b/src/lib/app/contexts/language.jsx deleted file mode 100644 index e3f41f4..0000000 --- a/src/lib/app/contexts/language.jsx +++ /dev/null @@ -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 ( - - {children} - - ); -}; diff --git a/src/lib/app/contexts/loading.jsx b/src/lib/app/contexts/loading.jsx deleted file mode 100644 index f5b8a47..0000000 --- a/src/lib/app/contexts/loading.jsx +++ /dev/null @@ -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 ( - - - {children} - - ); -}; diff --git a/src/lib/app/contexts/user.jsx b/src/lib/app/contexts/user.jsx deleted file mode 100644 index 827a8af..0000000 --- a/src/lib/app/contexts/user.jsx +++ /dev/null @@ -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 ( - - {children} - - ); -}; diff --git a/src/lib/app/hooks/useCities.jsx b/src/lib/app/hooks/useCities.jsx new file mode 100644 index 0000000..bc01e0f --- /dev/null +++ b/src/lib/app/hooks/useCities.jsx @@ -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 \ No newline at end of file diff --git a/src/lib/app/hooks/useDirection.jsx b/src/lib/app/hooks/useDirection.jsx deleted file mode 100644 index b2e01fe..0000000 --- a/src/lib/app/hooks/useDirection.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import {useContext} from "react"; -import {LanguageContext} from "../contexts/language"; - -const useDirection = () => { - const {directionApp} = useContext(LanguageContext); - - return {directionApp}; -}; - -export default useDirection; diff --git a/src/lib/app/hooks/useEducations.jsx b/src/lib/app/hooks/useEducations.jsx new file mode 100644 index 0000000..16bcfe4 --- /dev/null +++ b/src/lib/app/hooks/useEducations.jsx @@ -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; \ No newline at end of file diff --git a/src/lib/app/hooks/useLanguage.jsx b/src/lib/app/hooks/useLanguage.jsx deleted file mode 100644 index d663835..0000000 --- a/src/lib/app/hooks/useLanguage.jsx +++ /dev/null @@ -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; diff --git a/src/lib/app/hooks/useLoading.jsx b/src/lib/app/hooks/useLoading.jsx deleted file mode 100644 index a691bd7..0000000 --- a/src/lib/app/hooks/useLoading.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import {useContext} from "react"; -import {LoadingContext} from "../contexts/loading"; - -const useLoading = () => { - const {setLoadingPage} = useContext(LoadingContext); - - return {setLoadingPage}; -}; - -export default useLoading; diff --git a/src/lib/app/hooks/useNetwork.jsx b/src/lib/app/hooks/useNetwork.jsx deleted file mode 100644 index 4fff7fe..0000000 --- a/src/lib/app/hooks/useNetwork.jsx +++ /dev/null @@ -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; \ No newline at end of file diff --git a/src/lib/app/hooks/useOccupations.jsx b/src/lib/app/hooks/useOccupations.jsx new file mode 100644 index 0000000..4a2080a --- /dev/null +++ b/src/lib/app/hooks/useOccupations.jsx @@ -0,0 +1,29 @@ +import {GET_OCCUPATIONS_LIST} from "@/core/data/apiRoutes"; +import {useRequest} from "@witel/webapp-builder"; +import {useEffect, useState} from "react"; + +const useOccupations = () => { + const [isLoadingOccupationsList, setIsLoadingOccupationsList] = useState(false) + const [errorOccupationsList, setErrorOccupationsList] = useState(false) + const [occupationsList, setOccupationsList] = useState([]) + const requestServer = useRequest({auth: true, notification: false}) + + useEffect(() => { + setIsLoadingOccupationsList(true) + requestServer(GET_OCCUPATIONS_LIST, 'get', {auth: true, notification: false}).then(({data}) => { + setIsLoadingOccupationsList(false) + setOccupationsList(data.data); + }).catch(() => { + setIsLoadingOccupationsList(false) + setErrorOccupationsList(true) + }) + }, []) + + return { + occupationsList, + isLoadingOccupationsList, + errorOccupationsList + } +}; + +export default useOccupations; \ No newline at end of file diff --git a/src/lib/app/hooks/useProvince.jsx b/src/lib/app/hooks/useProvince.jsx index d0fbda0..add55f3 100644 --- a/src/lib/app/hooks/useProvince.jsx +++ b/src/lib/app/hooks/useProvince.jsx @@ -1,28 +1,33 @@ import {GET_PROVINCE_LIST} from "@/core/data/apiRoutes"; -import useRequest from "@/lib/app/hooks/useRequest"; -import useSWR from "swr"; +import {useRequest} from "@witel/webapp-builder"; +import {useEffect, useState} from "react"; const useProvince = () => { + const [isLoadingProvinceList, setIsLoadingProvinceList] = useState(false) + const [errorProvinceList, setErrorProvinceList] = useState(false) + const [provinceList, setProvinceList] = useState([]) const requestServer = useRequest({auth: true, notification: false}) - //swr config - const fetcher = (...args) => { - return requestServer(args, 'get').then(({data}) => { - return data; + useEffect(()=> { + setIsLoadingProvinceList(true) + requestServer(GET_PROVINCE_LIST, 'get',{auth : true, notification : false}).then(({data}) => { + const formattedData = data.map((province, index) => ({ + id: index, + name: province.name, + value: province.id, + })); + setIsLoadingProvinceList(false) + setProvinceList(formattedData); }).catch(() => { + setIsLoadingProvinceList(false) + setErrorProvinceList(true) }) - }; - - const {data, isLoading} = useSWR(GET_PROVINCE_LIST, fetcher, { - revalidateIfStale: false, - revalidateOnFocus: false, - revalidateOnReconnect: false - }); + },[]) return { - provinceList: data, - isLoadingProvinceList: isLoading, - errorProvinceList: !data + provinceList, + isLoadingProvinceList, + errorProvinceList } }; diff --git a/src/lib/app/hooks/useRequest.js b/src/lib/app/hooks/useRequest.js deleted file mode 100644 index d361e08..0000000 --- a/src/lib/app/hooks/useRequest.js +++ /dev/null @@ -1,66 +0,0 @@ -import axios from "axios"; -import {successRequest} from "@/core/utils/succesHandler"; -import PendingNotification from "@/core/components/notifications/PendingNotification"; -import {useTranslations} from "next-intl"; -import useUser from "@/lib/app/hooks/useUser"; -import {errorRequest, errorResponse, errorSetting} from "@/core/utils/errorHandler"; -import useNetwork from "@/lib/app/hooks/useNetwork"; - -const defaultOptions = { - auth: false, data: {}, requestOptions: { - headers: {} - }, notification: true, pending: true, success: { - notification: { - show: true, - }, - }, failed: { - notification: { - show: true, - }, - }, -} -const useRequest = (initOptions) => { - const network = useNetwork() - const t = useTranslations() - const {token, clearToken} = useUser() - let _options = {...defaultOptions, ...initOptions} - - function requestServer(url = '', method = 'get', options) { - _options = {..._options, ...options} - if (_options.auth) _options = { - ..._options, requestOptions: { - ..._options.requestOptions, - headers: {..._options.requestOptions.headers, authorization: `Bearer ${token}`} - } - } - - return new Promise((resolve, reject) => { - if (!network.online) { - reject() - return - } - if (_options.notification && _options.failed.notification.show && _options.pending) PendingNotification(t) - axios({ - url: url, method: method, data: _options.data, ..._options.requestOptions - }) - .then(response => { - successRequest(response, t, _options) - resolve(response) - }) - .catch(error => { - if (error.response) { - errorResponse(error.response, clearToken, t, _options.notification && _options.failed.notification.show) - } else if (error.request) { - errorRequest(t, _options.notification && _options.failed.notification.show) - } else { - errorSetting(t, _options.notification && _options.failed.notification.show) - } - reject(error) - }) - }); - } - - return requestServer -} - -export default useRequest \ No newline at end of file diff --git a/src/lib/app/hooks/useUser.jsx b/src/lib/app/hooks/useUser.jsx deleted file mode 100644 index 21ccbdb..0000000 --- a/src/lib/app/hooks/useUser.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import {useContext} from "react"; -import {UserContext} from "../contexts/user"; - -const useUser = () => { - const { - isAuth, - userChangedLanguage, - token, - user, - getUser, - clearUser, - changeUser, - changeUserLanguage, - changeAuthState, - changeLanguageState, - clearToken, - setToken, - } = useContext(UserContext); - - return { - isAuth, - userChangedLanguage, - token, - user, - getUser, - clearUser, - changeUser, - changeUserLanguage, - changeAuthState, - changeLanguageState, - clearToken, - setToken, - }; -}; - -export default useUser; diff --git a/src/middlewares/Deadline.jsx b/src/middlewares/Deadline.jsx new file mode 100644 index 0000000..796ee54 --- /dev/null +++ b/src/middlewares/Deadline.jsx @@ -0,0 +1,41 @@ +import {CenterLayout, FullPageLayout, useConfig} from "@witel/webapp-builder"; +import moment from "jalali-moment"; +import SvgMaintenance from "@/core/components/svgs/SvgMaintenance"; +import {Typography} from "@mui/material"; + +const DeadlineMiddleware = ({children, type = '', withMessage = false}) => { + const {config} = useConfig() + const middleware = config.deadlines[type] + + if (!middleware) return children + + const fromDate = moment(middleware.date.from, 'jYYYY/jMM/jDD') + const toDate = moment(middleware.date.to, 'jYYYY/jMM/jDD') + const today = moment() + + if (today.isBetween(fromDate, toDate, null, '[]')) { + return children + } else if (today.isAfter(toDate, null)) { + if (!withMessage) return + return ( + + + + {middleware.messages.after || ''} + + + ) + } else if (today.isBefore(fromDate, null)) { + if (!withMessage) return + return ( + + + + {middleware.messages.before || ''} + + + ) + } +} + +export default DeadlineMiddleware \ No newline at end of file diff --git a/src/middlewares/UserInfo.jsx b/src/middlewares/UserInfo.jsx new file mode 100644 index 0000000..3f594c4 --- /dev/null +++ b/src/middlewares/UserInfo.jsx @@ -0,0 +1,9 @@ +import {useUser} from "@witel/webapp-builder"; + +const UserInfo = ({children}) => { + const {user} = useUser(); + const userAccess = user.profile_completed; + return userAccess ? <>{children} : ''; +}; + +export default UserInfo; diff --git a/src/middlewares/UserType.jsx b/src/middlewares/UserType.jsx deleted file mode 100644 index d0b20cc..0000000 --- a/src/middlewares/UserType.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import {NextLinkComposed} from "@/core/components/LinkRouting"; -import Message from "@/core/components/Messages"; -import useUser from "@/lib/app/hooks/useUser"; -import {Button, Typography} from "@mui/material"; -import {useTranslations} from "next-intl"; - -const UserTypeMiddleware = ({children, user_type}) => { - const {user} = useUser(); - const t = useTranslations(); - - const userPermission = user.type_id === user_type; - - if (!userPermission) { - return ( - - {t("Permission.typography_you_dont_have_access")} - - } - actions={ - <> - - - } - /> - ); - } - - return <>{children}; -}; - -export default UserTypeMiddleware; diff --git a/src/middlewares/WithAuth.jsx b/src/middlewares/WithAuth.jsx deleted file mode 100644 index b317492..0000000 --- a/src/middlewares/WithAuth.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import {NextLinkComposed} from "@/core/components/LinkRouting"; -import Message from "@/core/components/Messages"; -import useUser from "@/lib/app/hooks/useUser"; -import {Button, Typography} from "@mui/material"; -import {useTranslations} from "next-intl"; -import {useRouter} from "next/router"; - -const WithAuthMiddleware = ({children}) => { - const {isAuth} = useUser(); - const t = useTranslations(); - const router = useRouter(); - - if (!isAuth) - return ( - - {t( - "Authorization.typography_your_access_to_this_page_has_expired_Please_login_again" - )} - - } - actions={ - <> - - - } - /> - ); - return <>{children}; -}; - -export default WithAuthMiddleware; diff --git a/src/middlewares/WithoutAuth.jsx b/src/middlewares/WithoutAuth.jsx deleted file mode 100644 index 594ffc5..0000000 --- a/src/middlewares/WithoutAuth.jsx +++ /dev/null @@ -1,56 +0,0 @@ -import Message from "@/core/components/Messages"; -import useUser from "@/lib/app/hooks/useUser"; -import {Stack, Typography} from "@mui/material"; -import {useTranslations} from "next-intl"; -import {useSearchParams} from "next/navigation"; -import {useRouter} from "next/router"; -import {useEffect} from "react"; - -const WithoutAuthMiddleware = ({children}) => { - const {isAuth} = useUser(); - const t = useTranslations(); - const router = useRouter(); - - // gettin url query - const searchParams = useSearchParams(); - const backUrlDecodedPath = searchParams.get("back_url"); - - useEffect(() => { - if (!isAuth) return; - const timer = setTimeout(() => { - router.replace( - backUrlDecodedPath - ? decodeURIComponent(backUrlDecodedPath) - : "/dashboard" - ); - }, 2000); - - return () => { - clearTimeout(timer); - }; - }, [isAuth]); - - if (isAuth) - return ( - - - {t( - "Authorization.typography_your_login_is_valid_and_you_do_not_need_to_login_again" - )} - - - {t("Authorization.typography_redirect_to")}{" "} - {backUrlDecodedPath - ? t("Authorization.typography_routing_previuos_page") - : t("Authorization.typography_routing_dashbaord_page")} - - - } - /> - ); - return <>{children}; -}; - -export default WithoutAuthMiddleware; diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx index 0fc6a4a..848a35c 100644 --- a/src/pages/_app.jsx +++ b/src/pages/_app.jsx @@ -1,32 +1,52 @@ -import "&/fontiran.scss"; -import AppLayout from "@/layouts/AppLayout"; -import MuiLayout from "@/layouts/MuiLayout"; -import {LanguageProvider} from "@/lib/app/contexts/language"; -import {LoadingProvider} from "@/lib/app/contexts/loading"; -import {UserProvider} from "@/lib/app/contexts/user"; +import "&/global.scss"; import "moment/locale/fa"; +import { + AppLayout, + ConfigProvider, + LanguageProvider, + LoadingProvider, + MuiLayout, + NetworkProvider, + PageMiddleware, + ToastProvider, + UserProvider +} from "@witel/webapp-builder"; +import {GET_USER} from "@/core/data/apiRoutes"; +import languageList from "@/core/data/languageList"; import {NextIntlProvider} from "next-intl"; +import themeRtl from "@/core/utils/theme-rtl"; import TitlePage from "@/core/components/TitlePage"; +import GlobalHead from "@/core/components/GlobalHead"; +import Layout from "@/layouts"; const App = ({Component, pageProps}) => { - return ( - <> - - - - + return (<> + + data}> + + + {pageProps.messages ? : ''} - - - + + + + + + + + + + + - - ); + + ); }; export default App; diff --git a/src/pages/_document.jsx b/src/pages/_document.jsx index 474e29b..6aaa82f 100644 --- a/src/pages/_document.jsx +++ b/src/pages/_document.jsx @@ -1,7 +1,8 @@ -import {createEmotionCacheRtl} from "@/core/utils/createEmotionCache"; import theme from "@/core/utils/theme"; import createEmotionServer from "@emotion/server/create-instance"; import Document, {Head, Html, Main, NextScript} from "next/document"; +import {createEmotionCacheLtr, createEmotionCacheRtl} from "@witel/webapp-builder"; +import languageList from "@/core/data/languageList"; export default function MyDocument(props) { const {emotionStyleTags} = props; @@ -26,10 +27,13 @@ export default function MyDocument(props) { MyDocument.getInitialProps = async (ctx) => { const originalRenderPage = ctx.renderPage; let cache; - switch (ctx.locale) { - case "fa": + for (const lang of languageList) { + if (ctx.locale !== lang.key) continue; + if (lang.dir === 'rtl') { cache = createEmotionCacheRtl(); - break; + } else { + cache = createEmotionCacheLtr(); + } } const {extractCriticalToChunks} = createEmotionServer(cache); diff --git a/src/pages/dashboard/index.jsx b/src/pages/dashboard/index.jsx index 02c438a..b946dbd 100644 --- a/src/pages/dashboard/index.jsx +++ b/src/pages/dashboard/index.jsx @@ -1,22 +1,18 @@ import FirstComponent from "@/components/dashboard/first"; -import WithAuthMiddleware from "@/middlewares/WithAuth"; -import {parse} from "next-useragent"; +import {globalServerProps} from "@/core/utils/globalServerProps"; export default function Dashboard() { return ( - - - + ); } export async function getServerSideProps({req, locale}) { - const {isBot} = parse(req.headers["user-agent"]); return { props: { - messages: (await import(`&/locales/${locale}/app.json`)).default, + ...await globalServerProps({req, locale}), title: "Dashboard.dashboard_page", - isBot, + layout: {name: 'DashboardLayout'} }, }; } diff --git a/src/pages/dashboard/navgan/add-request-loan/index.jsx b/src/pages/dashboard/navgan/add-request-loan/index.jsx index bd8a442..71bcaf0 100644 --- a/src/pages/dashboard/navgan/add-request-loan/index.jsx +++ b/src/pages/dashboard/navgan/add-request-loan/index.jsx @@ -1,26 +1,21 @@ -import WithAuthMiddleware from "@/middlewares/WithAuth"; -import {parse} from "next-useragent"; -import UserTypeMiddleware from "@/middlewares/UserType"; import LoanRequestComponent from "@/components/dashboard/navgan/add-request-loan"; +import {globalServerProps} from "@/core/utils/globalServerProps"; +import DeadlineMiddleware from "@/middlewares/Deadline"; -const user_type = 1; export default function AddLoanRequest() { return ( - - - - - + + + ); } export async function getServerSideProps({req, locale}) { - const {isBot} = parse(req.headers["user-agent"]); return { props: { - messages: (await import(`&/locales/${locale}/app.json`)).default, + ...await globalServerProps({req, locale}), title: "LoanRequest.loan_request_page", - isBot, + layout: {name: 'DashboardLayout', permissions: ["can_request_navgan_loan"]} }, }; } diff --git a/src/pages/dashboard/navgan/followUp-loan/index.jsx b/src/pages/dashboard/navgan/followUp-loan/index.jsx index 52f0271..68f4f73 100644 --- a/src/pages/dashboard/navgan/followUp-loan/index.jsx +++ b/src/pages/dashboard/navgan/followUp-loan/index.jsx @@ -1,26 +1,18 @@ -import WithAuthMiddleware from "@/middlewares/WithAuth"; -import {parse} from "next-useragent"; -import UserTypeMiddleware from "@/middlewares/UserType"; import LoanFollowUpComponent from "@/components/dashboard/navgan/followUp-loan"; +import {globalServerProps} from "@/core/utils/globalServerProps"; -const user_type = 1; export default function FollowUpLoan() { return ( - - - - - + ); } export async function getServerSideProps({req, locale}) { - const {isBot} = parse(req.headers["user-agent"]); return { props: { - messages: (await import(`&/locales/${locale}/app.json`)).default, + ...await globalServerProps({req, locale}), title: "LoanRequest.loan_request_page", - isBot, + layout: {name: 'DashboardLayout'} }, }; } diff --git a/src/pages/dashboard/refahi/add-request-loan/index.jsx b/src/pages/dashboard/refahi/add-request-loan/index.jsx deleted file mode 100644 index b4575e9..0000000 --- a/src/pages/dashboard/refahi/add-request-loan/index.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import WithAuthMiddleware from "@/middlewares/WithAuth"; -import {parse} from "next-useragent"; - -const user_type = 2; -export default function AddLoanRequest() { - return ( - - {/**/} - {/* */} - {/**/} - - ); -} - -export async function getServerSideProps({req, locale}) { - const {isBot} = parse(req.headers["user-agent"]); - return { - props: { - messages: (await import(`&/locales/${locale}/app.json`)).default, - title: "LoanRequest.loan_request_page", - isBot, - }, - }; -} diff --git a/src/pages/dashboard/refahi/edit-request-loan/[id].jsx b/src/pages/dashboard/refahi/edit-request-loan/[id].jsx deleted file mode 100644 index f6b72d5..0000000 --- a/src/pages/dashboard/refahi/edit-request-loan/[id].jsx +++ /dev/null @@ -1,24 +0,0 @@ -import WithAuthMiddleware from "@/middlewares/WithAuth"; -import {parse} from "next-useragent"; - -const user_type = 2; -export default function EditLoanRequest() { - return ( - - {/**/} - {/* */} - {/**/} - - ); -} - -export async function getServerSideProps({req, locale}) { - const {isBot} = parse(req.headers["user-agent"]); - return { - props: { - messages: (await import(`&/locales/${locale}/app.json`)).default, - title: "EditLoanRequest.edit_loan_request_page", - isBot, - }, - }; -} diff --git a/src/pages/dashboard/refahi/followUp-loan/index.jsx b/src/pages/dashboard/refahi/followUp-loan/index.jsx deleted file mode 100644 index f679299..0000000 --- a/src/pages/dashboard/refahi/followUp-loan/index.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import WithAuthMiddleware from "@/middlewares/WithAuth"; -import {parse} from "next-useragent"; - -const user_type = 2; -export default function FollowUpLoan() { - return ( - - {/**/} - {/* */} - {/**/} - - ); -} - -export async function getServerSideProps({req, locale}) { - const {isBot} = parse(req.headers["user-agent"]); - return { - props: { - messages: (await import(`&/locales/${locale}/app.json`)).default, - title: "LoanFollowUp.loan_follow_up_page", - isBot, - }, - }; -} diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 2e146c6..6e47ba2 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -1,5 +1,5 @@ import FirstComponent from "@/components/first"; -import {parse} from "next-useragent"; +import {globalServerProps} from "@/core/utils/globalServerProps"; export default function Home() { return ( @@ -10,12 +10,10 @@ export default function Home() { } export async function getServerSideProps({req, locale}) { - const {isBot} = parse(req.headers["user-agent"]); return { props: { - messages: (await import(`&/locales/${locale}/app.json`)).default, + ...await globalServerProps({req, locale}), title: "first_page", - isBot, }, }; } diff --git a/src/pages/login.jsx b/src/pages/login.jsx index 5cac2bc..6f7b288 100644 --- a/src/pages/login.jsx +++ b/src/pages/login.jsx @@ -1,22 +1,20 @@ import LoginComponent from "@/components/login"; -import WithoutAuthMiddleware from "@/middlewares/WithoutAuth"; -import {parse} from "next-useragent"; +import {WithoutAuthMiddleware} from "@witel/webapp-builder"; +import {globalServerProps} from "@/core/utils/globalServerProps"; export default function Login() { return ( - + ); } export async function getServerSideProps({req, locale}) { - const {isBot} = parse(req.headers["user-agent"]); return { props: { - messages: (await import(`&/locales/${locale}/app.json`)).default, + ...await globalServerProps({req, locale}), title: "Titles.title_login_page", - isBot, }, }; } diff --git a/src/pages/register/index.jsx b/src/pages/register/index.jsx deleted file mode 100644 index 6d8d4d6..0000000 --- a/src/pages/register/index.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import RegisterComponent from "@/components/register"; -import WithoutAuthMiddleware from "@/middlewares/WithoutAuth"; -import {parse} from "next-useragent"; - -export default function Register() { - return ( - - - - ); -} - -export async function getServerSideProps({req, locale}) { - const {isBot} = parse(req.headers["user-agent"]); - return { - props: { - messages: (await import(`&/locales/${locale}/app.json`)).default, - title: "Titles.title_register_page", - isBot, - }, - }; -} diff --git a/src/pages/register/navy/index.jsx b/src/pages/register/navy/index.jsx index 2272d57..e69de29 100644 --- a/src/pages/register/navy/index.jsx +++ b/src/pages/register/navy/index.jsx @@ -1,22 +0,0 @@ -import NavyComponent from "@/components/register/navy"; -import WithoutAuthMiddleware from "@/middlewares/WithoutAuth"; -import {parse} from "next-useragent"; - -export default function Register() { - return ( - - - - ); -} - -export async function getServerSideProps({req, locale}) { - const {isBot} = parse(req.headers["user-agent"]); - return { - props: { - messages: (await import(`&/locales/${locale}/app.json`)).default, - title: "Titles.title_register_navy_page", - isBot, - }, - }; -} diff --git a/src/pages/register/welfare-services/index.jsx b/src/pages/register/welfare-services/index.jsx deleted file mode 100644 index ce05a4f..0000000 --- a/src/pages/register/welfare-services/index.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import WithoutAuthMiddleware from "@/middlewares/WithoutAuth"; -import {parse} from "next-useragent"; - -export default function Register() { - return ( - - {/**/} - - ); -} - -export async function getServerSideProps({req, locale}) { - const {isBot} = parse(req.headers["user-agent"]); - return { - props: { - messages: (await import(`&/locales/${locale}/app.json`)).default, - title: "Titles.title_register_welfare_services_page", - isBot, - }, - }; -}