complete edit and details part of loan

This commit is contained in:
2023-12-20 13:22:07 +03:30
parent c95b4c329e
commit d864108439
13 changed files with 852 additions and 542 deletions

View File

@@ -1,7 +1,14 @@
{
"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": "ورود",
@@ -188,35 +195,45 @@
},
"ShowLoan": {
"show_loan_page": "نمایش وام | ناوگان",
"text_field_national_code": "کد ملی",
"loading_show_component": "درحال دریافت اطلاعات درخواست...",
"tel_number_max": "شماره ثابت می بایست 11 رقم باشد",
"text_field_national_id": "کد ملی",
"text_field_postal_code": "کد پستی",
"text_field_national_card_serial_num": "سریال پشت کارت ملی",
"text_field_national_serial_number": "سریال پشت کارت ملی",
"text_field_address": "آدرس",
"text_field_birth_date": "تاریخ تولد",
"text_field_birthday": "تاریخ تولد",
"text_field_navgan_id": "کد ناوگان",
"text_field_province_id": "استان",
"text_field_owner_full_name": "نام کامل مالک",
"text_field_education_id": "تحصیلات",
"text_field_occupation_id": "شغل",
"text_field_name": "نام کامل مالک",
"text_field_navgan_type": "نوع ناوگان",
"text_field_vehicle_type": "نوع وسیله",
"text_field_enter_your_national_code": "کد ملی را وارد کنید",
"text_field_tel_number": "شماره ثابت (با پیش شماره استان)",
"text_field_enter_your_national_id": "کد ملی را وارد کنید",
"text_field_enter_your_postal_code": "کد پستی را وارد کنید",
"text_field_enter_your_national_card_serial_num": "سریال پشت کارت ملی را وارد کنید",
"text_field_enter_your_national_serial_number": "سریال پشت کارت ملی را وارد کنید",
"text_field_enter_your_address": "آدرس را وارد کنید",
"text_field_enter_your_birth_date": "تاریخ تولد را وارد کنید",
"text_field_enter_your_tel_number": "شماره ثابت (با پیش شماره استان) خود را وارد کنید",
"text_field_enter_your_birthday": "تاریخ تولد را وارد کنید",
"text_field_enter_your_navgan_id": "کد ناوگان را وارد کنید",
"text_field_enter_your_owner_full_name": "نام کامل مالک را وارد کنید",
"error_message_national_code": "لطفا کد ملی را وارد کنید!",
"text_field_enter_your_name": "نام کامل مالک را وارد کنید",
"postal_code_max": "کد پستی می بایست 10 رقم باشد",
"error_message_postal_code": "لطفا کد پستی را وارد کنید!",
"error_message_national_card_serial_num": "لطفا سریال پشت کارت ملی را وارد کنید!",
"error_message_national_serial_number": "لطفا سریال پشت کارت ملی را وارد کنید!",
"error_message_address": "لطفا آدرس را وارد کنید!",
"error_message_birth_date": "لطفا تاریخ تولد را وارد کنید!",
"error_message_birthday": "لطفا تاریخ تولد را وارد کنید!",
"error_message_navgan_id": "لطفا کد ناوگان را وارد کنید!",
"error_message_province_id": "لطفا استان را وارد کنید!",
"error_message_city_id": "لطفا شهر خود را وارد کنید!",
"error_message_owner_full_name": "لطفا نام کامل مالک را وارد کنید!",
"error_message_name": "لطفا نام کامل مالک را وارد کنید!",
"error_message_date_of_birth": "لطفا تاریخ تولد خود را وارد کنید!",
"error_message_navgan_type": "لطفا نوع ناوگان را وارد کنید!",
"error_message_vehicle_type": "لطفا نوع وسیله را وارد کنید!",
"error_message_fixed_number": "لطفا تلفن ثابت را وارد کنید!",
"error_message_tel_number": "لطفا شماره ثابت (با پیش شماره استان) خود را وارد کنید!",
"error_message_occupation_id": "لطفا کد شغل (با توجه به مستندات ارائه شده) را به درستی وارد کنید!",
"error_message_education_id": "لطفا تحصیلات (با توجه به مستندات ارائه شده) را به درستی وارد کنید!",
"cityList_empty": "شهر یافت نشد",
"button_submit": "ویرایش"
},

View File

