update packages and bring some of fields to show loan page

This commit is contained in:
2023-12-19 10:25:10 +03:30
parent 80f9ebb03f
commit 79152b690b
12 changed files with 507 additions and 203 deletions

View File

@@ -16,9 +16,11 @@
"@mui/icons-material": "^5.11.16",
"@mui/lab": "^5.0.0-alpha.152",
"@mui/material": "^5.12.0",
"@witel/webapp-builder": "^1.0.6",
"@mui/x-date-pickers": "^6.18.5",
"@witel/webapp-builder": "^1.1.0",
"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",
@@ -43,4 +45,4 @@
"@faker-js/faker": "^7.6.0",
"eslint-config-next": "^13.3.0"
}
}
}

View File

@@ -67,7 +67,8 @@
"dashboard": "داشبورد",
"add-request-loan": "درخواست وام",
"followUp-loan": "پیگیری درخواست",
"edit-request-loan": "ویرایش درخواست وام"
"edit-request-loan": "ویرایش درخواست وام",
"show": "نمایش"
},
"Authorization": {
"typography_your_login_is_valid_and_you_do_not_need_to_login_again": "شما دسترسی لازم به این صفحه را دارید نیاز به ورود مجدد نیست.",
@@ -179,26 +180,38 @@
"error_message_city_id": "لطفا شهر خود را وارد کنید!",
"add_loan_request_permission": "اکنون امکان ثبت درخواست جدید برای شما مقدور نیست"
},
"showLoan": {
"show_loan_page": "نمایش وام",
"ShowLoan": {
"show_loan_page": "نمایش وام | ناوگان",
"text_field_national_code": "کد ملی",
"text_field_postal_code": "کد پستی",
"text_field_national_card_serial_num": "سریال پشت کارت ملی",
"text_field_address": "آدرس",
"text_field_birth_date": "تاریخ تولد",
"text_field_navgan_id": "کد ناوگان",
"text_field_enter_your_national_code": "کد ملی خود را وارد کنید",
"text_field_enter_your_postal_code": "کد پستی خود را وارد کنید",
"text_field_enter_your_national_card_serial_num": "سریال پشت کارت ملی خود را وارد کنید",
"text_field_enter_your_address": "آدرس خود را وارد کنید",
"text_field_enter_your_birth_date": "تاریخ تولد خود را وارد کنید",
"text_field_enter_your_navgan_id": "کد ناوگان خود را وارد کنید",
"error_message_national_code": "لطفا کد ملی خود را وارد کنید!",
"error_message_postal_code": "لطفا کد پستی خود را وارد کنید!",
"error_message_national_card_serial_num": "لطفا سریال پشت کارت ملی خود را وارد کنید!",
"error_message_address": "لطفا آدرس خود را وارد کنید!",
"error_message_birth_date": "لطفا تاریخ تولد خود را وارد کنید!",
"error_message_navgan_id": "لطفا کد ناوگان خود را وارد کنید!",
"text_field_province_id": "استان",
"text_field_owner_full_name": "نام کامل مالک",
"text_field_navgan_type": "نوع ناوگان",
"text_field_vehicle_type": "نوع وسیله",
"text_field_enter_your_national_code": "کد ملی را وارد کنید",
"text_field_enter_your_postal_code": "کد پستی را وارد کنید",
"text_field_enter_your_national_card_serial_num": "سریال پشت کارت ملی را وارد کنید",
"text_field_enter_your_address": "آدرس را وارد کنید",
"text_field_enter_your_birth_date": "تاریخ تولد را وارد کنید",
"text_field_enter_your_navgan_id": "کد ناوگان را وارد کنید",
"text_field_enter_your_owner_full_name": "نام کامل مالک را وارد کنید",
"error_message_national_code": "لطفا کد ملی را وارد کنید!",
"error_message_postal_code": "لطفا کد پستی را وارد کنید!",
"error_message_national_card_serial_num": "لطفا سریال پشت کارت ملی را وارد کنید!",
"error_message_address": "لطفا آدرس را وارد کنید!",
"error_message_birth_date": "لطفا تاریخ تولد را وارد کنید!",
"error_message_navgan_id": "لطفا کد ناوگان را وارد کنید!",
"error_message_province_id": "لطفا استان را وارد کنید!",
"error_message_city_id": "لطفا شهر خود را وارد کنید!",
"error_message_owner_full_name": "لطفا نام کامل مالک را وارد کنید!",
"error_message_navgan_type": "لطفا نوع ناوگان را وارد کنید!",
"error_message_vehicle_type": "لطفا نوع وسیله را وارد کنید!",
"error_message_fixed_number": "لطفا تلفن ثابت را وارد کنید!",
"cityList_empty": "شهر یافت نشد",
"button_submit": "ویرایش"
},
"EditLoanRequest": {

View File

@@ -1,29 +1,25 @@
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";
import {CenterLayout, useUser} from "@witel/webapp-builder";
const LoanRequestComponent = () => {
const t = useTranslations();
const {user} = useUser();
return (
<DashboardLayouts>
<CenterLayout>
<Box sx={{width: "80%", my: 2}}>
<Divider>
<Chip
label={`${t("LoanRequest.loan_request_page")} | ${
user.type_name
}`}
/>
</Divider>
</Box>
<AddFormComponent/>
</CenterLayout>
</DashboardLayouts>
<CenterLayout>
<Box sx={{width: "80%", my: 2}}>
<Divider>
<Chip
label={`${t("LoanRequest.loan_request_page")} | ${
user.type_name
}`}
/>
</Divider>
</Box>
<AddFormComponent/>
</CenterLayout>
);
};

View File

@@ -5,9 +5,16 @@ 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 = {
@@ -16,18 +23,38 @@ const ShowLoanForm = () => {
national_card_serial_num: "0312288875",
address: "تهران - ثنایی - مطهری ساختمان مهتاب",
birth_date: "10/25/44",
navgan_id: "14575"
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
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")),
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
@@ -40,6 +67,12 @@ const ShowLoanForm = () => {
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
@@ -82,8 +115,8 @@ const ShowLoanForm = () => {
disabled
variant="standard"
size="small"
label={t("showLoan.text_field_national_code")}
placeholder={t("showLoan.text_field_enter_your_national_code")}
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
@@ -104,9 +137,9 @@ const ShowLoanForm = () => {
disabled
variant="standard"
size="small"
label={t("showLoan.text_field_birth_date")}
label={t("ShowLoan.text_field_birth_date")}
placeholder={t(
"showLoan.text_field_enter_your_birth_date"
"ShowLoan.text_field_enter_your_birth_date"
)}
type={"text"}
error={!!(props.touched.birth_date && props.errors.birth_date)}
@@ -117,6 +150,12 @@ const ShowLoanForm = () => {
: 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={{
@@ -132,9 +171,9 @@ const ShowLoanForm = () => {
disabled
variant="standard"
size="small"
label={t("showLoan.text_field_national_card_serial_num")}
label={t("ShowLoan.text_field_national_card_serial_num")}
placeholder={t(
"showLoan.text_field_enter_your_national_card_serial_num"
"ShowLoan.text_field_enter_your_national_card_serial_num"
)}
type={"text"}
error={!!(props.touched.national_card_serial_num && props.errors.national_card_serial_num)}
@@ -147,6 +186,115 @@ const ShowLoanForm = () => {
/>
</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",
@@ -169,8 +317,8 @@ const ShowLoanForm = () => {
name="address"
variant="outlined"
size="small"
label={t("showLoan.text_field_address")}
placeholder={t("showLoan.text_field_enter_your_address")}
label={t("ShowLoan.text_field_address")}
placeholder={t("ShowLoan.text_field_enter_your_address")}
type={"text"}
error={!!(props.touched.address && props.errors.address)}
fullWidth
@@ -190,9 +338,9 @@ const ShowLoanForm = () => {
name="postal_code"
variant="outlined"
size="small"
label={t("showLoan.text_field_postal_code")}
label={t("ShowLoan.text_field_postal_code")}
placeholder={t(
"showLoan.text_field_enter_your_postal_code"
"ShowLoan.text_field_enter_your_postal_code"
)}
type={"text"}
error={!!(props.touched.postal_code && props.errors.postal_code)}
@@ -217,9 +365,9 @@ const ShowLoanForm = () => {
name="navgan_id"
variant="outlined"
size="small"
label={t("showLoan.text_field_navgan_id")}
label={t("ShowLoan.text_field_navgan_id")}
placeholder={t(
"showLoan.text_field_enter_your_navgan_id"
"ShowLoan.text_field_enter_your_navgan_id"
)}
type={"text"}
error={!!(props.touched.navgan_id && props.errors.navgan_id)}
@@ -248,22 +396,47 @@ const ShowLoanForm = () => {
width: "100%",
}}
>
<Field
<SelectBox
name="province_id"
label={t("LoanRequest.text_field_province_id")} // t("LoanRequest.text_field_enter_your_province")
label={t("ShowLoan.text_field_province_id")}
size="small"
selectType="province_id"
component={SelectBox}
isLoading={isLoadingProvinceList}
errorEcured={errorProvinceList}
selectors={provinceList}
select={props.values.province_id}
setFieldValue={props.setFieldValue}
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 && props.errors.province_id)
}
helperText={
props.touched.province_id ? props.errors.province_id : null
}
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>
@@ -287,7 +460,7 @@ const ShowLoanForm = () => {
endIcon={<EditIcon/>}
disabled={props.isSubmitting}
>
{t("showLoan.button_submit")}
{t("ShowLoan.button_submit")}
</Button>
</Box>
</StyledForm>

View File

@@ -12,9 +12,7 @@ const ShowLoan = () => {
<Box sx={{width: "80%", my: 2}}>
<Divider>
<Chip
label={`${t("showLoan.show_loan_page")} | ${
user.type_name
}`}
label={t("ShowLoan.show_loan_page")}
/>
</Divider>
</Box>

View File

@@ -0,0 +1,89 @@
import * as React from 'react';
import {useState} from 'react';
import Button from '@mui/material/Button';
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
import {LocalizationProvider} from '@mui/x-date-pickers/LocalizationProvider';
import {DatePicker} from '@mui/x-date-pickers/DatePicker';
import {useTranslations} from "next-intl";
import moment from "jalali-moment";
import {FormControl, FormHelperText} from "@mui/material";
function ButtonField(props) {
const t = useTranslations();
const {
setOpen,
label,
id,
disabled,
InputProps: {ref} = {},
inputProps: {'aria-label': ariaLabel} = {},
} = props;
return (
<Button
sx={{width: "100%", padding: 0.8}}
variant="outlined"
color={props.slotProps.formik.touched.birthday && Boolean(props.slotProps.formik.errors.birthday) ? "error" : "primary"}
id={id}
disabled={disabled}
ref={ref}
aria-label={ariaLabel}
onClick={() => setOpen?.((prev) => !prev)}
>
{label ? `${t("birthday")}: ${label}` : `${t("birthday")}`}
</Button>
);
}
function ButtonDatePicker(props) {
const t = useTranslations();
const [open, setOpen] = useState(false);
return (
<DatePicker
slots={{field: ButtonField, ...props.slots}}
disableFuture
slotProps={{
formik: props.formik,
field: {setOpen},
textField: {
helperText: props.formik.errors.birthday ? `${t("birthday_error")}` : null
}
}}
{...props}
open={open}
onClose={() => setOpen(false)}
onOpen={() => setOpen(true)}
/>
);
}
export default function PickerWithButtonField({formik, error, helperText}) {
const [value, setValue] = useState(null);
return (
<FormControl
variant={"outlined"}
fullWidth
size="small"
error={true}
>
<LocalizationProvider dateAdapter={AdapterDateFnsJalali}>
<ButtonDatePicker
label={value == null ? null : moment(value)
.locale("fa")
.format("YYYY/MM/DD")}
value={value}
formik={formik}
onChange={(newValue) => {
const formattedBirthday = moment(newValue).locale("fa").format("YYYY-MM-DD")
formik.setFieldValue("birthday", formattedBirthday)
setValue(newValue)
console.log(formattedBirthday)
}}
/>
</LocalizationProvider>
<FormHelperText>{formik.touched.birthday && formik.errors.birthday}</FormHelperText>
</FormControl>
);
}

View File

@@ -1,4 +1,4 @@
import {Box, Button, Drawer, FormHelperText, TextField, Typography} from "@mui/material";
import {Box, Button, Drawer, FormHelperText, InputBase, Stack} from "@mui/material";
import {useTranslations} from "next-intl";
import AccessibleIcon from '@mui/icons-material/Accessible';
import {useState} from "react";
@@ -120,7 +120,7 @@ const plate_words = [
name: <AccessibleIcon/>
},
]
const PlateNumber = ({formik}) => {
const PlateNumber = ({formik, disabled}) => {
const t = useTranslations();
const [plateDrawer, setPlateDrawer] = useState(false);
const [selectedWordName, setSelectedWordName] = useState("الف");
@@ -128,102 +128,84 @@ const PlateNumber = ({formik}) => {
return (
<>
<Box sx={{
display: "flex",
width: "fit-content",
flexDirection: "row",
alignItems: "end",
justifyContent: "end",
gap: 0.75
}}>
<Box sx={{display: "flex", flexDirection: "column", textAlign: "center"}}>
<Typography variant="caption" sx={{fontWeight: 500}}>
ایران
</Typography>
<TextField
sx={{width: "50px"}}
name="plate_part4"
variant="outlined"
size="small"
type='number'
onChange={formik.handleChange}
onBlur={formik.handleBlur("plate_part4")}
/>
</Box>
<Box>
<TextField
sx={{width: "70px"}}
name="plate_part3"
variant="outlined"
size="small"
type='number'
onChange={formik.handleChange}
onBlur={formik.handleBlur("plate_part3")}
/>
</Box>
<Box>
{/*<TextField*/}
{/* sx={{width: "50px"}}*/}
{/* name="plate_part2"*/}
{/* variant="outlined"*/}
{/* type={'number'}*/}
{/* size="small"*/}
{/* onChange={formik.handleChange}*/}
{/* onBlur={formik.handleBlur("plate_part1")}*/}
{/*/>*/}
<Button onClick={() => setPlateDrawer(true)}
sx={{
borderColor: "divider",
fontSize: "16px"
}}
variant="outlined"
data-selected-word={selectedWordValue}
>{selectedWordName}</Button>
<Drawer
anchor={"bottom"}
open={plateDrawer}
onClose={() => setPlateDrawer(false)}
<Stack direction={'row'}
sx={{border: 1, overflow: 'hidden', borderColor: 'divider', borderRadius: 1}}>
<InputBase
type={'number'}
disabled={disabled}
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}
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'}}}/>
<Box sx={{flexGrow: 1}}>
<Button
onClick={() => setPlateDrawer(true)}
disabled={disabled}
sx={{borderRadius: 0, borderColor: 'divider'}}
size={'small'}
data-selected-word={selectedWordValue}
fullWidth
>
<Box sx={{
display: "flex",
flexWrap: "wrap",
mx: "auto",
my: 2,
gap: 2,
width: "60%",
justifyContent: "center"
}}>
{plate_words.map((item) => (
<Button
key={item.id}
onClick={() => {
setSelectedWordName(item.name);
setSelectedWordValue(item.value);
setPlateDrawer(false);
}}
sx={{
width: "fit-content"
}}
variant="contained"
>
{item.name}
</Button>
))}
</Box>
</Drawer>
{selectedWordName}
</Button>
</Box>
<Box>
<TextField
sx={{width: "50px"}}
name="plate_part1"
variant="outlined"
type='number'
size="small"
onChange={formik.handleChange}
onBlur={formik.handleBlur("plate_part1")}
/>
</Box>
</Box>
<Drawer
anchor={"bottom"}
open={plateDrawer}
onClose={() => setPlateDrawer(false)}
>
<Box sx={{
display: "flex",
flexWrap: "wrap",
mx: "auto",
my: 2,
gap: 2,
width: "60%",
justifyContent: "center"
}}>
{plate_words.map((item) => (
<Button
key={item.id}
onClick={() => {
setSelectedWordName(item.name);
setSelectedWordValue(item.value);
formik.setFieldValue("plate_part2", item.value)
setPlateDrawer(false);
}}
sx={{
width: "fit-content"
}}
variant="contained"
>
{item.name}
</Button>
))}
</Box>
</Drawer>
<InputBase
type={'number'}
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'}}}/>
<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>
</>

View File

@@ -1,52 +1,60 @@
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,
disabled,
helperText,
isLoading,
errorEcured,
variant
}) {
const t = useTranslations();
const selectId = String(select);
const handleChange = (event) => {
setFieldValue(selectType, event.target.value);
};
const handleBlur = () => {
setFieldTouched(select, true);
};
return (
<FormControl
variant="outlined"
disabled={disabled || false}
variant={variant || "outlined"}
margin="normal"
fullWidth
size="small"
error={error}
sx={{mt: 0}}
>
<InputLabel id="language-label">{label}</InputLabel>
<InputLabel>{label}</InputLabel>
<Select
labelId="language-label"
id={selectId}
name={selectId}
label={label}
name={name}
size="small"
value={select}
value={isLoading ? "" : select}
onChange={handleChange}
label="Language"
onBlur={handleBlur}
onBlur={onBlur}
>
{selectors.map((selector) => (
<MenuItem key={selector.id} value={selector.value}>
{selector.name}
{isLoading ? (
<MenuItem
sx={{color: "primary.main"}}>{t("LoanRequest.text_field_loading_provinces_list")}</MenuItem>
) : errorEcured ? (
<MenuItem sx={{color: "secondary.main"}}>
{t("LoanRequest.text_field_error_fetching_provinces")}
</MenuItem>
))}
) : (
selectors.map((selector) => (
<MenuItem key={selector.id} value={selector.value}>
{selector.name}
</MenuItem>
))
)}
</Select>
<FormHelperText>{helperText}</FormHelperText>
</FormControl>
);
}
export default SelectBox;
export default SelectBox;

View File

@@ -14,5 +14,6 @@ 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"

View File

@@ -0,0 +1,37 @@
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 [isLoadingCityList, setIsLoadingCityList] = useState(false)
const [cityList, setCityList] = useState([]);
const [cityTextField, setCityTextField] = useState(t("LoanRequest.city_id"));
const requestServer = useRequest({auth: true, notification: false})
useEffect(() => {
if (provinceID === null) return
setIsLoadingCityList(true);
setCityTextField(t("LoanRequest.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);
setCityTextField(t("LoanRequest.text_field_city_id"))
setIsLoadingCityList(false);
}).catch(() => {
setCityTextField(t("LoanRequest.text_field_error_fetching_cities"))
});
}, [provinceID])
return {cityList, cityTextField, setProvinceID, isLoadingCityList}
}
export default useCities

View File

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

View File

@@ -12,7 +12,7 @@ export async function getServerSideProps({req, locale}) {
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
title: "showLoan.show_loan_page",
title: "ShowLoan.show_loan_page",
isBot,
locale,
layout: {name: 'DashboardLayout'}