diff --git a/public/images/upload-image.svg b/public/images/upload-image.svg new file mode 100644 index 0000000..3bbca65 --- /dev/null +++ b/public/images/upload-image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 67cc090..138c4b9 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -11,6 +11,7 @@ "pending": "درحال اجرا...", "user_navy": "ناوگان", "page_not_found": "صفحه مورد نظر یافت نشد", + "delete": "حذف", "header": { "open_profile": "پروفایل", "edit_profile": "ویرایش پروفایل", @@ -83,10 +84,8 @@ "error_message_required": "اجباری!", "text_field_phone_number": "شماره تلفن", "text_field_enter_your_phone_number": "شماره تلفن خود را وارد کنید", - "text_field_first_name": "نام", - "text_field_enter_your_first_name": "نام خود را وارد کنید", - "text_field_last_name": "نام خانوادگی", - "text_field_enter_your_last_name": "نام خانوادگی خود را وارد کنید", + "text_field_name": "نام", + "text_field_enter_your_name": "نام خود را وارد کنید", "text_field_vehicle_type": "نام وسیله نقلیه", "text_field_enter_your_vehicle_type": "نام وسیله نقلیه خود را وارد کنید", "text_field_province": "استان", @@ -95,8 +94,8 @@ "text_field_enter_your_navgan_id": "شماره ناوگان خود را وارد کنید", "text_field_national_code": "کد ملی", "text_field_enter_your_national_code": "کد ملی خود را وارد کنید", - "text_field_birth_certificate_id": "شماره شناسنامه", - "text_field_enter_your_birth_certificate_id": "شماره شناسنامه خود را وارد کنید", + "text_field_shenasname_id": "شماره شناسنامه", + "text_field_enter_your_shenasname_id": "شماره شناسنامه خود را وارد کنید", "text_field_plate_number": "شماره پلاک", "text_field_enter_your_plate_number": "شماره پلاک خود را وارد کنید", "button_submit": "ثبت درخواست" diff --git a/src/components/dashboard/loan-follow-up/index.jsx b/src/components/dashboard/loan-follow-up/index.jsx index e05fa20..1b211af 100644 --- a/src/components/dashboard/loan-follow-up/index.jsx +++ b/src/components/dashboard/loan-follow-up/index.jsx @@ -1,11 +1,8 @@ -import CenterLayout from "@/layouts/CenterLayout"; import DashboardLayouts from "@/layouts/dashboardLayouts"; import useUser from "@/lib/app/hooks/useUser"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import { - Avatar, - Box, - Card, + Avatar, Card, CardActions, CardContent, CardHeader, @@ -13,7 +10,7 @@ import { Grid, IconButton, Stack, - Typography, + Typography } from "@mui/material"; import { styled } from "@mui/material/styles"; import { useTranslations } from "next-intl"; @@ -30,19 +27,42 @@ const ExpandMore = styled((props) => { }), })); +const data = [ + { + name: "جان دو", + date: "۱۳۹۹/۰۴/۲۵", + description: + "لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.", + }, + { + name: "جین اسمیت", + date: "۱۳۹۹/۰۴/۲۶", + description: "نُلا ویته الیت لیبرو آ، آ فارِترا آوگوه.", + }, + { + name: "مایک جانسون", + date: "۱۳۹۹/۰۴/۲۷", + description: + "دوئیس مولیس، است نُن کُمُدو لُکتوس، نیسی ارات پورتیتور لیگولا.", + }, +]; + const DashboardLoanFollowUpComponent = () => { const t = useTranslations(); const { token } = useUser(); - const [expanded, setExpanded] = useState(false); + const [expanded, setExpanded] = useState([]); - const handleExpandClick = () => { - setExpanded(!expanded); + const handleExpandClick = (index) => { + setExpanded((prevExpanded) => { + const newExpanded = [...prevExpanded]; + newExpanded[index] = !newExpanded[index]; + return newExpanded; + }); }; return ( - { container columnSpacing={2} rowSpacing={2} - sx={{ alignItems: "center", justifyContent: "center" }} + sx={{ alignItems: "start", justifyContent: "center" }} > - - - - } - title="اسم اقاهه" - subheader="تاریخ اگه خواستیم" - /> - - - متن تست - - - - - - - - + {data.map((item, index) => ( + + + + } + title={item.name} + subheader={item.date} + /> - اطلاعات تکمیلی: - پارت دوم متن تست - پارت سه همون قبلی - در ادامه باید بگم که... - درپایان همینه که هست + + متن تست + - - - - - - - } - title="اسم اقاهه" - subheader="تاریخ اگه خواستیم" - /> - - - متن تست - - - - - - - - - - اطلاعات تکمیلی: - پارت دوم متن تست - پارت سه همون قبلی - در ادامه باید بگم که... - درپایان همینه که هست - - - - - - - - } - title="اسم اقاهه" - subheader="تاریخ اگه خواستیم" - /> - - - متن تست - - - - - - - - - - اطلاعات تکمیلی: - پارت دوم متن تست - پارت سه همون قبلی - در ادامه باید بگم که... - درپایان همینه که هست - - - - + + handleExpandClick(index)} + aria-expanded={expanded[index]} + aria-label="show more" + > + + + + + + اطلاعات تکمیلی: + {item.description} + + + + + ))} - ); }; diff --git a/src/components/dashboard/loan-request/NavyForm.jsx b/src/components/dashboard/loan-request/NavyForm.jsx index fc7ed83..7686862 100644 --- a/src/components/dashboard/loan-request/NavyForm.jsx +++ b/src/components/dashboard/loan-request/NavyForm.jsx @@ -1,4 +1,6 @@ +import Notifications from "@/core/components/notifications"; import StyledForm from "@/core/components/StyledForm"; +import useDirection from "@/lib/app/hooks/useDirection"; import DataSaverOnIcon from "@mui/icons-material/DataSaverOn"; import { Box, Button, Stack, TextField } from "@mui/material"; import { Field, Formik } from "formik"; @@ -7,26 +9,45 @@ import Image from "next/image"; const NavyForm = () => { const t = useTranslations(); + const { directionApp } = useDirection(); const initialValues = { - first_name: "", - last_name: "", + name: "", phone_number: "", vehicle_type: "", plate_number: "", province: "", navgan_id: "", national_code: "", - birth_certificate_id: "", + shenasname_id: "", national_card_img: "", - birth_certificate_img: "", + shenasname_img: "", + }; + + const handleSubmit = async (values, props) => { + Notifications(directionApp, t, undefined); + await axios + .post(SEND_LOAN_REQUEST_NAVGAN, { + name: values.name, + phone_number: values.phone_number, + vehicle_type: values.vehicle_type, + plate_number: values.plate_number, + province_id: values.province, + navgan_id: values.navgan_id, + national_code: values.national_code, + shenasname_id: values.shenasname_id, + }) + .then(function (response) { + Notifications(directionApp, t, response); + }) + .catch(function (error) { + Notifications(directionApp, t, error.response); + props.setSubmitting(false); + }); }; return ( - + {(props) => ( { - - - { diff --git a/src/components/dashboard/loan-request/WelfareServicesForm.jsx b/src/components/dashboard/loan-request/WelfareServicesForm.jsx index 0bca6ff..4ea21b6 100644 --- a/src/components/dashboard/loan-request/WelfareServicesForm.jsx +++ b/src/components/dashboard/loan-request/WelfareServicesForm.jsx @@ -1,31 +1,71 @@ +import Notifications from "@/core/components/notifications"; import StyledForm from "@/core/components/StyledForm"; +import UploadSystem from "@/core/components/UploadSystem"; +import { SEND_LOAN_REQUEST_WELFARE } from "@/core/data/apiRoutes"; +import useDirection from "@/lib/app/hooks/useDirection"; 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 { useTranslations } from "next-intl"; -import Image from "next/image"; +import { useState } from "react"; import * as Yup from "yup"; const WelfareServicesForm = () => { const t = useTranslations(); + const { directionApp } = useDirection(); + // 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]; + const fileType = event.target.files[0].type; + const fileName = event.target.files[0].name; + if (uploadedFile) { + 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, validation and request action of form const initialValues = { - first_name: "", - last_name: "", + name: "", phone_number: "", vehicle_type: "", plate_number: "", province: "", - navgan_id: "", national_code: "", - birth_certificate_id: "", - national_card_img: "", - birth_certificate_img: "", + shenasname_id: "", + national_card_img: null, + shenasname_img: null, }; const validationSchema = Yup.object().shape({ - first_name: Yup.string().required(t("LoanRequest.error_message_required")), - last_name: Yup.string().required(t("LoanRequest.error_message_required")), + name: Yup.string().required(t("LoanRequest.error_message_required")), phone_number: Yup.string().required( t("LoanRequest.error_message_required") ), @@ -36,19 +76,45 @@ const WelfareServicesForm = () => { t("LoanRequest.error_message_required") ), province: Yup.string().required(t("LoanRequest.error_message_required")), - navgan_id: Yup.string().required(t("LoanRequest.error_message_required")), national_code: Yup.string().required( t("LoanRequest.error_message_required") ), - birth_certificate_id: Yup.string().required( + shenasname_id: Yup.string().required( t("LoanRequest.error_message_required") ), }); + const handleSubmit = async (values, props) => { + Notifications(directionApp, t, undefined); + console.log(values.national_card_img); + console.log(values.shenasname_img); + await axios + .post(SEND_LOAN_REQUEST_WELFARE, { + name: values.name, + phone_number: values.phone_number, + vehicle_type: values.vehicle_type, + plate_number: values.plate_number, + province_id: values.province, + navgan_id: values.navgan_id, + national_code: values.national_code, + shenasname_id: values.shenasname_id, + national_card_image: values.national_card_img, + shenasname_image: values.shenasname_img, + }) + .then(function (response) { + Notifications(directionApp, t, response); + }) + .catch(function (error) { + Notifications(directionApp, t, error.response); + props.setSubmitting(false); + }); + }; + // end initial values, validation and request action of form + return ( {(props) => ( @@ -79,50 +145,15 @@ const WelfareServicesForm = () => { - - - { width: "100%", }} > - - - { @@ -365,24 +368,32 @@ const WelfareServicesForm = () => { width: "100%", }} > - - {t("app_name")} - - - {t("app_name")} - + + 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*/]} + /> + + 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*/]} + /> { flexDirection: { xs: "column", sm: "row" }, alignItems: "center", mx: "auto", + my: 2, width: { xs: "100%", sm: "30%", md: "25%" }, }} > diff --git a/src/components/first/index.jsx b/src/components/first/index.jsx index 897f7cd..edd3a8a 100644 --- a/src/components/first/index.jsx +++ b/src/components/first/index.jsx @@ -19,6 +19,7 @@ const FirstComponent = () => { alt={t("app_name")} width={300} height={200} + priority /> {t("app_name")} diff --git a/src/components/register-navy/SendToken.jsx b/src/components/register-navy/SendToken.jsx index fcba709..62bbb86 100644 --- a/src/components/register-navy/SendToken.jsx +++ b/src/components/register-navy/SendToken.jsx @@ -76,6 +76,7 @@ const SendToken = ({ PhoneNumber, nationalId, navganId, typeId }) => { fill src="/images/register.svg" alt={t("app_name")} + priority /> diff --git a/src/components/register-navy/SendUserData.jsx b/src/components/register-navy/SendUserData.jsx index bb13517..1433266 100644 --- a/src/components/register-navy/SendUserData.jsx +++ b/src/components/register-navy/SendUserData.jsx @@ -4,6 +4,7 @@ import StyledForm from "@/core/components/StyledForm"; import { REGISTER_SEND_OTP_TOKEN } from "@/core/data/apiRoutes"; import CenterLayout from "@/layouts/CenterLayout"; import FullPageLayout from "@/layouts/FullPageLayout"; +import useDirection from "@/lib/app/hooks/useDirection"; import FingerprintIcon from "@mui/icons-material/Fingerprint"; import { Box, @@ -90,6 +91,7 @@ const SendUserData = ({ fill src="/images/register.svg" alt={t("app_name")} + priority /> diff --git a/src/components/register-welfare-services/SendUserData.jsx b/src/components/register-welfare-services/SendUserData.jsx index c74a1f4..07fb6e0 100644 --- a/src/components/register-welfare-services/SendUserData.jsx +++ b/src/components/register-welfare-services/SendUserData.jsx @@ -88,6 +88,7 @@ const SendUserData = ({ fill src="/images/register.svg" alt={t("app_name")} + priority /> diff --git a/src/components/register-welfare-services/sendToken.jsx b/src/components/register-welfare-services/sendToken.jsx index 7634f93..5d5af44 100644 --- a/src/components/register-welfare-services/sendToken.jsx +++ b/src/components/register-welfare-services/sendToken.jsx @@ -76,6 +76,7 @@ const SendToken = ({ PhoneNumber, nationalId, typeId }) => { fill src="/images/register.svg" alt={t("app_name")} + priority /> diff --git a/src/core/components/Messages.jsx b/src/core/components/Messages.jsx index db6a980..2bd45c8 100644 --- a/src/core/components/Messages.jsx +++ b/src/core/components/Messages.jsx @@ -11,6 +11,7 @@ const Message = ({ text, actions }) => { alt="loading loan facilities" width={100} height={100} + priority /> {text} {actions} diff --git a/src/core/components/UploadSystem.jsx b/src/core/components/UploadSystem.jsx new file mode 100644 index 0000000..b60552a --- /dev/null +++ b/src/core/components/UploadSystem.jsx @@ -0,0 +1,163 @@ +import { Box, Button, TextField, Typography } from "@mui/material"; +import { useTranslations } from "next-intl"; +import Image from "next/image"; +import DeleteForeverIcon from "@mui/icons-material/DeleteForever"; +import { useRef } from "react"; + +const UploadSystem = ({ + selectedImage, + setselectedImage, + handleUploadChange, + fieldname, + setFieldValue, + imageAlt, + imageSize, + fileType, + fileName, +}) => { + const t = useTranslations(); + const fileInputRef = useRef(null); + + const handleClick = () => { + fileInputRef.current.click(); + }; + const handleDeleteImage = () => { + setselectedImage("/images/upload-image.svg"); + setFieldValue(fieldname, null); + }; + + const isDocumentFormat = (fileType) => { + const documentFormats = [ + "application/pdf", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.ms-excel", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + ]; + return documentFormats.includes(fileType); + }; + + return ( + + {selectedImage === "/images/upload-image.svg" ? ( + {imageAlt} + ) : fileType && fileType.startsWith("image/") ? ( + {imageAlt} + ) : ( + fileType && + isDocumentFormat(fileType) && ( + + + {fileName} + + + ) + )} + + + + + ); +}; + +export default UploadSystem; + + + +//////****** usage document ******///////// +// 1.) use component inside your page +// 2.) list of props that you need to send is down below +// 2.1) selectedImage // this value come from useState that you need to write on your own component +// 2.2) handleUploadChange // use on your own component (explain below more) you should set it to {(e) =>handleUploadChange[your special name]](e, props.setFieldValue)} +// 2.3) setFieldValue // for setting value of file to null when user click on Delete button. you should set it to {props.setFieldValue} +// 2.4) fieldname name that file field has on your formik initialValues. +// 2.5) fileType // type of your file shows its document image etc... +// 2.6) imageAlt // alt of your image. +// 2.7) imageSize // this is size of your image box and value type is like that imageSize={ [width , height] }. +// 2.9) setselectedImage // for making box empty when user click on delete button (explain below more) + +// const [selectedImage[your special name]], setSelectedImage[your special name]] = useState( +// "/images/upload-image.svg" // default image +// ); +// const [fileType[your special name], setFileType[your special name]] = useState(null); +// const [fileName[your special name], setFileName[your special name]] = useState(null); + + +// const handleUploadChange[your special name]] = (event, setFieldValue) => { +// const uploadedFile = event.target?.files?.[0]; +// const fileType = event.target.files[0].type; +// const fileName = event.target.files[0].name; +// if (uploadedFile) { // just check file is uploaded or not +// setSelectedImage[your special name]](URL.createObjectURL(uploadedFile)); // set image value +// setFileType[your special name]](fileType); // set fileType +// setFileName[your special name]](fileName); // set fileName +// setFieldValue("[your special name]]_img", uploadedFile); set field value for sending data (this automaticaly append value in initial state) +// } +// }; +//////****** end usage document ******///////// diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index b4a2241..ebbd73c 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -5,5 +5,7 @@ export const LOGIN = BASE_URL + "/login"; export const REGISTER_SEND_OTP_TOKEN = BASE_URL + "/register/send_otp"; export const REGISTER = BASE_URL + "/register"; export const USER_INFO = BASE_URL + "/profile/info"; +export const SEND_LOAN_REQUEST_NAVGAN = BASE_URL + "/navgan/store_loan"; +export const SEND_LOAN_REQUEST_WELFARE = BASE_URL + "/navgan/store_loan";