@@ -0,0 +1,658 @@
import StyledForm from "@/core/components/StyledForm";
import {Box, Button, Chip, Divider, Stack, TextField} from "@mui/material";
import {Field, Formik} from "formik";
import {useTranslations} from "next-intl";
import EditIcon from '@mui/icons-material/Edit';
import * as Yup from "yup";
import SelectBox from "@/core/components/SelectBox";
import PlateNumber from "@/core/components/PlateNumber";
import MuiDatePicker from "@/core/components/MuiDatePicker";
import moment from "jalali-moment";
import useProvince from "@/lib/app/hooks/useProvince";
import useCities from "@/lib/app/hooks/useCities";
import UseEducations from "@/lib/app/hooks/useEducations";
import useOccupations from "@/lib/app/hooks/useOccupations";
import {UPDATE_LOAN} from "@/core/data/apiRoutes";
import {useRequest} from "@witel/webapp-builder";
import {useRouter} from "next/router";
import {useEffect} from "react";
const UpdateForm = ({LoanDetails, LoanId}) => {
const t = useTranslations();
const provinceStates = useProvince();
const router = useRouter()
const citiesStates = useCities();
const educationStates = UseEducations();
const occupationStates = useOccupations();
const requestServer = useRequest();
useEffect(() => {
citiesStates.setProvinceID(LoanDetails.province_id)
}, [provinceStates]);
// initial values
const initialValues = {
national_id: LoanDetails.national_id,
postal_code: LoanDetails.postal_code,
national_serial_number: LoanDetails.national_serial_number,
address: LoanDetails.address,
birthday: moment(LoanDetails.birthday),
navgan_id: LoanDetails.navgan_id,
province_id: LoanDetails.province_id,
city_id: LoanDetails.city_id,
name: LoanDetails.name,
navgan_type: LoanDetails.navgan_type,
vehicle_type: LoanDetails.vehicle_type,
telephone_number: LoanDetails.telephone_number,
plate_part1: LoanDetails.plate_number.split("-")[0],
plate_part2: LoanDetails.plate_number.split("-")[1],
plate_part3: LoanDetails.plate_number.split("-")[2],
plate_part4: LoanDetails.plate_number.split("-")[3],
education_id: LoanDetails.education_id,
occupation_id: LoanDetails.occupation_id,
};
// end initial values
// validation
const validationSchema = Yup.object().shape({
postal_code: Yup.mixed()
.test("max", `${t("ShowLoan.postal_code_max")}`, (value) => value.toString().length === 10)
.required(
t("ShowLoan.error_message_postal_code")
),
address: Yup.string().required(t("ShowLoan.error_message_address")),
province_id: Yup.string().required(t("ShowLoan.error_message_province_id")),
city_id: Yup.string().required(t("ShowLoan.error_message_city_id")),
telephone_number: Yup.mixed()
.test("max", `${t("ShowLoan.tel_number_max")}`, (value) => {
const stringValue = String(value);
return stringValue.length === 11
})
.required(t("ShowLoan.error_message_tel_number")),
occupation_id: Yup.string().required(t("ShowLoan.error_message_occupation_id")),
education_id: Yup.string().required(t("ShowLoan.error_message_education_id")),
birthday: Yup.string().required(t("ShowLoan.error_message_date_of_birth")),
});
// end validation
// submit
const handleSubmit = async (values, props) => {
props.setSubmitting(true)
const formData = new FormData();
formData.append("postal_code", values.postal_code);
formData.append("address", values.address);
formData.append("province_id", values.province_id);
formData.append("city_id", values.city_id);
formData.append("telephone_number", values.telephone_number);
formData.append("occupation_id", values.occupation_id);
formData.append("education_id", values.education_id);
formData.append("national_serial_number", values.national_serial_number);
formData.append("birthday", values.birthday.locale('en').format("YYYY-MM-DD"));
await requestServer(UPDATE_LOAN + LoanId, "post", {
auth: true, notification: true, data: formData
}).then(() => {
router.push("/dashboard/navgan/followUp-loan")
}).catch(() => {
}).finally(() => {
props.setSubmitting(false)
})
};
// end submit
return (
<>
<Box sx={{width: "80%", my: 2}}>
<Divider>
<Chip
label={t("ShowLoan.show_loan_page")}
/>
</Divider>
</Box>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Stack
spacing={2}
sx={{
p: 1,
width: "100%",
}}
>
<StyledForm sx={{width: "100%"}}>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="national_id"
disabled
variant="standard"
size="small"
label={t("ShowLoan.text_field_national_id")}
placeholder={t("ShowLoan.text_field_enter_your_national_id")}
type={'tel'}
error={!!(props.touched.national_id && props.errors.national_id)}
fullWidth
helperText={props.touched.national_id ? props.errors.national_id : null}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="name"
disabled
variant="standard"
size="small"
label={t("ShowLoan.text_field_name")}
placeholder={t(
"ShowLoan.text_field_enter_your_name"
)}
type={"text"}
error={!!(props.touched.name && props.errors.name)}
fullWidth
helperText={
props.touched.name
? props.errors.name
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="navgan_id"
disabled
variant="standard"
size="small"
label={t("ShowLoan.text_field_navgan_id")}
placeholder={t(
"ShowLoan.text_field_enter_your_navgan_id"
)}
type={'tel'}
error={!!(props.touched.navgan_id && props.errors.navgan_id)}
fullWidth
helperText={
props.touched.navgan_id
? props.errors.navgan_id
: null
}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<SelectBox
name="navgan_type"
label={t("ShowLoan.text_field_navgan_type")}
size="small"
disabled
variant="standard"
selectType="navgan_type"
schema={{value: "value", name: "name"}}
selectors={[
{
id: 1,
value: "روستایی",
name: "روستایی"
},
{
id: 2,
value: "عمومی",
name: "عمومی"
},
{
id: 3,
value: "منطقه آزاد",
name: "منطقه آزاد"
}
]}
select={props.values.navgan_type}
handleChange={(event) => {
props.setFieldValue('navgan_type', event.target.value)
}}
setFieldTouched={props.setFieldTouched}
error={props.touched.navgan_type && Boolean(props.errors.navgan_type)}
helperText={props.touched.navgan_type && props.errors.navgan_type}
onBlur={props.handleBlur("navgan_type")}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<PlateNumber formik={props} disabled={true}/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<SelectBox
name="vehicle_type"
label={t("ShowLoan.text_field_vehicle_type")}
size="small"
disabled
variant="standard"
selectType="vehicle_type"
schema={{value: "value", name: "name"}}
selectors={[
{
id: 0,
value: "اتوبوس",
name: "اتوبوس"
},
{
id: 1,
value: "مینی بوس",
name: "مینی بوس"
},
{
id: 2,
value: "سواری",
name: "سواری"
}
]}
select={props.values.vehicle_type}
handleChange={(event) => props.setFieldValue('vehicle_type', event.target.value)}
error={props.touched.vehicle_type && Boolean(props.errors.vehicle_type)}
helperText={props.touched.vehicle_type && props.errors.vehicle_type}
onBlur={props.handleBlur("vehicle_type")}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="national_serial_number"
size="small"
label={t("ShowLoan.text_field_national_serial_number")}
placeholder={t(
"ShowLoan.text_field_enter_your_national_serial_number"
)}
type={"text"}
error={!!(props.touched.national_serial_number && props.errors.national_serial_number)}
fullWidth
helperText={
props.touched.national_serial_number
? props.errors.national_serial_number
: null
}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<MuiDatePicker
formik={props}
disableFuture={true}
error={props.touched.birthday && Boolean(props.errors.birthday)}
helperText={props.touched.birthday && props.errors.birthday}
onBlur={props.handleBlur("birthday")}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="postal_code"
variant="outlined"
size="small"
label={t("ShowLoan.text_field_postal_code")}
placeholder={t(
"ShowLoan.text_field_enter_your_postal_code"
)}
type={'tel'}
error={!!(props.touched.postal_code && props.errors.postal_code)}
fullWidth
helperText={
props.touched.postal_code
? props.errors.postal_code
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
{provinceStates.provinceList.length !== 0 ?
<SelectBox
name="province_id"
label={t("ShowLoan.text_field_province_id")}
size="small"
selectType="province_id"
schema={{value: "value", name: "name"}}
isLoading={provinceStates.isLoadingProvinceList}
errorEcured={provinceStates.errorProvinceList}
selectors={provinceStates.provinceList}
select={props.values.province_id}
handleChange={(event) => {
props.setFieldValue('province_id', event.target.value);
citiesStates.setProvinceID(event.target.value)
props.setFieldTouched("city_id", false, false);
props.setFieldValue("city_id", "")
}}
setFieldTouched={props.setFieldTouched}
error={props.touched.province_id && Boolean(props.errors.province_id)}
helperText={props.touched.province_id && props.errors.province_id}
onBlur={props.handleBlur("province_id")}
/> : <Field
as={TextField}
sx={{width: "100%"}}
variant="outlined"
disabled
size="small"
label={t("ShowLoan.text_field_province_id")}
value={t("text_field_loading")}
type={"text"}
/>}
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
{citiesStates.cityList.length !== 0 ?
<SelectBox
name="city_id"
label={citiesStates.cityList.length === 0 ? `${t("ShowLoan.cityList_empty")}` : citiesStates.cityTextField}
size="small"
selectType="city_id"
disabled={citiesStates.cityList.length === 0}
selectors={citiesStates.cityList}
select={props.values.city_id}
schema={{value: "value", name: "name"}}
handleChange={(event) => props.setFieldValue('city_id', event.target.value)}
setFieldTouched={props.setFieldTouched}
error={props.touched.city_id && Boolean(props.errors.city_id)}
helperText={props.touched.city_id && props.errors.city_id}
onBlur={props.handleBlur("city_id")}
/> : <Field
as={TextField}
sx={{width: "100%"}}
variant="outlined"
disabled
size="small"
label={t("ShowLoan.cityList_empty")}
value={t("text_field_loading")}
type={"text"}
/>}
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<TextField
sx={{width: "100%"}}
name="telephone_number"
variant="outlined"
type={'tel'}
size="small"
value={props.values.telephone_number}
onChange={props.handleChange}
label={t("ShowLoan.text_field_tel_number")}
placeholder={t(
"ShowLoan.text_field_enter_your_tel_number"
)}
fullWidth
onBlur={props.handleBlur("telephone_number")}
error={props.touched.telephone_number && Boolean(props.errors.telephone_number)}
helperText={props.touched.telephone_number && props.errors.telephone_number}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
{educationStates.educationsList.length !== 0 ?
<SelectBox
name="education_id"
label={t("ShowLoan.text_field_education_id")}
size="small"
isLoading={educationStates.isLoadingEducationsList}
errorEcured={educationStates.errorEducationsList}
selectType="education_id"
selectors={educationStates.educationsList}
select={props.values.education_id}
schema={{value: "id", name: "title"}}
handleChange={(event) => {
props.setFieldValue('education_id', event.target.value)
}}
setFieldTouched={props.setFieldTouched}
error={props.touched.education_id && Boolean(props.errors.education_id)}
helperText={props.touched.education_id && props.errors.education_id}
onBlur={props.handleBlur("education_id")}
/> : <Field
as={TextField}
sx={{width: "100%"}}
variant="outlined"
disabled
size="small"
label={t("ShowLoan.text_field_education_id")}
value={t("text_field_loading")}
type={"text"}
/>}
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
{occupationStates.occupationsList.length !== 0 ?
<SelectBox
name="occupation_id"
label={t("ShowLoan.text_field_occupation_id")}
size="small"
isLoading={occupationStates.isLoadingOccupationsList}
errorEcured={occupationStates.errorOccupationsList}
selectType="occupation_id"
selectors={occupationStates.occupationsList}
select={props.values.occupation_id}
schema={{value: "id", name: "title"}}
handleChange={(event) => {
props.setFieldValue('occupation_id', event.target.value)
}}
setFieldTouched={props.setFieldTouched}
error={props.touched.occupation_id && Boolean(props.errors.occupation_id)}
helperText={props.touched.occupation_id && props.errors.occupation_id}
onBlur={props.handleBlur("occupation_id")}
/> : <Field
as={TextField}
sx={{width: "100%"}}
variant="outlined"
disabled
size="small"
label={t("ShowLoan.text_field_occupation_id")}
value={t("text_field_loading")}
type={"text"}
/>}
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
multiline
rows={4}
sx={{width: "100%"}}
name="address"
variant="outlined"
size="small"
label={t("ShowLoan.text_field_address")}
placeholder={t("ShowLoan.text_field_enter_your_address")}
type={"text"}
error={!!(props.touched.address && props.errors.address)}
fullWidth
helperText={props.touched.address ? props.errors.address : null}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "center",
mx: "auto",
width: {xs: "100%", sm: "30%", md: "25%"},
}}
>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
sx={{mt: 2}}
endIcon={<EditIcon/>}
disabled={props.isSubmitting || !props.dirty || !props.isValid}
>
{t("ShowLoan.button_submit")}
</Button>
</Box>
</StyledForm>
</Stack>
)}
</Formik>
</>
);
};
export default UpdateForm;

View File

@@ -1,472 +1,34 @@
import StyledForm from "@/core/components/StyledForm";
import {Box, Button, Stack, TextField} from "@mui/material";
import {Field, Formik} from "formik";
import UpdateForm from "@/components/dashboard/navgan/show/form/UpdateForm";
import {useEffect, useState} from "react";
import {GET_LOAN_DETAILS} from "@/core/data/apiRoutes";
import {useRouter} from "next/router";
import {SvgLoading, useRequest} from "@witel/webapp-builder";
import {Stack, Typography} from "@mui/material";
import {useTranslations} from "next-intl";
import EditIcon from '@mui/icons-material/Edit';
import * as Yup from "yup";
import SelectBox from "@/core/components/SelectBox";
import useProvince from "@/lib/app/hooks/useProvince";
import useCities from "@/lib/app/hooks/useCities";
import {useEffect} from "react";
import PlateNumber from "@/core/components/PlateNumber";
import MuiDatePicker from "@/core/components/MuiDatePicker";
const ShowLoanForm = () => {
const t = useTranslations();
const {provinceList, isLoadingProvinceList, errorProvinceList} = useProvince();
const {cityList, cityTextField, setProvinceID, isLoadingCityList} = useCities();
// initial values
const initialValues = {
national_code: "0312288875",
postal_code: "326585475",
national_card_serial_num: "0312288875",
address: "تهران - ثنایی - مطهری ساختمان مهتاب",
birth_date: "10/25/44",
navgan_id: "14575",
province_id: "9",
city_id: "33",
owner_full_name: "حسن قلی ابدوالابادی",
navgan_type: "2",
vehicle_type: "1",
fixed_number: "02637317735",
plate_part1: "22",
plate_part2: "ب",
plate_part3: "333",
plate_part4: "12",
};
// end initial values
const {query} = useRouter();
const requestServer = useRequest({auth: true, notification: false});
const [LoanDetails, setLoanDetails] = useState({});
useEffect(() => {
setProvinceID(initialValues.province_id);
}, [initialValues.province_id]);
// validation
const validationSchema = Yup.object().shape({
national_code: Yup.string().required(t("ShowLoan.error_message_national_code")),
postal_code: Yup.string().required(t("ShowLoan.error_message_postal_code")),
national_card_serial_num: Yup.string().required(t("ShowLoan.error_message_national_card_serial_num")),
address: Yup.string().required(t("ShowLoan.error_message_address")),
birth_date: Yup.string().required(t("ShowLoan.error_message_birth_date")),
navgan_id: Yup.string().required(t("ShowLoan.error_message_navgan_id")),
province_id: Yup.string().required(t("ShowLoan.error_message_province_id")),
city_id: Yup.string().required(t("ShowLoan.error_message_city_id")),
owner_full_name: Yup.string().required(t("ShowLoan.error_message_owner_full_name")),
navgan_type: Yup.string().required(t("ShowLoan.error_message_navgan_type")),
vehicle_type: Yup.string().required(t("ShowLoan.error_message_vehicle_type")),
fixed_number: Yup.string().required(t("ShowLoan.error_message_fixed_number")),
});
// end validation
// submit
const handleSubmit = async (values, props) => {
const formData = new FormData();
formData.append("national_code", values.national_code);
formData.append("postal_code", values.postal_code);
formData.append("national_card_serial_num", values.national_card_serial_num);
formData.append("address", values.address);
formData.append("birth_date", values.birth_date);
formData.append("navgan_id", values.navgan_id);
formData.append("province_id", values.province_id);
formData.append("city_id", values.city_id);
formData.append("owner_full_name", values.owner_full_name);
formData.append("navgan_type", values.navgan_type);
formData.append("vehicle_type", values.vehicle_type);
formData.append("fixed_number", values.fixed_number);
};
// end submit
requestServer(GET_LOAN_DETAILS + query.id, 'get', {auth: true, notification: false}).then(({data}) => {
setLoanDetails(data.data);
}).catch(() => {
})
}, []);
if (Object.keys(LoanDetails).length === 0) {
return (
<Stack sx={{alignItems: "center", justifyContent: "center"}} spacing={3}>
<SvgLoading height={150} width={150}/>
<Typography>{t("ShowLoan.loading_show_component")}</Typography>
</Stack>
);
}
return (
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Stack
spacing={2}
sx={{
p: 1,
width: "100%",
}}
>
<StyledForm sx={{width: "100%"}}>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="national_code"
disabled
variant="standard"
size="small"
label={t("ShowLoan.text_field_national_code")}
placeholder={t("ShowLoan.text_field_enter_your_national_code")}
type={"text"}
error={!!(props.touched.national_code && props.errors.national_code)}
fullWidth
helperText={props.touched.national_code ? props.errors.national_code : null}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="birth_date"
disabled
variant="standard"
size="small"
label={t("ShowLoan.text_field_birth_date")}
placeholder={t(
"ShowLoan.text_field_enter_your_birth_date"
)}
type={"text"}
error={!!(props.touched.birth_date && props.errors.birth_date)}
fullWidth
helperText={
props.touched.birth_date
? props.errors.birth_date
: null
}
/>
<MuiDatePicker
formik={props}
error={props.touched.birthday && Boolean(props.errors.birthday)}
helperText={props.touched.birthday && props.errors.birthday}
onBlur={props.handleBlur("birthday")}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="national_card_serial_num"
disabled
variant="standard"
size="small"
label={t("ShowLoan.text_field_national_card_serial_num")}
placeholder={t(
"ShowLoan.text_field_enter_your_national_card_serial_num"
)}
type={"text"}
error={!!(props.touched.national_card_serial_num && props.errors.national_card_serial_num)}
fullWidth
helperText={
props.touched.national_card_serial_num
? props.errors.national_card_serial_num
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="owner_full_name"
disabled
variant="standard"
size="small"
label={t("ShowLoan.text_field_owner_full_name")}
placeholder={t(
"ShowLoan.text_field_enter_your_owner_full_name"
)}
type={"text"}
error={!!(props.touched.owner_full_name && props.errors.owner_full_name)}
fullWidth
helperText={
props.touched.owner_full_name
? props.errors.owner_full_name
: null
}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<SelectBox
name="vehicle_type"
label={t("ShowLoan.text_field_vehicle_type")}
size="small"
disabled
variant="standard"
selectType="vehicle_type"
selectors={[{id: 0, value: 0, name: "اتوبوس"},
{id: 1, value: 1, name: "مینی بوس"}]}
select={props.values.vehicle_type}
handleChange={(event) => props.setFieldValue('vehicle_type', event.target.value)}
error={props.touched.vehicle_type && Boolean(props.errors.vehicle_type)}
helperText={props.touched.vehicle_type && props.errors.vehicle_type}
onBlur={props.handleBlur("vehicle_type")}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<SelectBox
name="navgan_type"
label={t("ShowLoan.text_field_navgan_type")}
size="small"
disabled
variant="standard"
selectType="navgan_type"
selectors={[{id: 1, value: 1, name: "مسافری"}, {id: 2, value: 2, name: "عمومی"}, {
id: 3,
value: 3,
name: "روستایی"
}]}
select={props.values.navgan_type}
handleChange={(event) => {
props.setFieldValue('navgan_type', event.target.value)
}}
setFieldTouched={props.setFieldTouched}
error={props.touched.navgan_type && Boolean(props.errors.navgan_type)}
helperText={props.touched.navgan_type && props.errors.navgan_type}
onBlur={props.handleBlur("navgan_type")}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<PlateNumber formik={props} disabled={true}/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="address"
variant="outlined"
size="small"
label={t("ShowLoan.text_field_address")}
placeholder={t("ShowLoan.text_field_enter_your_address")}
type={"text"}
error={!!(props.touched.address && props.errors.address)}
fullWidth
helperText={props.touched.address ? props.errors.address : null}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="postal_code"
variant="outlined"
size="small"
label={t("ShowLoan.text_field_postal_code")}
placeholder={t(
"ShowLoan.text_field_enter_your_postal_code"
)}
type={"text"}
error={!!(props.touched.postal_code && props.errors.postal_code)}
fullWidth
helperText={
props.touched.postal_code
? props.errors.postal_code
: null
}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="navgan_id"
variant="outlined"
size="small"
label={t("ShowLoan.text_field_navgan_id")}
placeholder={t(
"ShowLoan.text_field_enter_your_navgan_id"
)}
type={"text"}
error={!!(props.touched.navgan_id && props.errors.navgan_id)}
fullWidth
helperText={
props.touched.navgan_id
? props.errors.navgan_id
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<SelectBox
name="province_id"
label={t("ShowLoan.text_field_province_id")}
size="small"
selectType="province_id"
isLoading={isLoadingProvinceList}
errorEcured={errorProvinceList}
selectors={provinceList}
select={props.values.province_id}
handleChange={(event) => {
props.setFieldValue('province_id', event.target.value);
setProvinceID(event.target.value)
props.setFieldTouched("city_id", false, false);
props.setFieldValue("city_id", "")
}}
setFieldTouched={props.setFieldTouched}
error={props.touched.province_id && Boolean(props.errors.province_id)}
helperText={props.touched.province_id && props.errors.province_id}
onBlur={props.handleBlur("province_id")}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<SelectBox
name="city_id"
label={cityList.length === 0 ? `${t("ShowLoan.cityList_empty")}` : cityTextField}
size="small"
selectType="city_id"
disabled={cityList.length === 0}
selectors={cityList}
select={props.values.city_id}
handleChange={(event) => props.setFieldValue('city_id', event.target.value)}
setFieldTouched={props.setFieldTouched}
error={props.touched.city_id && Boolean(props.errors.city_id)}
helperText={props.touched.city_id && props.errors.city_id}
onBlur={props.handleBlur("city_id")}
/>
</Box>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
display: "flex",
justifyContent: "end"
}}
>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
sx={{
mt: 2,
width: "fit-content",
display: "flex",
}}
endIcon={<EditIcon/>}
disabled={props.isSubmitting}
>
{t("ShowLoan.button_submit")}
</Button>
</Box>
</StyledForm>
</Stack>
)}
</Formik>
<UpdateForm LoanDetails={LoanDetails} LoanId={query.id}/>
);
};

View File

@@ -1,4 +1,3 @@
import {Box, Chip, Divider} from "@mui/material";
import {useTranslations} from "next-intl";
import {CenterLayout, useUser} from "@witel/webapp-builder";
import ShowLoanForm from "@/components/dashboard/navgan/show/form";
@@ -9,13 +8,6 @@ const ShowLoan = () => {
return (
<CenterLayout>
<Box sx={{width: "80%", my: 2}}>
<Divider>
<Chip
label={t("ShowLoan.show_loan_page")}
/>
</Divider>
</Box>
<ShowLoanForm/>
</CenterLayout>
);

View File

@@ -43,6 +43,7 @@ function ButtonDatePicker(props) {
<DatePicker
slots={{field: ButtonField, ...props.slots}}
disableFuture
disabled={props.disabled}
slotProps={{
formik: props.formik,
field: {setOpen},
@@ -58,8 +59,7 @@ function ButtonDatePicker(props) {
);
}
export default function PickerWithButtonField({formik, error, helperText}) {
const [value, setValue] = useState(null);
export default function PickerWithButtonField({formik, disabled}) {
return (
<FormControl
variant={"outlined"}
@@ -69,16 +69,14 @@ export default function PickerWithButtonField({formik, error, helperText}) {
>
<LocalizationProvider dateAdapter={AdapterDateFnsJalali}>
<ButtonDatePicker
label={value == null ? null : moment(value)
label={formik.values.birthday
.locale("fa")
.format("YYYY/MM/DD")}
value={value}
value={formik.values.birthday.toDate()}
formik={formik}
disabled={disabled}
onChange={(newValue) => {
const formattedBirthday = moment(newValue).locale("fa").format("YYYY-MM-DD")
formik.setFieldValue("birthday", formattedBirthday)
setValue(newValue)
console.log(formattedBirthday)
formik.setFieldValue("birthday", moment(newValue))
}}
/>

View File

@@ -1,4 +1,4 @@
import {Box, Button, Drawer, FormHelperText, InputBase, Stack} from "@mui/material";
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";
@@ -123,39 +123,58 @@ const plate_words = [
const PlateNumber = ({formik, disabled}) => {
const t = useTranslations();
const [plateDrawer, setPlateDrawer] = useState(false);
const [selectedWordName, setSelectedWordName] = useState("الف");
const [selectedWordValue, setSelectedWordValue] = useState("");
const isErrorPlate = Boolean(formik.errors.plate_part1 || formik.errors.plate_part3 || formik.errors.plate_part4)
const isTouched = (formik.touched.plate_part1 || formik.touched.plate_part3 || formik.touched.plate_part4)
return (
<>
<Stack direction={'row'}
sx={{border: 1, overflow: 'hidden', borderColor: 'divider', borderRadius: 1}}>
<InputBase
type={'number'}
disabled={disabled}
sx={{
border: 1,
overflow: 'hidden',
borderColor: (isTouched && isErrorPlate) ? 'error.main' : 'divider',
borderRadius: 1
}}>
<TextField
name={'plate_part4'}
type={'tel'}
value={formik.values.plate_part4}
onInput={(event) => event.target.value.length <= 2 ? formik.setFieldValue("plate_part4", event.target.value) : null}
size={'small'}
placeholder={'xx'} sx={{flexGrow: 2}}
inputProps={{sx: {textAlign: 'center'}}}/>
<InputBase
type={'number'}
disabled={disabled}
size={'small'}
placeholder={'xx'} sx={{flexGrow: 2, "& fieldset": {border: 'none'}}}
inputProps={{sx: {textAlign: 'center'}}}
onChange={(event) => event.target.value.length <= 2 ? formik.setFieldValue("plate_part4", event.target.value) : null}
onBlur={formik.handleBlur}
error={formik.touched.plate_part4 && Boolean(formik.errors.plate_part4)}
/>
<TextField
name={'plate_part3'}
type={'tel'}
value={formik.values.plate_part3}
onInput={(event) => event.target.value.length <= 3 ? formik.setFieldValue("plate_part3", event.target.value) : null}
size={'small'} placeholder={'xxx'} sx={{
flexGrow: 3, borderLeft: 1, borderRadius: 0, borderColor: 'divider'
}} inputProps={{sx: {textAlign: 'center'}}}/>
size={'small'}
disabled={disabled}
placeholder={'xxx'}
sx={{
flexGrow: 3,
borderLeft: 1,
borderRadius: 0,
borderColor: 'divider',
"& fieldset": {border: 'none'}
}}
inputProps={{sx: {textAlign: 'center'}}}
onChange={(event) => event.target.value.length <= 3 ? formik.setFieldValue("plate_part3", event.target.value) : null}
onBlur={formik.handleBlur}
error={formik.touched.plate_part3 && Boolean(formik.errors.plate_part3)}
/>
<Box sx={{flexGrow: 1}}>
<Button
onClick={() => setPlateDrawer(true)}
disabled={disabled}
sx={{borderRadius: 0, borderColor: 'divider'}}
sx={{height: '100%', borderRadius: 0, borderColor: 'divider'}}
size={'small'}
data-selected-word={selectedWordValue}
data-selected-word={formik.values.plate_part2}
disabled={disabled}
fullWidth
>
{selectedWordName}
{plate_words.find(p => p.value === formik.values.plate_part2).name}
</Button>
</Box>
<Drawer
@@ -176,8 +195,6 @@ const PlateNumber = ({formik, disabled}) => {
<Button
key={item.id}
onClick={() => {
setSelectedWordName(item.name);
setSelectedWordValue(item.value);
formik.setFieldValue("plate_part2", item.value)
setPlateDrawer(false);
}}
@@ -191,22 +208,27 @@ const PlateNumber = ({formik, disabled}) => {
))}
</Box>
</Drawer>
<InputBase
type={'number'}
<TextField
name={'plate_part1'}
type={'tel'}
disabled={disabled}
value={formik.values.plate_part1}
onInput={(event) => event.target.value.length <= 2 ? formik.setFieldValue("plate_part1", event.target.value) : null}
size={'small'}
placeholder={'xx'}
sx={{flexGrow: 2}}
inputProps={{sx: {textAlign: 'center'}}}/>
sx={{flexGrow: 2, "& fieldset": {border: 'none'}}}
inputProps={{sx: {textAlign: 'center'}}}
onChange={(event) => event.target.value.length <= 2 ? formik.setFieldValue("plate_part1", event.target.value) : null}
onBlur={formik.handleBlur}
error={true}
/>
<Stack sx={{width: 24, borderLeft: 1, borderColor: 'divider'}}>
<Box sx={{flexGrow: 1, bgcolor: '#1ebc1e'}}></Box>
<Box sx={{flexGrow: 1, bgcolor: 'white'}}></Box>
<Box sx={{flexGrow: 1, bgcolor: '#f52121'}}></Box>
</Stack>
</Stack>
<FormHelperText>{t("error_message_plate_number")}</FormHelperText>
<FormHelperText
error={(isTouched && isErrorPlate)}>{(isTouched && isErrorPlate) ? `${t("LoanRequest.error_message_plate_number")}` : null}</FormHelperText>
</>
)

View File

@@ -1,9 +1,8 @@
import {Button} from "@mui/material";
import {useTranslations} from "next-intl";
import {useEffect} from "react";
import {SEND_OTP_TOKEN} from "../data/apiRoutes";
import {SEND_OTP_TOKEN} from "../data/apiRoutes";
import {useDirection, useRequest} from "@witel/webapp-builder";
import {SEND_OTP_TOKEN} from "@/core/data/apiRoutes";
const ResendToken = ({initialTimerValue, timer, setTimer, PhoneNumber, disabled}) => {
const t = useTranslations();

View File

@@ -9,23 +9,22 @@ function SelectBox({
handleChange,
error,
onBlur,
schema,
disabled,
helperText,
isLoading,
errorEcured,
variant
variant = "outlined"
}) {
const t = useTranslations();
return (
<FormControl
disabled={disabled || false}
variant={variant || "outlined"}
margin="normal"
variant={variant}
fullWidth
size="small"
error={error}
sx={{mt: 0}}
>
<InputLabel>{label}</InputLabel>
<Select
@@ -38,16 +37,15 @@ function SelectBox({
>
{isLoading ? (
<MenuItem
sx={{color: "primary.main"}}>{t("LoanRequest.text_field_loading_provinces_list")}</MenuItem>
<MenuItem sx={{color: "primary.main"}}>{t("text_field_loading")}</MenuItem>
) : errorEcured ? (
<MenuItem sx={{color: "secondary.main"}}>
{t("LoanRequest.text_field_error_fetching_provinces")}
{t("text_field_error_fetching")}
</MenuItem>
) : (
selectors.map((selector) => (
<MenuItem key={selector.id} value={selector.value}>
{selector.name}
<MenuItem key={selector.id} value={selector[schema.value]}>
{selector[schema.name]}
</MenuItem>
))
)}

View File

@@ -14,6 +14,11 @@ 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_CITIES_LIST = BASE_URL + "/cities";
export const GET_EDUCATIONS_LIST = BASE_URL + "/education";
export const GET_OCCUPATIONS_LIST = BASE_URL + "/occupations";
export const GET_LOAN_DETAILS = BASE_URL + "/navgan/loan/details/"
export const UPDATE_LOAN = BASE_URL + "/navgan/loan/update/"

View File

@@ -13,13 +13,13 @@ const DashboardLayout = (props) => {
return (
<>
<DashboardLayoutPure
middlewares={{list: [UserInfo], props: {...middlewaresProps,loginUrl:'/login'}}}
middlewares={{list: [UserInfo], props: {...middlewaresProps, loginUrl: '/login'}}}
user_introduction={user.phone_number}
headerProfileItems={headerProfileItems}
headerSubtitle={`${t('today')} ${moment().locale('fa').format('LL')}`}
sidebarMenu={sidebarMenu}
urlNotification={GET_SIDEBAR_NOTIFICATION}
BC_segmentsToRemove={['navgan']}
BC_segmentsToRemove={['navgan', '[id]']}
{...props}
/>
</>

View File

@@ -5,16 +5,16 @@ import {GET_CITIES_LIST} from "@/core/data/apiRoutes";
const useCities = () => {
const t = useTranslations();
const [provinceID, setProvinceID] = useState(null);
const [isLoadingCityList, setIsLoadingCityList] = useState(false)
const [provinceID, setProvinceID] = useState(null)
const [cityList, setCityList] = useState([]);
const [cityTextField, setCityTextField] = useState(t("LoanRequest.city_id"));
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("LoanRequest.text_field_loading_cities_list"))
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;
@@ -24,14 +24,15 @@ const useCities = () => {
value: city.id,
}));
setCityList(formattedData);
setCityTextField(t("LoanRequest.text_field_city_id"))
setIsLoadingCityList(false);
setIsLoadingCityList(false)
setCityTextField(t("text_field_city_id"))
}).catch(() => {
setCityTextField(t("LoanRequest.text_field_error_fetching_cities"))
setIsLoadingCityList(false)
setCityTextField(t("text_field_error_fetching_cities"))
});
}, [provinceID])
return {cityList, cityTextField, setProvinceID, isLoadingCityList}
return {cityTextField, cityList, setProvinceID, isLoadingCityList}
}
export default useCities

View File

@@ -0,0 +1,29 @@
import {GET_EDUCATIONS_LIST} from "@/core/data/apiRoutes";
import {useRequest} from "@witel/webapp-builder";
import {useEffect, useState} from "react";
const useEducations = () => {
const [isLoadingEducationsList, setIsLoadingEducationsList] = useState(false)
const [errorEducationsList, setErrorEducationsList] = useState(false)
const [educationsList, setEducationsList] = useState([])
const requestServer = useRequest({auth: true, notification: false})
useEffect(() => {
setIsLoadingEducationsList(true)
requestServer(GET_EDUCATIONS_LIST, 'get', {auth: true, notification: false}).then(({data}) => {
setIsLoadingEducationsList(false)
setEducationsList(data.data);
}).catch(() => {
setIsLoadingEducationsList(false)
setErrorEducationsList(true)
})
}, [])
return {
educationsList,
isLoadingEducationsList,
errorEducationsList
}
};
export default useEducations;

View File

@@ -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;