recode and add editor config

This commit is contained in:
Amirhossein Mahmoodi
2023-07-31 15:27:34 +03:30
parent 8a3e82bb9a
commit 51228f3c02
88 changed files with 5121 additions and 4138 deletions

View File

@@ -1,7 +1,7 @@
import DashboardLayouts from "@/layouts/dashboardLayouts";
const DashboardFirstComponent = () => {
return <DashboardLayouts></DashboardLayouts>;
return <DashboardLayouts></DashboardLayouts>;
};
export default DashboardFirstComponent;

View File

@@ -2,121 +2,122 @@ import DashboardLayouts from "@/layouts/dashboardLayouts";
import useUser from "@/lib/app/hooks/useUser";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import {
Avatar, Card,
CardActions,
CardContent,
CardHeader,
Collapse,
Grid,
IconButton,
Stack,
Typography
Avatar,
Card,
CardActions,
CardContent,
CardHeader,
Collapse,
Grid,
IconButton,
Stack,
Typography
} from "@mui/material";
import { styled } from "@mui/material/styles";
import { useTranslations } from "next-intl";
import { useState } from "react";
import {styled} from "@mui/material/styles";
import {useTranslations} from "next-intl";
import {useState} from "react";
const ExpandMore = styled((props) => {
const { expand, ...other } = props;
return <IconButton {...other} />;
})(({ theme, expand }) => ({
transform: !expand ? "rotate(0deg)" : "rotate(180deg)",
marginLeft: "auto",
transition: theme.transitions.create("transform", {
duration: theme.transitions.duration.shortest,
}),
const {expand, ...other} = props;
return <IconButton {...other} />;
})(({theme, expand}) => ({
transform: !expand ? "rotate(0deg)" : "rotate(180deg)",
marginLeft: "auto",
transition: theme.transitions.create("transform", {
duration: theme.transitions.duration.shortest,
}),
}));
const data = [
{
name: "جان دو",
date: "۱۳۹۹/۰۴/۲۵",
description:
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.",
},
{
name: "جین اسمیت",
date: "۱۳۹۹/۰۴/۲۶",
description: "نُلا ویته الیت لیبرو آ، آ فارِترا آوگوه.",
},
{
name: "مایک جانسون",
date: "۱۳۹۹/۰۴/۲۷",
description:
"دوئیس مولیس، است نُن کُمُدو لُکتوس، نیسی ارات پورتیتور لیگولا.",
},
{
name: "جان دو",
date: "۱۳۹۹/۰۴/۲۵",
description:
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.",
},
{
name: "جین اسمیت",
date: "۱۳۹۹/۰۴/۲۶",
description: "نُلا ویته الیت لیبرو آ، آ فارِترا آوگوه.",
},
{
name: "مایک جانسون",
date: "۱۳۹۹/۰۴/۲۷",
description:
"دوئیس مولیس، است نُن کُمُدو لُکتوس، نیسی ارات پورتیتور لیگولا.",
},
];
const DashboardLoanFollowUpComponent = () => {
const t = useTranslations();
const { token } = useUser();
const t = useTranslations();
const {token} = useUser();
const [expanded, setExpanded] = useState([]);
const [expanded, setExpanded] = useState([]);
const handleExpandClick = (index) => {
setExpanded((prevExpanded) => {
const newExpanded = [...prevExpanded];
newExpanded[index] = !newExpanded[index];
return newExpanded;
});
};
const handleExpandClick = (index) => {
setExpanded((prevExpanded) => {
const newExpanded = [...prevExpanded];
newExpanded[index] = !newExpanded[index];
return newExpanded;
});
};
return (
<DashboardLayouts>
<Stack
spacing={2}
sx={{
p: 4,
width: "100%",
}}
>
<Grid
container
columnSpacing={2}
rowSpacing={2}
sx={{ alignItems: "start", justifyContent: "center" }}
>
{data.map((item, index) => (
<Grid item xs={12} md={6} lg={4} key={index}>
<Card sx={{ width: "100%" }}>
<CardHeader
avatar={
<Avatar
sx={{ bgcolor: "primary.main" }}
aria-label="recipe"
></Avatar>
}
title={item.name}
subheader={item.date}
/>
<CardContent>
<Typography variant="body2" color="text.secondary">
متن تست
</Typography>
</CardContent>
<CardActions disableSpacing>
<ExpandMore
expand={expanded[index]}
onClick={() => handleExpandClick(index)}
aria-expanded={expanded[index]}
aria-label="show more"
>
<ExpandMoreIcon />
</ExpandMore>
</CardActions>
<Collapse in={expanded[index]} timeout="auto" unmountOnExit>
<CardContent>
<Typography paragraph>اطلاعات تکمیلی:</Typography>
<Typography paragraph>{item.description}</Typography>
</CardContent>
</Collapse>
</Card>
</Grid>
))}
</Grid>
</Stack>
</DashboardLayouts>
);
return (
<DashboardLayouts>
<Stack
spacing={2}
sx={{
p: 4,
width: "100%",
}}
>
<Grid
container
columnSpacing={2}
rowSpacing={2}
sx={{alignItems: "start", justifyContent: "center"}}
>
{data.map((item, index) => (
<Grid item xs={12} md={6} lg={4} key={index}>
<Card sx={{width: "100%"}}>
<CardHeader
avatar={
<Avatar
sx={{bgcolor: "primary.main"}}
aria-label="recipe"
></Avatar>
}
title={item.name}
subheader={item.date}
/>
<CardContent>
<Typography variant="body2" color="text.secondary">
متن تست
</Typography>
</CardContent>
<CardActions disableSpacing>
<ExpandMore
expand={expanded[index]}
onClick={() => handleExpandClick(index)}
aria-expanded={expanded[index]}
aria-label="show more"
>
<ExpandMoreIcon/>
</ExpandMore>
</CardActions>
<Collapse in={expanded[index]} timeout="auto" unmountOnExit>
<CardContent>
<Typography paragraph>اطلاعات تکمیلی:</Typography>
<Typography paragraph>{item.description}</Typography>
</CardContent>
</Collapse>
</Card>
</Grid>
))}
</Grid>
</Stack>
</DashboardLayouts>
);
};
export default DashboardLoanFollowUpComponent;

View File

@@ -2,490 +2,487 @@ 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 {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 {Box, Button, Stack, TextField} from "@mui/material";
import axios from "axios";
import { Field, Formik } from "formik";
import { useTranslations } from "next-intl";
import { useEffect, useState } from "react";
import {Field, Formik} from "formik";
import {useTranslations} from "next-intl";
import {useEffect, useState} from "react";
import * as Yup from "yup";
const NavyForm = () => {
const t = useTranslations();
const { directionApp } = useDirection();
const { token } = useUser();
const t = useTranslations();
const {directionApp} = useDirection();
const {token} = useUser();
// 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(directionApp, t, error.response);
});
}, []);
// end get province list
// 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(directionApp, 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);
// 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
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: "",
vehicle_type: "",
plate_number: "",
province: "",
navgan_id: "",
national_code: "",
shenasname_id: "",
national_card_img: null,
shenasname_img: null,
};
// end initial values
// initial values
const initialValues = {
name: "",
phone_number: "",
vehicle_type: "",
plate_number: "",
province: "",
navgan_id: "",
national_code: "",
shenasname_id: "",
national_card_img: null,
shenasname_img: null,
};
// end initial values
// validation
const validationSchema = Yup.object().shape({
name: Yup.string().required(t("LoanRequest.error_message_required")),
phone_number: Yup.string().required(
t("LoanRequest.error_message_required")
),
vehicle_type: Yup.string().required(
t("LoanRequest.error_message_required")
),
plate_number: Yup.string().required(
t("LoanRequest.error_message_required")
),
navgan_id: Yup.string().required(t("LoanRequest.error_message_required")),
province: Yup.string().required(t("LoanRequest.error_message_required")),
national_code: Yup.string().required(
t("LoanRequest.error_message_required")
),
shenasname_id: Yup.string().required(
t("LoanRequest.error_message_required")
),
});
// end validation
// validation
const validationSchema = Yup.object().shape({
name: Yup.string().required(t("LoanRequest.error_message_required")),
phone_number: Yup.string().required(
t("LoanRequest.error_message_required")
),
vehicle_type: Yup.string().required(
t("LoanRequest.error_message_required")
),
plate_number: Yup.string().required(
t("LoanRequest.error_message_required")
),
navgan_id: Yup.string().required(t("LoanRequest.error_message_required")),
province: Yup.string().required(t("LoanRequest.error_message_required")),
national_code: Yup.string().required(
t("LoanRequest.error_message_required")
),
shenasname_id: Yup.string().required(
t("LoanRequest.error_message_required")
),
});
// end validation
// submit
const handleSubmit = async (values, props) => {
Notifications(directionApp, 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);
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);
// submit
const handleSubmit = async (values, props) => {
Notifications(directionApp, 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);
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);
await axios
.post(SEND_LOAN_REQUEST_NAVGAN, formData, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "multipart/form-data",
},
})
.then(function (response) {
Notifications(directionApp, t, response);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
// end submit
await axios
.post(SEND_LOAN_REQUEST_NAVGAN, formData, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "multipart/form-data",
},
})
.then(function (response) {
Notifications(directionApp, t, response);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
// end submit
return (
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Stack
spacing={2}
sx={{
p: 1,
width: "100%",
}}
return (
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
<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="name"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_name")}
placeholder={t("LoanRequest.text_field_enter_your_name")}
type={"text"}
error={props.touched.name && props.errors.name ? true : false}
fullWidth
helperText={props.touched.name ? props.errors.name : null}
/>
</Box>
<Box
sx={{
mx: { xs: 0, sm: 2 },
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{ width: "100%" }}
name="phone_number"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_phone_number")}
placeholder={t(
"LoanRequest.text_field_enter_your_phone_number"
)}
type={"text"}
error={
props.touched.phone_number && props.errors.phone_number
? true
: false
}
fullWidth
helperText={
props.touched.phone_number
? props.errors.phone_number
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: { xs: "column", sm: "row" },
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: { xs: 0, sm: 2 },
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{ width: "100%" }}
name="vehicle_type"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_vehicle_type")}
placeholder={t(
"LoanRequest.text_field_enter_your_vehicle_type"
)}
type={"text"}
error={
props.touched.vehicle_type && props.errors.vehicle_type
? true
: false
}
fullWidth
helperText={
props.touched.vehicle_type
? props.errors.vehicle_type
: null
}
/>
</Box>
<Box
sx={{
mx: { xs: 0, sm: 2 },
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{ width: "100%" }}
name="plate_number"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_plate_number")}
placeholder={t(
"LoanRequest.text_field_enter_your_plate_number"
)}
type={"text"}
error={
props.touched.plate_number && props.errors.plate_number
? true
: false
}
fullWidth
helperText={
props.touched.plate_number
? props.errors.plate_number
: null
}
/>
</Box>
<Box
sx={{
mx: { xs: 0, sm: 2 },
my: 2,
width: "100%",
}}
>
<Field
name="province"
label={t("LoanRequest.text_field_province")} // t("LoanRequest.text_field_enter_your_province")
size="small"
selectType="province"
component={SelectBox}
selectors={provinceList}
select={props.values.province}
setFieldValue={props.setFieldValue}
setFieldTouched={props.setFieldTouched}
error={
props.touched.gender && props.errors.province ? true : false
}
helperText={
props.touched.gender ? props.errors.province : null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: { xs: "column", sm: "row" },
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: { xs: 0, sm: 2 },
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{ width: "100%" }}
name="navgan_id"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_navgan_id")}
placeholder={t("LoanRequest.text_field_enter_your_navgan_id")}
type={"text"}
error={
props.touched.navgan_id && props.errors.navgan_id
? true
: false
}
fullWidth
helperText={
props.touched.navgan_id ? props.errors.navgan_id : null
}
/>
</Box>
<Box
sx={{
mx: { xs: 0, sm: 2 },
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{ width: "100%" }}
name="national_code"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_national_code")}
placeholder={t(
"LoanRequest.text_field_enter_your_national_code"
)}
type={"text"}
error={
props.touched.national_code && props.errors.national_code
? true
: false
}
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="shenasname_id"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_shenasname_id")}
placeholder={t(
"LoanRequest.text_field_enter_your_shenasname_id"
)}
type={"text"}
error={
props.touched.shenasname_id && props.errors.shenasname_id
? true
: false
}
fullWidth
helperText={
props.touched.shenasname_id
? props.errors.shenasname_id
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: { xs: "column", sm: "row" },
alignItems: "center",
justifyContent: "space-around",
width: "100%",
}}
>
<UploadSystem
selectedImage={selectedImageShenasname}
handleUploadChange={(e) =>
handleUploadChangeShenasname(e, props.setFieldValue)
}
setselectedImage={setSelectedImageShenasname}
setFieldValue={props.setFieldValue}
fieldname="shenasname_img"
fileType={fileTypeShenasname}
fileName={fileNameShenasname}
imageAlt={t("app_name")}
imageSize={[300 /*width*/, 150 /*height*/]}
label={t("LoanRequest.file_field_shenasname_image")}
/>
<UploadSystem
selectedImage={selectedImageNationalCard}
handleUploadChange={(e) =>
handleUploadChangeNationalCard(e, props.setFieldValue)
}
setselectedImage={setSelectedImageNationalCard}
setFieldValue={props.setFieldValue}
fieldname="national_card_img"
fileType={fileTypeNationalCard}
fileName={fileNameNationalCard}
imageAlt={t("app_name")}
imageSize={[300 /*width*/, 150 /*height*/]}
label={t("LoanRequest.file_field_national_card_image")}
/>
</Box>
<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"
endIcon={<DataSaverOnIcon />}
disabled={props.isSubmitting ? true : false}
>
{t("LoanRequest.button_submit")}
</Button>
</Box>
</StyledForm>
</Stack>
)}
</Formik>
);
{(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="name"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_name")}
placeholder={t("LoanRequest.text_field_enter_your_name")}
type={"text"}
error={props.touched.name && props.errors.name ? true : false}
fullWidth
helperText={props.touched.name ? props.errors.name : null}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="phone_number"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_phone_number")}
placeholder={t(
"LoanRequest.text_field_enter_your_phone_number"
)}
type={"text"}
error={
props.touched.phone_number && props.errors.phone_number
? true
: false
}
fullWidth
helperText={
props.touched.phone_number
? props.errors.phone_number
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="vehicle_type"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_vehicle_type")}
placeholder={t(
"LoanRequest.text_field_enter_your_vehicle_type"
)}
type={"text"}
error={
props.touched.vehicle_type && props.errors.vehicle_type
? true
: false
}
fullWidth
helperText={
props.touched.vehicle_type
? props.errors.vehicle_type
: null
}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="plate_number"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_plate_number")}
placeholder={t(
"LoanRequest.text_field_enter_your_plate_number"
)}
type={"text"}
error={
props.touched.plate_number && props.errors.plate_number
? true
: false
}
fullWidth
helperText={
props.touched.plate_number
? props.errors.plate_number
: null
}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
name="province"
label={t("LoanRequest.text_field_province")} // t("LoanRequest.text_field_enter_your_province")
size="small"
selectType="province"
component={SelectBox}
selectors={provinceList}
select={props.values.province}
setFieldValue={props.setFieldValue}
setFieldTouched={props.setFieldTouched}
error={
props.touched.gender && props.errors.province ? true : false
}
helperText={
props.touched.gender ? props.errors.province : null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="navgan_id"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_navgan_id")}
placeholder={t("LoanRequest.text_field_enter_your_navgan_id")}
type={"text"}
error={
props.touched.navgan_id && props.errors.navgan_id
? true
: false
}
fullWidth
helperText={
props.touched.navgan_id ? props.errors.navgan_id : null
}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="national_code"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_national_code")}
placeholder={t(
"LoanRequest.text_field_enter_your_national_code"
)}
type={"text"}
error={
props.touched.national_code && props.errors.national_code
? true
: false
}
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="shenasname_id"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_shenasname_id")}
placeholder={t(
"LoanRequest.text_field_enter_your_shenasname_id"
)}
type={"text"}
error={
props.touched.shenasname_id && props.errors.shenasname_id
? true
: false
}
fullWidth
helperText={
props.touched.shenasname_id
? props.errors.shenasname_id
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "center",
justifyContent: "space-around",
width: "100%",
}}
>
<UploadSystem
selectedImage={selectedImageShenasname}
handleUploadChange={(e) =>
handleUploadChangeShenasname(e, props.setFieldValue)
}
setselectedImage={setSelectedImageShenasname}
setFieldValue={props.setFieldValue}
fieldname="shenasname_img"
fileType={fileTypeShenasname}
fileName={fileNameShenasname}
imageAlt={t("app_name")}
imageSize={[300 /*width*/, 150 /*height*/]}
label={t("LoanRequest.file_field_shenasname_image")}
/>
<UploadSystem
selectedImage={selectedImageNationalCard}
handleUploadChange={(e) =>
handleUploadChangeNationalCard(e, props.setFieldValue)
}
setselectedImage={setSelectedImageNationalCard}
setFieldValue={props.setFieldValue}
fieldname="national_card_img"
fileType={fileTypeNationalCard}
fileName={fileNameNationalCard}
imageAlt={t("app_name")}
imageSize={[300 /*width*/, 150 /*height*/]}
label={t("LoanRequest.file_field_national_card_image")}
/>
</Box>
<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"
endIcon={<DataSaverOnIcon/>}
disabled={props.isSubmitting ? true : false}
>
{t("LoanRequest.button_submit")}
</Button>
</Box>
</StyledForm>
</Stack>
)}
</Formik>
);
};
export default NavyForm;

View File

@@ -1,435 +1,435 @@
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 {SEND_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, Stack, TextField } from "@mui/material";
import {Box, Button, Stack, TextField} from "@mui/material";
import axios from "axios";
import { Field, Formik } from "formik";
import { useTranslations } from "next-intl";
import { useState } from "react";
import {Field, Formik} from "formik";
import {useTranslations} from "next-intl";
import {useState} from "react";
import * as Yup from "yup";
const WelfareServicesForm = () => {
const t = useTranslations();
const { directionApp } = useDirection();
const { token } = useUser();
const t = useTranslations();
const {directionApp} = useDirection();
const {token} = useUser();
// 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);
// 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
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, validation and request action of form
const initialValues = {
name: "",
phone_number: "",
vehicle_type: "",
plate_number: "",
province: "",
national_code: "",
shenasname_id: "",
national_card_img: null,
shenasname_img: null,
};
// initial values, validation and request action of form
const initialValues = {
name: "",
phone_number: "",
vehicle_type: "",
plate_number: "",
province: "",
national_code: "",
shenasname_id: "",
national_card_img: null,
shenasname_img: null,
};
const validationSchema = Yup.object().shape({
name: Yup.string().required(t("LoanRequest.error_message_required")),
phone_number: Yup.string().required(
t("LoanRequest.error_message_required")
),
vehicle_type: Yup.string().required(
t("LoanRequest.error_message_required")
),
plate_number: Yup.string().required(
t("LoanRequest.error_message_required")
),
province: Yup.string().required(t("LoanRequest.error_message_required")),
national_code: Yup.string().required(
t("LoanRequest.error_message_required")
),
shenasname_id: Yup.string().required(
t("LoanRequest.error_message_required")
),
});
const validationSchema = Yup.object().shape({
name: Yup.string().required(t("LoanRequest.error_message_required")),
phone_number: Yup.string().required(
t("LoanRequest.error_message_required")
),
vehicle_type: Yup.string().required(
t("LoanRequest.error_message_required")
),
plate_number: Yup.string().required(
t("LoanRequest.error_message_required")
),
province: Yup.string().required(t("LoanRequest.error_message_required")),
national_code: Yup.string().required(
t("LoanRequest.error_message_required")
),
shenasname_id: Yup.string().required(
t("LoanRequest.error_message_required")
),
});
const handleSubmit = async (values, props) => {
Notifications(directionApp, 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);
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);
const handleSubmit = async (values, props) => {
Notifications(directionApp, 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);
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);
await axios
.post(SEND_LOAN_REQUEST_WELFARE, formData, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "multipart/form-data",
},
})
.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
await axios
.post(SEND_LOAN_REQUEST_WELFARE, formData, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "multipart/form-data",
},
})
.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 (
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Stack
spacing={2}
sx={{
p: 1,
width: "100%",
}}
return (
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
<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="name"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_name")}
placeholder={t("LoanRequest.text_field_enter_your_name")}
type={"text"}
error={props.touched.name && props.errors.name ? true : false}
fullWidth
helperText={props.touched.name ? props.errors.name : null}
/>
</Box>
<Box
sx={{
mx: { xs: 0, sm: 2 },
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{ width: "100%" }}
name="phone_number"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_phone_number")}
placeholder={t(
"LoanRequest.text_field_enter_your_phone_number"
)}
type={"text"}
error={
props.touched.phone_number && props.errors.phone_number
? true
: false
}
fullWidth
helperText={
props.touched.phone_number
? props.errors.phone_number
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: { xs: "column", sm: "row" },
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: { xs: 0, sm: 2 },
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{ width: "100%" }}
name="vehicle_type"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_vehicle_type")}
placeholder={t(
"LoanRequest.text_field_enter_your_vehicle_type"
)}
type={"text"}
error={
props.touched.vehicle_type && props.errors.vehicle_type
? true
: false
}
fullWidth
helperText={
props.touched.vehicle_type
? props.errors.vehicle_type
: null
}
/>
</Box>
<Box
sx={{
mx: { xs: 0, sm: 2 },
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{ width: "100%" }}
name="plate_number"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_plate_number")}
placeholder={t(
"LoanRequest.text_field_enter_your_plate_number"
)}
type={"text"}
error={
props.touched.plate_number && props.errors.plate_number
? true
: false
}
fullWidth
helperText={
props.touched.plate_number
? props.errors.plate_number
: null
}
/>
</Box>
<Box
sx={{
mx: { xs: 0, sm: 2 },
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{ width: "100%" }}
name="province"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_province")}
placeholder={t("LoanRequest.text_field_enter_your_province")}
type={"text"}
error={
props.touched.province && props.errors.province
? true
: false
}
fullWidth
helperText={
props.touched.province ? props.errors.province : null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: { xs: "column", sm: "row" },
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: { xs: 0, sm: 2 },
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{ width: "100%" }}
name="national_code"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_national_code")}
placeholder={t(
"LoanRequest.text_field_enter_your_national_code"
)}
type={"text"}
error={
props.touched.national_code && props.errors.national_code
? true
: false
}
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="shenasname_id"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_shenasname_id")}
placeholder={t(
"LoanRequest.text_field_enter_your_shenasname_id"
)}
type={"text"}
error={
props.touched.shenasname_id && props.errors.shenasname_id
? true
: false
}
fullWidth
helperText={
props.touched.shenasname_id
? props.errors.shenasname_id
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: { xs: "column", sm: "row" },
alignItems: "center",
justifyContent: "space-around",
width: "100%",
}}
>
<UploadSystem
selectedImage={selectedImageShenasname}
handleUploadChange={(e) =>
handleUploadChangeShenasname(e, props.setFieldValue)
}
setselectedImage={setSelectedImageShenasname}
setFieldValue={props.setFieldValue}
fieldname="shenasname_img"
fileType={fileTypeShenasname}
fileName={fileNameShenasname}
imageAlt={t("app_name")}
imageSize={[300 /*width*/, 150 /*height*/]}
label={t("LoanRequest.file_field_shenasname_image")}
/>
<UploadSystem
selectedImage={selectedImageNationalCard}
handleUploadChange={(e) =>
handleUploadChangeNationalCard(e, props.setFieldValue)
}
setselectedImage={setSelectedImageNationalCard}
setFieldValue={props.setFieldValue}
fieldname="national_card_img"
fileType={fileTypeNationalCard}
fileName={fileNameNationalCard}
imageAlt={t("app_name")}
imageSize={[300 /*width*/, 150 /*height*/]}
label={t("LoanRequest.file_field_national_card_image")}
/>
</Box>
<Box
sx={{
display: "flex",
flexDirection: { xs: "column", sm: "row" },
alignItems: "center",
mx: "auto",
my: 2,
width: { xs: "100%", sm: "30%", md: "25%" },
}}
>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<DataSaverOnIcon />}
disabled={props.isSubmitting ? true : false}
>
{t("LoanRequest.button_submit")}
</Button>
</Box>
</StyledForm>
</Stack>
)}
</Formik>
);
{(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="name"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_name")}
placeholder={t("LoanRequest.text_field_enter_your_name")}
type={"text"}
error={props.touched.name && props.errors.name ? true : false}
fullWidth
helperText={props.touched.name ? props.errors.name : null}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="phone_number"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_phone_number")}
placeholder={t(
"LoanRequest.text_field_enter_your_phone_number"
)}
type={"text"}
error={
props.touched.phone_number && props.errors.phone_number
? true
: false
}
fullWidth
helperText={
props.touched.phone_number
? props.errors.phone_number
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="vehicle_type"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_vehicle_type")}
placeholder={t(
"LoanRequest.text_field_enter_your_vehicle_type"
)}
type={"text"}
error={
props.touched.vehicle_type && props.errors.vehicle_type
? true
: false
}
fullWidth
helperText={
props.touched.vehicle_type
? props.errors.vehicle_type
: null
}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="plate_number"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_plate_number")}
placeholder={t(
"LoanRequest.text_field_enter_your_plate_number"
)}
type={"text"}
error={
props.touched.plate_number && props.errors.plate_number
? true
: false
}
fullWidth
helperText={
props.touched.plate_number
? props.errors.plate_number
: null
}
/>
</Box>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="province"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_province")}
placeholder={t("LoanRequest.text_field_enter_your_province")}
type={"text"}
error={
props.touched.province && props.errors.province
? true
: false
}
fullWidth
helperText={
props.touched.province ? props.errors.province : null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "start",
justifyContent: "center",
width: "100%",
}}
>
<Box
sx={{
mx: {xs: 0, sm: 2},
my: 2,
width: "100%",
}}
>
<Field
as={TextField}
sx={{width: "100%"}}
name="national_code"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_national_code")}
placeholder={t(
"LoanRequest.text_field_enter_your_national_code"
)}
type={"text"}
error={
props.touched.national_code && props.errors.national_code
? true
: false
}
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="shenasname_id"
variant="outlined"
size="small"
label={t("LoanRequest.text_field_shenasname_id")}
placeholder={t(
"LoanRequest.text_field_enter_your_shenasname_id"
)}
type={"text"}
error={
props.touched.shenasname_id && props.errors.shenasname_id
? true
: false
}
fullWidth
helperText={
props.touched.shenasname_id
? props.errors.shenasname_id
: null
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "center",
justifyContent: "space-around",
width: "100%",
}}
>
<UploadSystem
selectedImage={selectedImageShenasname}
handleUploadChange={(e) =>
handleUploadChangeShenasname(e, props.setFieldValue)
}
setselectedImage={setSelectedImageShenasname}
setFieldValue={props.setFieldValue}
fieldname="shenasname_img"
fileType={fileTypeShenasname}
fileName={fileNameShenasname}
imageAlt={t("app_name")}
imageSize={[300 /*width*/, 150 /*height*/]}
label={t("LoanRequest.file_field_shenasname_image")}
/>
<UploadSystem
selectedImage={selectedImageNationalCard}
handleUploadChange={(e) =>
handleUploadChangeNationalCard(e, props.setFieldValue)
}
setselectedImage={setSelectedImageNationalCard}
setFieldValue={props.setFieldValue}
fieldname="national_card_img"
fileType={fileTypeNationalCard}
fileName={fileNameNationalCard}
imageAlt={t("app_name")}
imageSize={[300 /*width*/, 150 /*height*/]}
label={t("LoanRequest.file_field_national_card_image")}
/>
</Box>
<Box
sx={{
display: "flex",
flexDirection: {xs: "column", sm: "row"},
alignItems: "center",
mx: "auto",
my: 2,
width: {xs: "100%", sm: "30%", md: "25%"},
}}
>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<DataSaverOnIcon/>}
disabled={props.isSubmitting ? true : false}
>
{t("LoanRequest.button_submit")}
</Button>
</Box>
</StyledForm>
</Stack>
)}
</Formik>
);
};
export default WelfareServicesForm;

View File

@@ -3,29 +3,29 @@ import DashboardLayouts from "@/layouts/dashboardLayouts";
import useUser from "@/lib/app/hooks/useUser";
import NavyForm from "./NavyForm";
import WelfareServicesForm from "./WelfareServicesForm";
import { Divider, Chip, Box } from "@mui/material";
import { useTranslations } from "next-intl";
import {Box, Chip, Divider} from "@mui/material";
import {useTranslations} from "next-intl";
const DashboardLoanRequestComponent = () => {
const t = useTranslations();
const { user } = useUser();
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>
{user.type_id == 1 ? <NavyForm /> : <WelfareServicesForm />}
</CenterLayout>
</DashboardLayouts>
);
return (
<DashboardLayouts>
<CenterLayout>
<Box sx={{width: "80%", my: 2}}>
<Divider>
<Chip
label={`${t("LoanRequest.loan_request_page")} | ${
user.type_name
}`}
/>
</Divider>
</Box>
{user.type_id == 1 ? <NavyForm/> : <WelfareServicesForm/>}
</CenterLayout>
</DashboardLayouts>
);
};
export default DashboardLoanRequestComponent;

View File

@@ -1,55 +1,55 @@
import dahsboardImage from "&/images/dashboard.svg";
import { NextLinkComposed } from "@/core/components/LinkRouting";
import {NextLinkComposed} from "@/core/components/LinkRouting";
import StyledImage from "@/core/components/StyledImage";
import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
import useUser from "@/lib/app/hooks/useUser";
import { Button, Typography } from "@mui/material";
import { useTranslations } from "next-intl";
import {Button, Typography} from "@mui/material";
import {useTranslations} from "next-intl";
const FirstComponent = () => {
const t = useTranslations();
const { isAuth } = useUser();
const t = useTranslations();
const {isAuth} = useUser();
return (
<FullPageLayout sx={{ p: 1 }}>
<CenterLayout spacing={3}>
<StyledImage
src={dahsboardImage}
alt={t("app_name")}
width={300}
height={200}
priority
/>
<Typography variant="h5" sx={{ textAlign: "center" }}>
{t("app_name")}
</Typography>
{isAuth ? (
<Button
variant="contained"
component={NextLinkComposed}
to={{
pathname: "/dashboard",
}}
>
{t("dashboard")}
</Button>
) : (
<Button
sx={{ whiteSpace: "nowrap" }}
variant="contained"
size="large"
component={NextLinkComposed}
to={{
pathname: "/login",
}}
>
{t("login_user_panel")}
</Button>
)}
</CenterLayout>
</FullPageLayout>
);
return (
<FullPageLayout sx={{p: 1}}>
<CenterLayout spacing={3}>
<StyledImage
src={dahsboardImage}
alt={t("app_name")}
width={300}
height={200}
priority
/>
<Typography variant="h5" sx={{textAlign: "center"}}>
{t("app_name")}
</Typography>
{isAuth ? (
<Button
variant="contained"
component={NextLinkComposed}
to={{
pathname: "/dashboard",
}}
>
{t("dashboard")}
</Button>
) : (
<Button
sx={{whiteSpace: "nowrap"}}
variant="contained"
size="large"
component={NextLinkComposed}
to={{
pathname: "/login",
}}
>
{t("login_user_panel")}
</Button>
)}
</CenterLayout>
</FullPageLayout>
);
};
export default FirstComponent;

View File

@@ -1,167 +1,158 @@
import Notifications from "@/core/components/notifications";
import ResendToken from "@/core/components/ResendToken";
import StyledForm from "@/core/components/StyledForm";
import { LOGIN } from "@/core/data/apiRoutes";
import {LOGIN} from "@/core/data/apiRoutes";
import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
import useDirection from "@/lib/app/hooks/useDirection";
import useUser from "@/lib/app/hooks/useUser";
import ChangeCircleIcon from "@mui/icons-material/ChangeCircle";
import LoginIcon from "@mui/icons-material/Login";
import {
Box,
Button,
Container,
Grid,
Paper,
Stack,
TextField,
Typography,
} from "@mui/material";
import {Box, Button, Container, Grid, Paper, Stack, TextField, Typography,} from "@mui/material";
import axios from "axios";
import { Field, Formik } from "formik";
import { useTranslations } from "next-intl";
import {Field, Formik} from "formik";
import {useTranslations} from "next-intl";
import Image from "next/image";
import * as Yup from "yup";
const SendToken = ({
PhoneNumber,
setOtpToken,
timer,
setTimer,
initialTimerValue,
}) => {
const t = useTranslations();
const { directionApp } = useDirection();
const { setToken } = useUser();
PhoneNumber,
setOtpToken,
timer,
setTimer,
initialTimerValue,
}) => {
const t = useTranslations();
const {directionApp} = useDirection();
const {setToken} = useUser();
const initialValues = {
phone_number: PhoneNumber,
verification_code: "",
};
const validationSchema = Yup.object().shape({
verification_code: Yup.string().required(
t("LoginPage.error_message_required")
),
});
const initialValues = {
phone_number: PhoneNumber,
verification_code: "",
};
const validationSchema = Yup.object().shape({
verification_code: Yup.string().required(
t("LoginPage.error_message_required")
),
});
const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined);
await axios
.post(LOGIN, {
phone_number: values.phone_number,
verification_code: values.verification_code,
})
.then(function (response) {
Notifications(directionApp, t, response);
setToken(response.data.token);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined);
await axios
.post(LOGIN, {
phone_number: values.phone_number,
verification_code: values.verification_code,
})
.then(function (response) {
Notifications(directionApp, t, response);
setToken(response.data.token);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
return (
<FullPageLayout sx={{ p: 1 }}>
<CenterLayout>
<Container maxWidth="sm">
<Paper elevation={0}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Stack spacing={2} sx={{ p: 2 }}>
<Box
sx={{ position: "relative", width: "100%", height: 200 }}
>
<Image
fill
src="/images/login.svg"
priority
alt={t("app_name")}
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("login")}
</Typography>
<StyledForm sx={{ width: "100%" }}>
<Stack spacing={3} sx={{ p: 2 }}>
<Box
sx={{
display: { xs: "column", sm: "flex" },
alignItems: "center",
textAlign: { xs: "center", sm: "unset" },
justifyContent: "space-between",
}}
>
<Typography variant="button" sx={{ display: "block" }}>
{t("LoginPage.sent_token_to")}: {PhoneNumber}
</Typography>
<Button
size="small"
startIcon={<ChangeCircleIcon />}
variant="outlined"
onClick={() => setOtpToken(false)}
sx={{ whiteSpace: "nowrap", my: { xs: 1, sm: 0 } }}
return (
<FullPageLayout sx={{p: 1}}>
<CenterLayout>
<Container maxWidth="sm">
<Paper elevation={0}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{t("LoginPage.change_phone_number")}
</Button>
</Box>
<Field
as={TextField}
name="verification_code"
variant="outlined"
label={t("LoginPage.text_field_verification_code")}
placeholder={t(
"LoginPage.text_field_enter_your_verification_code"
)}
type={"text"}
error={
props.touched.verification_code &&
props.errors.verification_code
? true
: false
}
fullWidth
helperText={
props.touched.verification_code
? props.errors.verification_code
: null
}
/>
<Grid container>
<Grid item xs={12}>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<LoginIcon />}
disabled={props.isSubmitting ? true : false}
>
{t("LoginPage.button_submit")}
</Button>
</Grid>
</Grid>
<ResendToken
initialTimerValue={initialTimerValue}
timer={timer}
setTimer={setTimer}
PhoneNumber={PhoneNumber}
/>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
</FullPageLayout>
);
{(props) => (
<Stack spacing={2} sx={{p: 2}}>
<Box
sx={{position: "relative", width: "100%", height: 200}}
>
<Image
fill
src="/images/login.svg"
priority
alt={t("app_name")}
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("login")}
</Typography>
<StyledForm sx={{width: "100%"}}>
<Stack spacing={3} sx={{p: 2}}>
<Box
sx={{
display: {xs: "column", sm: "flex"},
alignItems: "center",
textAlign: {xs: "center", sm: "unset"},
justifyContent: "space-between",
}}
>
<Typography variant="button" sx={{display: "block"}}>
{t("LoginPage.sent_token_to")}: {PhoneNumber}
</Typography>
<Button
size="small"
startIcon={<ChangeCircleIcon/>}
variant="outlined"
onClick={() => setOtpToken(false)}
sx={{whiteSpace: "nowrap", my: {xs: 1, sm: 0}}}
>
{t("LoginPage.change_phone_number")}
</Button>
</Box>
<Field
as={TextField}
name="verification_code"
variant="outlined"
label={t("LoginPage.text_field_verification_code")}
placeholder={t(
"LoginPage.text_field_enter_your_verification_code"
)}
type={"text"}
error={
props.touched.verification_code &&
props.errors.verification_code
? true
: false
}
fullWidth
helperText={
props.touched.verification_code
? props.errors.verification_code
: null
}
/>
<Grid container>
<Grid item xs={12}>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<LoginIcon/>}
disabled={props.isSubmitting ? true : false}
>
{t("LoginPage.button_submit")}
</Button>
</Grid>
</Grid>
<ResendToken
initialTimerValue={initialTimerValue}
timer={timer}
setTimer={setTimer}
PhoneNumber={PhoneNumber}
/>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
</FullPageLayout>
);
};
export default SendToken;

View File

@@ -1,173 +1,164 @@
import LinkRouting from "@/core/components/LinkRouting";
import Notifications from "@/core/components/notifications";
import StyledForm from "@/core/components/StyledForm";
import { SEND_OTP_TOKEN } from "@/core/data/apiRoutes";
import {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 PersonAddIcon from "@mui/icons-material/PersonAdd";
import {
Box,
Button,
Container,
Grid,
Paper,
Stack,
TextField,
Typography,
} from "@mui/material";
import {Box, Button, Container, Grid, Paper, Stack, TextField, Typography,} from "@mui/material";
import axios from "axios";
import { Field, Formik } from "formik";
import { useTranslations } from "next-intl";
import {Field, Formik} from "formik";
import {useTranslations} from "next-intl";
import Image from "next/image";
import { useSearchParams } from "next/navigation";
import {useSearchParams} from "next/navigation";
import * as Yup from "yup";
const SendUserData = ({
setOtpToken,
setPhoneNumber,
PhoneNumber,
setTimer,
initialTimerValue,
}) => {
const t = useTranslations();
const { directionApp } = useDirection();
setOtpToken,
setPhoneNumber,
PhoneNumber,
setTimer,
initialTimerValue,
}) => {
const t = useTranslations();
const {directionApp} = useDirection();
const searchParams = useSearchParams();
const backUrlDecodedPath = searchParams.get("back_url");
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("LoginPage.error_message_required")),
});
const initialValues = {
phone_number: PhoneNumber,
};
const validationSchema = Yup.object().shape({
phone_number: Yup.string().required(t("LoginPage.error_message_required")),
});
const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined);
await axios
.post(SEND_OTP_TOKEN, {
phone_number: values.phone_number,
})
.then(function (response) {
Notifications(directionApp, t, response);
setPhoneNumber(values.phone_number);
setOtpToken(true);
setTimer(initialTimerValue);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined);
await axios
.post(SEND_OTP_TOKEN, {
phone_number: values.phone_number,
})
.then(function (response) {
Notifications(directionApp, t, response);
setPhoneNumber(values.phone_number);
setOtpToken(true);
setTimer(initialTimerValue);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
return (
<FullPageLayout sx={{ p: 1 }}>
<CenterLayout>
<Container maxWidth="sm">
<Paper elevation={0}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Stack spacing={2} sx={{ p: 2 }}>
<Box
sx={{ position: "relative", width: "100%", height: 200 }}
>
<Image
fill
src="/images/login.svg"
priority
alt={t("app_name")}
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("Titles.title_login_page")}
</Typography>
<StyledForm sx={{ width: "100%" }}>
<Stack spacing={3} sx={{ p: 2 }}>
<Field
as={TextField}
name="phone_number"
variant="outlined"
label={t("LoginPage.text_field_phone_number")}
placeholder={t(
"LoginPage.text_field_enter_your_phone_number"
)}
type={"text"}
error={
props.touched.phone_number &&
props.errors.phone_number
? true
: false
}
fullWidth
helperText={
props.touched.phone_number
? props.errors.phone_number
: null
}
/>
<Grid
container
rowSpacing={{ xs: 1, sm: 0 }}
sx={{
flexDirection: { xs: "column-reverse", sm: "row" },
}}
>
<Grid item xs={12} sm={6} sx={{ pr: { xs: 0, sm: 1 } }}>
<LinkRouting href={"/register"}>
<Button
fullWidth
type="submit"
variant="outlined"
size="large"
endIcon={<PersonAddIcon />}
disabled={props.isSubmitting ? true : false}
>
{t("LoginPage.button_make_account")}
</Button>
</LinkRouting>
</Grid>
<Grid item xs={12} sm={6} sx={{ pl: { xs: 0, sm: 1 } }}>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<FingerprintIcon />}
disabled={props.isSubmitting ? true : false}
>
{t("LoginPage.button_request_verification")}
</Button>
</Grid>
</Grid>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
<Stack direction="row" alignItems="center" justifyContent="center">
<LinkRouting
sx={{ margin: 2 }}
href={
backUrlDecodedPath ? decodeURIComponent(backUrlDecodedPath) : "/"
}
>
{t("LoginPage.link_routing_back_to")}{" "}
{backUrlDecodedPath
? t("LoginPage.link_routing_previuos_page")
: t("LoginPage.link_routing_main_page")}
</LinkRouting>
</Stack>
</FullPageLayout>
);
return (
<FullPageLayout sx={{p: 1}}>
<CenterLayout>
<Container maxWidth="sm">
<Paper elevation={0}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Stack spacing={2} sx={{p: 2}}>
<Box
sx={{position: "relative", width: "100%", height: 200}}
>
<Image
fill
src="/images/login.svg"
priority
alt={t("app_name")}
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("Titles.title_login_page")}
</Typography>
<StyledForm sx={{width: "100%"}}>
<Stack spacing={3} sx={{p: 2}}>
<Field
as={TextField}
name="phone_number"
variant="outlined"
label={t("LoginPage.text_field_phone_number")}
placeholder={t(
"LoginPage.text_field_enter_your_phone_number"
)}
type={"text"}
error={
props.touched.phone_number &&
props.errors.phone_number
? true
: false
}
fullWidth
helperText={
props.touched.phone_number
? props.errors.phone_number
: null
}
/>
<Grid
container
rowSpacing={{xs: 1, sm: 0}}
sx={{
flexDirection: {xs: "column-reverse", sm: "row"},
}}
>
<Grid item xs={12} sm={6} sx={{pr: {xs: 0, sm: 1}}}>
<LinkRouting href={"/register"}>
<Button
fullWidth
type="submit"
variant="outlined"
size="large"
endIcon={<PersonAddIcon/>}
disabled={props.isSubmitting ? true : false}
>
{t("LoginPage.button_make_account")}
</Button>
</LinkRouting>
</Grid>
<Grid item xs={12} sm={6} sx={{pl: {xs: 0, sm: 1}}}>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<FingerprintIcon/>}
disabled={props.isSubmitting ? true : false}
>
{t("LoginPage.button_request_verification")}
</Button>
</Grid>
</Grid>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
<Stack direction="row" alignItems="center" justifyContent="center">
<LinkRouting
sx={{margin: 2}}
href={
backUrlDecodedPath ? decodeURIComponent(backUrlDecodedPath) : "/"
}
>
{t("LoginPage.link_routing_back_to")}{" "}
{backUrlDecodedPath
? t("LoginPage.link_routing_previuos_page")
: t("LoginPage.link_routing_main_page")}
</LinkRouting>
</Stack>
</FullPageLayout>
);
};
export default SendUserData;

View File

@@ -1,37 +1,37 @@
import { useState } from "react";
import {useState} from "react";
import SendToken from "./SendToken";
import SendUserData from "./SendUserData";
const LoginComponent = () => {
const [otpToken, setOtpToken] = useState(false);
const [PhoneNumber, setPhoneNumber] = useState("");
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
// For Resend Token (read ResendToken Component Doc)
const initialTimerValue = 30;
const [timer, setTimer] = useState(initialTimerValue);
// End For Resend Token
if (!otpToken) {
return (
<SendUserData
setOtpToken={setOtpToken}
setPhoneNumber={setPhoneNumber}
PhoneNumber={PhoneNumber}
initialTimerValue={initialTimerValue}
setTimer={setTimer}
/>
);
} else {
return (
<SendToken
PhoneNumber={PhoneNumber}
setOtpToken={setOtpToken}
timer={timer}
initialTimerValue={initialTimerValue}
setTimer={setTimer}
/>
);
}
if (!otpToken) {
return (
<SendUserData
setOtpToken={setOtpToken}
setPhoneNumber={setPhoneNumber}
PhoneNumber={PhoneNumber}
initialTimerValue={initialTimerValue}
setTimer={setTimer}
/>
);
} else {
return (
<SendToken
PhoneNumber={PhoneNumber}
setOtpToken={setOtpToken}
timer={timer}
initialTimerValue={initialTimerValue}
setTimer={setTimer}
/>
);
}
};
export default LoginComponent;

View File

@@ -1,38 +1,38 @@
import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
import { Box, Button, Typography } from "@mui/material";
import { NextLinkComposed } from "@/core/components/LinkRouting";
import { useTranslations } from "next-intl";
import {Box, Button, Typography} from "@mui/material";
import {NextLinkComposed} from "@/core/components/LinkRouting";
import {useTranslations} from "next-intl";
import Image from "next/image";
const NotFoundComponent = () => {
const t = useTranslations();
return (
<FullPageLayout sx={{ p: 1 }}>
<CenterLayout>
<Box sx={{ position: "relative", width: "100%", height: 250 }}>
<Image
fill
src="/images/not-found.svg"
alt="not found image"
priority
/>
</Box>
<Typography margin={2} variant="h6" textAlign="center">
صفحه ای با این عنوان یافت نشد
</Typography>
<Button
variant="contained"
component={NextLinkComposed}
to={{
pathname: "/dashboard",
}}
>
رفتن به داشبورد
</Button>
</CenterLayout>
</FullPageLayout>
);
return (
<FullPageLayout sx={{p: 1}}>
<CenterLayout>
<Box sx={{position: "relative", width: "100%", height: 250}}>
<Image
fill
src="/images/not-found.svg"
alt="not found image"
priority
/>
</Box>
<Typography margin={2} variant="h6" textAlign="center">
صفحه ای با این عنوان یافت نشد
</Typography>
<Button
variant="contained"
component={NextLinkComposed}
to={{
pathname: "/dashboard",
}}
>
رفتن به داشبورد
</Button>
</CenterLayout>
</FullPageLayout>
);
};
export default NotFoundComponent;

View File

@@ -1,151 +1,143 @@
import LinkRouting from "@/core/components/LinkRouting";
import Notifications from "@/core/components/notifications";
import StyledForm from "@/core/components/StyledForm";
import { SEND_OTP_TOKEN } from "@/core/data/apiRoutes";
import {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,
Button,
Container,
Paper,
Stack,
TextField,
Typography,
} from "@mui/material";
import {Box, Button, Container, Paper, Stack, TextField, Typography,} from "@mui/material";
import axios from "axios";
import { Field, Formik } from "formik";
import { useTranslations } from "next-intl";
import {Field, Formik} from "formik";
import {useTranslations} from "next-intl";
import Image from "next/image";
import { useSearchParams } from "next/navigation";
import {useSearchParams} from "next/navigation";
import * as Yup from "yup";
const RequestOtp = ({
setOtpToken,
setPhoneNumber,
PhoneNumber,
setTimer,
initialTimerValue,
}) => {
const t = useTranslations();
const { directionApp } = useDirection();
setOtpToken,
setPhoneNumber,
PhoneNumber,
setTimer,
initialTimerValue,
}) => {
const t = useTranslations();
const {directionApp} = useDirection();
const searchParams = useSearchParams();
const backUrlDecodedPath = searchParams.get("back_url");
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_required")
),
});
const initialValues = {
phone_number: PhoneNumber,
};
const validationSchema = Yup.object().shape({
phone_number: Yup.string().required(
t("RegisterPage.error_message_required")
),
});
const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined);
await axios
.post(SEND_OTP_TOKEN, {
phone_number: values.phone_number,
})
.then(function (response) {
Notifications(directionApp, t, response);
setPhoneNumber(values.phone_number);
setOtpToken(true);
setTimer(initialTimerValue);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined);
await axios
.post(SEND_OTP_TOKEN, {
phone_number: values.phone_number,
})
.then(function (response) {
Notifications(directionApp, t, response);
setPhoneNumber(values.phone_number);
setOtpToken(true);
setTimer(initialTimerValue);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
return (
<FullPageLayout sx={{ p: 1 }}>
<CenterLayout>
<Container maxWidth="sm">
<Paper elevation={0}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Stack spacing={2} sx={{ p: 2 }}>
<Box
sx={{ position: "relative", width: "100%", height: 200 }}
>
<Image
fill
src="/images/login.svg"
priority
alt={t("app_name")}
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("Titles.title_register_page")}
</Typography>
<StyledForm sx={{ width: "100%" }}>
<Stack spacing={3} sx={{ p: 2 }}>
<Field
as={TextField}
name="phone_number"
variant="outlined"
label={t("RegisterPage.text_field_phone_number")}
placeholder={t(
"RegisterPage.text_field_enter_your_phone_number"
)}
type={"text"}
error={
props.touched.phone_number &&
props.errors.phone_number
? true
: false
}
fullWidth
helperText={
props.touched.phone_number
? props.errors.phone_number
: null
}
/>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<FingerprintIcon />}
disabled={props.isSubmitting ? true : false}
>
{t("RegisterPage.button_request_verification")}
</Button>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
<Stack direction="row" alignItems="center" justifyContent="center">
<LinkRouting
sx={{ margin: 2 }}
href={
backUrlDecodedPath
? decodeURIComponent(backUrlDecodedPath)
: "/register"
}
>
{t("RegisterPage.link_routing_back_to")}{" "}
{backUrlDecodedPath
? t("RegisterPage.link_routing_previuos_page")
: t("RegisterPage.link_routing_register")}
</LinkRouting>
</Stack>
</FullPageLayout>
);
return (
<FullPageLayout sx={{p: 1}}>
<CenterLayout>
<Container maxWidth="sm">
<Paper elevation={0}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Stack spacing={2} sx={{p: 2}}>
<Box
sx={{position: "relative", width: "100%", height: 200}}
>
<Image
fill
src="/images/login.svg"
priority
alt={t("app_name")}
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("Titles.title_register_page")}
</Typography>
<StyledForm sx={{width: "100%"}}>
<Stack spacing={3} sx={{p: 2}}>
<Field
as={TextField}
name="phone_number"
variant="outlined"
label={t("RegisterPage.text_field_phone_number")}
placeholder={t(
"RegisterPage.text_field_enter_your_phone_number"
)}
type={"text"}
error={
props.touched.phone_number &&
props.errors.phone_number
? true
: false
}
fullWidth
helperText={
props.touched.phone_number
? props.errors.phone_number
: null
}
/>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<FingerprintIcon/>}
disabled={props.isSubmitting ? true : false}
>
{t("RegisterPage.button_request_verification")}
</Button>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
<Stack direction="row" alignItems="center" justifyContent="center">
<LinkRouting
sx={{margin: 2}}
href={
backUrlDecodedPath
? decodeURIComponent(backUrlDecodedPath)
: "/register"
}
>
{t("RegisterPage.link_routing_back_to")}{" "}
{backUrlDecodedPath
? t("RegisterPage.link_routing_previuos_page")
: t("RegisterPage.link_routing_register")}
</LinkRouting>
</Stack>
</FullPageLayout>
);
};
export default RequestOtp;

View File

@@ -1,98 +1,97 @@
import dahsboardImage from "&/images/dashboard.svg";
import LinkRouting from "@/core/components/LinkRouting";
import { NextLinkComposed } from "@/core/components/LinkRouting";
import LinkRouting, {NextLinkComposed} from "@/core/components/LinkRouting";
import StyledImage from "@/core/components/StyledImage";
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 {Box, Button, Grid, Stack} from "@mui/material";
import {useTranslations} from "next-intl";
import {useSearchParams} from "next/navigation";
const RegisterComponent = () => {
const t = useTranslations();
const { isAuth } = useUser();
const t = useTranslations();
const {isAuth} = useUser();
const searchParams = useSearchParams();
const backUrlDecodedPath = searchParams.get("back_url");
const searchParams = useSearchParams();
const backUrlDecodedPath = searchParams.get("back_url");
return (
<FullPageLayout sx={{ p: 1 }}>
<CenterLayout spacing={3}>
<StyledImage
src={dahsboardImage}
alt={t("app_name")}
width={300}
height={200}
priority
/>
{isAuth ? (
<Button
variant="contained"
component={NextLinkComposed}
to={{
pathname: "/dashboard",
}}
>
{t("dashboard")}
</Button>
) : (
<Box>
<Grid
container
rowSpacing={{ xs: 1, sm: 0 }}
sx={{
flexDirection: { xs: "column", sm: "row" },
alignItems: "center",
}}
>
<Grid item xs={12} sm={6} sx={{ px: { xs: 0, sm: 1 } }}>
<Button
sx={{ whiteSpace: "nowrap" }}
variant="contained"
size="large"
component={NextLinkComposed}
to={{
pathname: "register/navy",
}}
return (
<FullPageLayout sx={{p: 1}}>
<CenterLayout spacing={3}>
<StyledImage
src={dahsboardImage}
alt={t("app_name")}
width={300}
height={200}
priority
/>
{isAuth ? (
<Button
variant="contained"
component={NextLinkComposed}
to={{
pathname: "/dashboard",
}}
>
{t("dashboard")}
</Button>
) : (
<Box>
<Grid
container
rowSpacing={{xs: 1, sm: 0}}
sx={{
flexDirection: {xs: "column", sm: "row"},
alignItems: "center",
}}
>
<Grid item xs={12} sm={6} sx={{px: {xs: 0, sm: 1}}}>
<Button
sx={{whiteSpace: "nowrap"}}
variant="contained"
size="large"
component={NextLinkComposed}
to={{
pathname: "register/navy",
}}
>
{t("register_navy")}
</Button>
</Grid>
<Grid item xs={12} sm={6} sx={{px: {xs: 0, sm: 1}}}>
<Button
sx={{whiteSpace: "nowrap"}}
variant="contained"
size="large"
component={NextLinkComposed}
to={{
pathname: "register/welfare-services",
}}
>
{t("register_welfare_services")}
</Button>
</Grid>
</Grid>
</Box>
)}
</CenterLayout>
<Stack direction="row" alignItems="center" justifyContent="center">
<LinkRouting
sx={{margin: 2}}
href={
backUrlDecodedPath
? decodeURIComponent(backUrlDecodedPath)
: "/login"
}
>
{t("register_navy")}
</Button>
</Grid>
<Grid item xs={12} sm={6} sx={{ px: { xs: 0, sm: 1 } }}>
<Button
sx={{ whiteSpace: "nowrap" }}
variant="contained"
size="large"
component={NextLinkComposed}
to={{
pathname: "register/welfare-services",
}}
>
{t("register_welfare_services")}
</Button>
</Grid>
</Grid>
</Box>
)}
</CenterLayout>
<Stack direction="row" alignItems="center" justifyContent="center">
<LinkRouting
sx={{ margin: 2 }}
href={
backUrlDecodedPath
? decodeURIComponent(backUrlDecodedPath)
: "/login"
}
>
{t("RegisterPage.link_routing_back_to")}{" "}
{backUrlDecodedPath
? t("RegisterPage.link_routing_previuos_page")
: t("RegisterPage.link_routing_login")}
</LinkRouting>
</Stack>
</FullPageLayout>
);
{t("RegisterPage.link_routing_back_to")}{" "}
{backUrlDecodedPath
? t("RegisterPage.link_routing_previuos_page")
: t("RegisterPage.link_routing_login")}
</LinkRouting>
</Stack>
</FullPageLayout>
);
};
export default RegisterComponent;

View File

@@ -1,222 +1,212 @@
import Notifications from "@/core/components/notifications";
import StyledForm from "@/core/components/StyledForm";
import { REGISTER } from "@/core/data/apiRoutes";
import {REGISTER} from "@/core/data/apiRoutes";
import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
import useDirection from "@/lib/app/hooks/useDirection";
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 {Box, Button, Chip, Container, Divider, Paper, Stack, TextField, Typography,} from "@mui/material";
import axios from "axios";
import { Field, Formik } from "formik";
import { useTranslations } from "next-intl";
import {Field, Formik} from "formik";
import {useTranslations} from "next-intl";
import Image from "next/image";
import * as Yup from "yup";
import ResendToken from "@/core/components/ResendToken";
import useUser from "@/lib/app/hooks/useUser";
const UserRegister = ({
PhoneNumber,
setOtpToken,
initialTimerValue,
timer,
setTimer,
}) => {
const t = useTranslations();
const { directionApp } = useDirection();
const { setToken } = useUser();
PhoneNumber,
setOtpToken,
initialTimerValue,
timer,
setTimer,
}) => {
const t = useTranslations();
const {directionApp} = useDirection();
const {setToken} = useUser();
const initialValues = {
type_id: "1",
verification_code: "",
phone_number: PhoneNumber,
national_id: "",
navgan_id: "",
};
const initialValues = {
type_id: "1",
verification_code: "",
phone_number: PhoneNumber,
national_id: "",
navgan_id: "",
};
const validationSchema = Yup.object().shape({
verification_code: Yup.string().required(
t("RegisterPage.error_message_required")
),
national_id: Yup.string().required(
t("RegisterPage.error_message_required")
),
navgan_id: Yup.string().required(t("RegisterPage.error_message_required")),
});
const validationSchema = Yup.object().shape({
verification_code: Yup.string().required(
t("RegisterPage.error_message_required")
),
national_id: Yup.string().required(
t("RegisterPage.error_message_required")
),
navgan_id: Yup.string().required(t("RegisterPage.error_message_required")),
});
const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined);
console.log(initialValues);
await axios
.post(REGISTER, {
type_id: values.type_id,
national_id: values.national_id,
navgan_id: values.navgan_id,
phone_number: values.phone_number,
verification_code: values.verification_code,
})
.then(function (response) {
Notifications(directionApp, t, response);
setOtpToken(true);
setToken(response.data.token);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined);
console.log(initialValues);
await axios
.post(REGISTER, {
type_id: values.type_id,
national_id: values.national_id,
navgan_id: values.navgan_id,
phone_number: values.phone_number,
verification_code: values.verification_code,
})
.then(function (response) {
Notifications(directionApp, t, response);
setOtpToken(true);
setToken(response.data.token);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
return (
<FullPageLayout sx={{ p: 1 }}>
<CenterLayout>
<Container maxWidth="sm">
<Paper elevation={0}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Stack spacing={2} sx={{ p: 2 }}>
<Box
sx={{ position: "relative", width: "100%", height: 200 }}
>
<Image
fill
src="/images/register.svg"
alt={t("app_name")}
priority
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("register_navy")}
</Typography>
<StyledForm sx={{ width: "100%" }}>
<Stack spacing={3} sx={{ p: 2 }}>
<Box
sx={{
display: { xs: "column", sm: "flex" },
alignItems: "center",
textAlign: { xs: "center", sm: "unset" },
justifyContent: "space-between",
}}
>
<Typography variant="button" sx={{ display: "block" }}>
{t("LoginPage.sent_token_to")}: {PhoneNumber}
</Typography>
<Button
size="small"
startIcon={<ChangeCircleIcon />}
variant="outlined"
sx={{ whiteSpace: "nowrap", my: { xs: 1, sm: 0 } }}
onClick={() => setOtpToken(false)}
return (
<FullPageLayout sx={{p: 1}}>
<CenterLayout>
<Container maxWidth="sm">
<Paper elevation={0}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{t("LoginPage.change_phone_number")}
</Button>
</Box>
<Field
as={TextField}
name="verification_code"
variant="outlined"
label={t("LoginPage.text_field_verification_code")}
placeholder={t(
"LoginPage.text_field_enter_your_verification_code"
)}
type={"text"}
error={
props.touched.verification_code &&
props.errors.verification_code
? true
: false
}
fullWidth
helperText={
props.touched.verification_code
? props.errors.verification_code
: null
}
/>
<ResendToken
initialTimerValue={initialTimerValue}
timer={timer}
setTimer={setTimer}
PhoneNumber={PhoneNumber}
/>
<Divider>
<Chip label={t("RegisterPage.complete_information")} />
</Divider>
<Field
as={TextField}
name="national_id"
variant="outlined"
label={t("RegisterPage.text_field_national_id")}
placeholder={t(
"RegisterPage.text_field_enter_your_national_id"
)}
type={"text"}
error={
props.touched.national_id && props.errors.national_id
? true
: false
}
fullWidth
helperText={
props.touched.national_id
? props.errors.national_id
: null
}
/>
<Field
as={TextField}
name="navgan_id"
variant="outlined"
label={t("RegisterPage.text_field_navgan_id")}
placeholder={t(
"RegisterPage.text_field_enter_your_navgan_id"
)}
type={"text"}
error={
props.touched.navgan_id && props.errors.navgan_id
? true
: false
}
fullWidth
helperText={
props.touched.navgan_id
? props.errors.navgan_id
: null
}
/>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<LoginIcon />}
disabled={props.isSubmitting ? true : false}
>
{t("RegisterPage.button_submit")}
</Button>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
</FullPageLayout>
);
{(props) => (
<Stack spacing={2} sx={{p: 2}}>
<Box
sx={{position: "relative", width: "100%", height: 200}}
>
<Image
fill
src="/images/register.svg"
alt={t("app_name")}
priority
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("register_navy")}
</Typography>
<StyledForm sx={{width: "100%"}}>
<Stack spacing={3} sx={{p: 2}}>
<Box
sx={{
display: {xs: "column", sm: "flex"},
alignItems: "center",
textAlign: {xs: "center", sm: "unset"},
justifyContent: "space-between",
}}
>
<Typography variant="button" sx={{display: "block"}}>
{t("LoginPage.sent_token_to")}: {PhoneNumber}
</Typography>
<Button
size="small"
startIcon={<ChangeCircleIcon/>}
variant="outlined"
sx={{whiteSpace: "nowrap", my: {xs: 1, sm: 0}}}
onClick={() => setOtpToken(false)}
>
{t("LoginPage.change_phone_number")}
</Button>
</Box>
<Field
as={TextField}
name="verification_code"
variant="outlined"
label={t("LoginPage.text_field_verification_code")}
placeholder={t(
"LoginPage.text_field_enter_your_verification_code"
)}
type={"text"}
error={
props.touched.verification_code &&
props.errors.verification_code
? true
: false
}
fullWidth
helperText={
props.touched.verification_code
? props.errors.verification_code
: null
}
/>
<ResendToken
initialTimerValue={initialTimerValue}
timer={timer}
setTimer={setTimer}
PhoneNumber={PhoneNumber}
/>
<Divider>
<Chip label={t("RegisterPage.complete_information")}/>
</Divider>
<Field
as={TextField}
name="national_id"
variant="outlined"
label={t("RegisterPage.text_field_national_id")}
placeholder={t(
"RegisterPage.text_field_enter_your_national_id"
)}
type={"text"}
error={
props.touched.national_id && props.errors.national_id
? true
: false
}
fullWidth
helperText={
props.touched.national_id
? props.errors.national_id
: null
}
/>
<Field
as={TextField}
name="navgan_id"
variant="outlined"
label={t("RegisterPage.text_field_navgan_id")}
placeholder={t(
"RegisterPage.text_field_enter_your_navgan_id"
)}
type={"text"}
error={
props.touched.navgan_id && props.errors.navgan_id
? true
: false
}
fullWidth
helperText={
props.touched.navgan_id
? props.errors.navgan_id
: null
}
/>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<LoginIcon/>}
disabled={props.isSubmitting ? true : false}
>
{t("RegisterPage.button_submit")}
</Button>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
</FullPageLayout>
);
};
export default UserRegister;

View File

@@ -1,37 +1,37 @@
import { useState } from "react";
import {useState} from "react";
import RequestOtp from "../RequestOtp";
import UserRegister from "./UserRegister";
const NavyComponent = () => {
const [otpToken, setOtpToken] = useState(false);
const [PhoneNumber, setPhoneNumber] = useState("");
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
// For Resend Token (read ResendToken Component Doc)
const initialTimerValue = 30;
const [timer, setTimer] = useState(initialTimerValue);
// End For Resend Token
if (!otpToken) {
return (
<RequestOtp
setOtpToken={setOtpToken}
PhoneNumber={PhoneNumber}
setPhoneNumber={setPhoneNumber}
setTimer={setTimer}
initialTimerValue={initialTimerValue}
/>
);
} else {
return (
<UserRegister
PhoneNumber={PhoneNumber}
setOtpToken={setOtpToken}
timer={timer}
setTimer={setTimer}
initialTimerValue={initialTimerValue}
/>
);
}
if (!otpToken) {
return (
<RequestOtp
setOtpToken={setOtpToken}
PhoneNumber={PhoneNumber}
setPhoneNumber={setPhoneNumber}
setTimer={setTimer}
initialTimerValue={initialTimerValue}
/>
);
} else {
return (
<UserRegister
PhoneNumber={PhoneNumber}
setOtpToken={setOtpToken}
timer={timer}
setTimer={setTimer}
initialTimerValue={initialTimerValue}
/>
);
}
};
export default NavyComponent;

View File

@@ -1,198 +1,188 @@
import Notifications from "@/core/components/notifications";
import StyledForm from "@/core/components/StyledForm";
import { REGISTER } from "@/core/data/apiRoutes";
import {REGISTER} from "@/core/data/apiRoutes";
import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
import useDirection from "@/lib/app/hooks/useDirection";
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 {Box, Button, Chip, Container, Divider, Paper, Stack, TextField, Typography,} from "@mui/material";
import axios from "axios";
import { Field, Formik } from "formik";
import { useTranslations } from "next-intl";
import {Field, Formik} from "formik";
import {useTranslations} from "next-intl";
import Image from "next/image";
import * as Yup from "yup";
import ResendToken from "@/core/components/ResendToken";
import useUser from "@/lib/app/hooks/useUser";
const UserRegister = ({
PhoneNumber,
setOtpToken,
initialTimerValue,
timer,
setTimer,
}) => {
const t = useTranslations();
const { directionApp } = useDirection();
const { setToken } = useUser();
PhoneNumber,
setOtpToken,
initialTimerValue,
timer,
setTimer,
}) => {
const t = useTranslations();
const {directionApp} = useDirection();
const {setToken} = useUser();
const initialValues = {
type_id: "2",
verification_code: "",
phone_number: PhoneNumber,
national_id: "",
};
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_required")
),
national_id: Yup.string().required(
t("RegisterPage.error_message_required")
),
});
const validationSchema = Yup.object().shape({
verification_code: Yup.string().required(
t("RegisterPage.error_message_required")
),
national_id: Yup.string().required(
t("RegisterPage.error_message_required")
),
});
const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined);
console.log(initialValues);
await axios
.post(REGISTER, {
type_id: values.type_id,
national_id: values.national_id,
phone_number: values.phone_number,
verification_code: values.verification_code,
})
.then(function (response) {
Notifications(directionApp, t, response);
setOtpToken(true);
setToken(response.data.token);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined);
console.log(initialValues);
await axios
.post(REGISTER, {
type_id: values.type_id,
national_id: values.national_id,
phone_number: values.phone_number,
verification_code: values.verification_code,
})
.then(function (response) {
Notifications(directionApp, t, response);
setOtpToken(true);
setToken(response.data.token);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
props.setSubmitting(false);
});
};
return (
<FullPageLayout sx={{ p: 1 }}>
<CenterLayout>
<Container maxWidth="sm">
<Paper elevation={0}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Stack spacing={2} sx={{ p: 2 }}>
<Box
sx={{ position: "relative", width: "100%", height: 200 }}
>
<Image
fill
src="/images/register.svg"
alt={t("app_name")}
priority
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("register_welfare_services")}
</Typography>
<StyledForm sx={{ width: "100%" }}>
<Stack spacing={3} sx={{ p: 2 }}>
<Box
sx={{
display: { xs: "column", sm: "flex" },
alignItems: "center",
textAlign: { xs: "center", sm: "unset" },
justifyContent: "space-between",
}}
>
<Typography variant="button" sx={{ display: "block" }}>
{t("LoginPage.sent_token_to")}: {PhoneNumber}
</Typography>
<Button
size="small"
startIcon={<ChangeCircleIcon />}
variant="outlined"
onClick={() => setOtpToken(false)}
sx={{ whiteSpace: "nowrap", my: { xs: 1, sm: 0 } }}
return (
<FullPageLayout sx={{p: 1}}>
<CenterLayout>
<Container maxWidth="sm">
<Paper elevation={0}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={validationSchema}
>
{t("LoginPage.change_phone_number")}
</Button>
</Box>
<Field
as={TextField}
name="verification_code"
variant="outlined"
label={t("LoginPage.text_field_verification_code")}
placeholder={t(
"LoginPage.text_field_enter_your_verification_code"
)}
type={"text"}
error={
props.touched.verification_code &&
props.errors.verification_code
? true
: false
}
fullWidth
helperText={
props.touched.verification_code
? props.errors.verification_code
: null
}
/>
<ResendToken
initialTimerValue={initialTimerValue}
timer={timer}
setTimer={setTimer}
PhoneNumber={PhoneNumber}
/>
<Divider>
<Chip label={t("RegisterPage.complete_information")} />
</Divider>
<Field
as={TextField}
name="national_id"
variant="outlined"
label={t("RegisterPage.text_field_national_id")}
placeholder={t(
"RegisterPage.text_field_enter_your_national_id"
)}
type={"text"}
error={
props.touched.national_id && props.errors.national_id
? true
: false
}
fullWidth
helperText={
props.touched.national_id
? props.errors.national_id
: null
}
/>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<LoginIcon />}
disabled={props.isSubmitting ? true : false}
>
{t("RegisterPage.button_submit")}
</Button>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
</FullPageLayout>
);
{(props) => (
<Stack spacing={2} sx={{p: 2}}>
<Box
sx={{position: "relative", width: "100%", height: 200}}
>
<Image
fill
src="/images/register.svg"
alt={t("app_name")}
priority
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("register_welfare_services")}
</Typography>
<StyledForm sx={{width: "100%"}}>
<Stack spacing={3} sx={{p: 2}}>
<Box
sx={{
display: {xs: "column", sm: "flex"},
alignItems: "center",
textAlign: {xs: "center", sm: "unset"},
justifyContent: "space-between",
}}
>
<Typography variant="button" sx={{display: "block"}}>
{t("LoginPage.sent_token_to")}: {PhoneNumber}
</Typography>
<Button
size="small"
startIcon={<ChangeCircleIcon/>}
variant="outlined"
onClick={() => setOtpToken(false)}
sx={{whiteSpace: "nowrap", my: {xs: 1, sm: 0}}}
>
{t("LoginPage.change_phone_number")}
</Button>
</Box>
<Field
as={TextField}
name="verification_code"
variant="outlined"
label={t("LoginPage.text_field_verification_code")}
placeholder={t(
"LoginPage.text_field_enter_your_verification_code"
)}
type={"text"}
error={
props.touched.verification_code &&
props.errors.verification_code
? true
: false
}
fullWidth
helperText={
props.touched.verification_code
? props.errors.verification_code
: null
}
/>
<ResendToken
initialTimerValue={initialTimerValue}
timer={timer}
setTimer={setTimer}
PhoneNumber={PhoneNumber}
/>
<Divider>
<Chip label={t("RegisterPage.complete_information")}/>
</Divider>
<Field
as={TextField}
name="national_id"
variant="outlined"
label={t("RegisterPage.text_field_national_id")}
placeholder={t(
"RegisterPage.text_field_enter_your_national_id"
)}
type={"text"}
error={
props.touched.national_id && props.errors.national_id
? true
: false
}
fullWidth
helperText={
props.touched.national_id
? props.errors.national_id
: null
}
/>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<LoginIcon/>}
disabled={props.isSubmitting ? true : false}
>
{t("RegisterPage.button_submit")}
</Button>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
</FullPageLayout>
);
};
export default UserRegister;

View File

@@ -1,37 +1,37 @@
import { useState } from "react";
import {useState} from "react";
import RequestOtp from "../RequestOtp";
import UserRegister from "./UserRegister";
const NavyComponent = () => {
const [otpToken, setOtpToken] = useState(false);
const [PhoneNumber, setPhoneNumber] = useState("");
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
// For Resend Token (read ResendToken Component Doc)
const initialTimerValue = 30;
const [timer, setTimer] = useState(initialTimerValue);
// End For Resend Token
if (!otpToken) {
return (
<RequestOtp
setOtpToken={setOtpToken}
PhoneNumber={PhoneNumber}
setPhoneNumber={setPhoneNumber}
setTimer={setTimer}
initialTimerValue={initialTimerValue}
/>
);
} else {
return (
<UserRegister
PhoneNumber={PhoneNumber}
setOtpToken={setOtpToken}
timer={timer}
setTimer={setTimer}
initialTimerValue={initialTimerValue}
/>
);
}
if (!otpToken) {
return (
<RequestOtp
setOtpToken={setOtpToken}
PhoneNumber={PhoneNumber}
setPhoneNumber={setPhoneNumber}
setTimer={setTimer}
initialTimerValue={initialTimerValue}
/>
);
} else {
return (
<UserRegister
PhoneNumber={PhoneNumber}
setOtpToken={setOtpToken}
timer={timer}
setTimer={setTimer}
initialTimerValue={initialTimerValue}
/>
);
}
};
export default NavyComponent;

View File

@@ -1,116 +1,116 @@
import MuiLink from "@mui/material/Link";
import { styled } from "@mui/material/styles";
import {styled} from "@mui/material/styles";
import clsx from "clsx";
import NextLink from "next/link";
import { useRouter } from "next/router";
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
props,
ref
) {
const {
to,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior = true,
locale,
...other
} = props;
const {
to,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior = true,
locale,
...other
} = props;
return (
<NextLink
href={to}
prefetch={prefetch}
as={linkAs}
replace={replace}
scroll={scroll}
shallow={shallow}
passHref
locale={locale}
legacyBehavior={legacyBehavior}
>
<Anchor ref={ref} {...other} />
</NextLink>
);
return (
<NextLink
href={to}
prefetch={prefetch}
as={linkAs}
replace={replace}
scroll={scroll}
shallow={shallow}
passHref
locale={locale}
legacyBehavior={legacyBehavior}
>
<Anchor ref={ref} {...other} />
</NextLink>
);
});
// A styled version of the Next.js Link component:
// https://nextjs.org/docs/api-reference/next/link
const LinkRouting = React.forwardRef(function Link(props, ref) {
const {
activeClassName = "active",
as,
className: classNameProps,
href,
legacyBehavior,
linkAs: linkAsProp,
locale,
noLinkStyle,
prefetch,
replace,
role, // Link don't have roles.
scroll,
shallow,
...other
} = props;
const {
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 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);
const isExternal =
typeof href === "string" &&
(href.indexOf("http") === 0 || href.indexOf("mailto:") === 0);
if (isExternal) {
if (noLinkStyle) {
return <Anchor className={className} href={href} ref={ref} {...other} />;
if (isExternal) {
if (noLinkStyle) {
return <Anchor className={className} href={href} ref={ref} {...other} />;
}
return <MuiLink className={className} href={href} ref={ref} {...other} />;
}
return <MuiLink className={className} href={href} ref={ref} {...other} />;
}
const linkAs = linkAsProp || as;
const nextjsProps = {
to: href,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior,
locale,
};
const linkAs = linkAsProp || as;
const nextjsProps = {
to: href,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior,
locale,
};
if (noLinkStyle) {
return (
<NextLinkComposed
className={className}
ref={ref}
{...nextjsProps}
{...other}
/>
);
}
if (noLinkStyle) {
return (
<NextLinkComposed
className={className}
ref={ref}
{...nextjsProps}
{...other}
/>
<MuiLink
component={NextLinkComposed}
className={className}
ref={ref}
{...nextjsProps}
{...other}
/>
);
}
return (
<MuiLink
component={NextLinkComposed}
className={className}
ref={ref}
{...nextjsProps}
{...other}
/>
);
});
export default LinkRouting;

View File

@@ -1,44 +1,44 @@
import { Backdrop, Fade, styled } from "@mui/material";
import {Backdrop, Fade, styled} from "@mui/material";
import StyledImage from "./StyledImage";
const LoadingImage = styled(StyledImage)({
"@keyframes load": {
"0%": {
// opacity: 0,
transform: "scale(1)",
"@keyframes load": {
"0%": {
// opacity: 0,
transform: "scale(1)",
},
"50%": {
// opacity: 1,
transform: "scale(2)",
},
"100%": {
// opacity: 0,
transform: "scale(1)",
},
},
"50%": {
// opacity: 1,
transform: "scale(2)",
},
"100%": {
// opacity: 0,
transform: "scale(1)",
},
},
animation: "load 2s infinite",
animation: "load 2s infinite",
});
const LoadingHardPage = ({ children, loading }) => {
return (
<>
<Backdrop
sx={{ bgcolor: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1 }}
open={loading}
>
<Fade in={true}>
<LoadingImage
src={"/images/loading.svg"}
alt="loading marhaba"
priority
width={100}
height={100}
/>
</Fade>
</Backdrop>
{children}
</>
);
const LoadingHardPage = ({children, loading}) => {
return (
<>
<Backdrop
sx={{bgcolor: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1}}
open={loading}
>
<Fade in={true}>
<LoadingImage
src={"/images/loading.svg"}
alt="loading marhaba"
priority
width={100}
height={100}
/>
</Fade>
</Backdrop>
{children}
</>
);
};
export default LoadingHardPage;

View File

@@ -2,22 +2,22 @@ import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
import StyledImage from "./StyledImage";
const Message = ({ text, actions }) => {
return (
<FullPageLayout sx={{ p: 1 }}>
<CenterLayout spacing={3}>
<StyledImage
src={"/images/loading.svg"}
alt="loading loan facilities"
width={100}
height={100}
priority
/>
{text}
{actions}
</CenterLayout>
</FullPageLayout>
);
const Message = ({text, actions}) => {
return (
<FullPageLayout sx={{p: 1}}>
<CenterLayout spacing={3}>
<StyledImage
src={"/images/loading.svg"}
alt="loading loan facilities"
width={100}
height={100}
priority
/>
{text}
{actions}
</CenterLayout>
</FullPageLayout>
);
};
export default Message;

View File

@@ -1,33 +1,33 @@
import { useState } from "react";
import { IconButton, InputAdornment, TextField } from "@mui/material";
import { Visibility, VisibilityOff } from "@mui/icons-material";
import { Field } from "formik";
import {useState} from "react";
import {IconButton, InputAdornment, TextField} from "@mui/material";
import {Visibility, VisibilityOff} from "@mui/icons-material";
import {Field} from "formik";
const PasswordField = (props) => {
const [showPassword, setShowPassword] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const handleClickShowPassword = () => {
setShowPassword(!showPassword);
};
const handleClickShowPassword = () => {
setShowPassword(!showPassword);
};
return (
<Field
variant="outlined"
fullWidth
as={TextField}
{...props}
type={showPassword ? "text" : "password"}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleClickShowPassword}>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
/>
);
return (
<Field
variant="outlined"
fullWidth
as={TextField}
{...props}
type={showPassword ? "text" : "password"}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleClickShowPassword}>
{showPassword ? <Visibility/> : <VisibilityOff/>}
</IconButton>
</InputAdornment>
),
}}
/>
);
};
export default PasswordField;

View File

@@ -1,72 +1,72 @@
import Notifications from "@/core/components/notifications";
import useDirection from "@/lib/app/hooks/useDirection";
import { Button, Typography } from "@mui/material";
import {Button} from "@mui/material";
import axios from "axios";
import { useTranslations } from "next-intl";
import { useEffect } from "react";
import { SEND_OTP_TOKEN } from "../data/apiRoutes";
import {useTranslations} from "next-intl";
import {useEffect} from "react";
import {SEND_OTP_TOKEN} from "../data/apiRoutes";
const ResendToken = ({ initialTimerValue, timer, setTimer, PhoneNumber }) => {
const t = useTranslations();
const { directionApp } = useDirection();
const ResendToken = ({initialTimerValue, timer, setTimer, PhoneNumber}) => {
const t = useTranslations();
const {directionApp} = useDirection();
// Countdown Timer
useEffect(() => {
let interval;
if (timer > 0) {
interval = setInterval(() => {
setTimer((prevTimer) => prevTimer - 1);
}, 1000);
} else {
clearInterval(interval);
}
// Countdown Timer
useEffect(() => {
let interval;
if (timer > 0) {
interval = setInterval(() => {
setTimer((prevTimer) => prevTimer - 1);
}, 1000);
} else {
clearInterval(interval);
}
return () => clearInterval(interval);
}, [timer]);
// End Countdown Timer
return () => clearInterval(interval);
}, [timer]);
// End Countdown Timer
// Handle Resend Token
const handleResendClick = async () => {
// work on it
if (timer != 0) return;
Notifications(directionApp, t, undefined);
await axios
.post(SEND_OTP_TOKEN, {
phone_number: PhoneNumber,
})
.then(function (response) {
Notifications(directionApp, t, response);
setTimer(initialTimerValue);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
});
};
// End Handle Resend Token
// Handle Resend Token
const handleResendClick = async () => {
// work on it
if (timer != 0) return;
Notifications(directionApp, t, undefined);
await axios
.post(SEND_OTP_TOKEN, {
phone_number: PhoneNumber,
})
.then(function (response) {
Notifications(directionApp, t, response);
setTimer(initialTimerValue);
})
.catch(function (error) {
Notifications(directionApp, t, error.response);
});
};
// End Handle Resend Token
return (
<>
{timer > 0 ? (
<Button
color="success"
disabled
sx={{ width: "auto", alignSelf: "center", mt: 0 }}
onClick={handleResendClick}
>
{t("Resend_code_in")} {timer} {" "}
{t("seconds_later")}
</Button>
) : (
<Button
color="success"
sx={{ width: "120px", alignSelf: "center", mt: 0 }}
onClick={handleResendClick}
>
{t("resend_code")}
</Button>
)}
</>
);
return (
<>
{timer > 0 ? (
<Button
color="success"
disabled
sx={{width: "auto", alignSelf: "center", mt: 0}}
onClick={handleResendClick}
>
{t("Resend_code_in")} {timer} {" "}
{t("seconds_later")}
</Button>
) : (
<Button
color="success"
sx={{width: "120px", alignSelf: "center", mt: 0}}
onClick={handleResendClick}
>
{t("resend_code")}
</Button>
)}
</>
);
};
export default ResendToken;

View File

@@ -1,55 +1,49 @@
import {
FormControl,
FormHelperText,
InputLabel,
MenuItem,
Select,
} from "@mui/material";
import {FormControl, FormHelperText, InputLabel, MenuItem, Select,} from "@mui/material";
function SelectBox({
select,
selectType,
selectors,
label,
setFieldValue,
setFieldTouched,
error,
helperText,
}) {
const handleChange = (event) => {
setFieldValue(selectType, event.target.value);
};
const handleBlur = () => {
setFieldTouched(select, true);
};
return (
<FormControl
variant="outlined"
margin="normal"
fullWidth
size="small"
error={error}
>
<InputLabel id="language-label">{label}</InputLabel>
<Select
labelId="language-label"
id={select}
name={select}
size="small"
value={select}
onChange={handleChange}
label="Language"
onBlur={handleBlur}
>
{selectors.map((selector) => (
<MenuItem key={selector.id} value={selector.value}>
{selector.name}
</MenuItem>
))}
</Select>
<FormHelperText>{helperText}</FormHelperText>
</FormControl>
);
select,
selectType,
selectors,
label,
setFieldValue,
setFieldTouched,
error,
helperText,
}) {
const handleChange = (event) => {
setFieldValue(selectType, event.target.value);
};
const handleBlur = () => {
setFieldTouched(select, true);
};
return (
<FormControl
variant="outlined"
margin="normal"
fullWidth
size="small"
error={error}
>
<InputLabel id="language-label">{label}</InputLabel>
<Select
labelId="language-label"
id={select}
name={select}
size="small"
value={select}
onChange={handleChange}
label="Language"
onBlur={handleBlur}
>
{selectors.map((selector) => (
<MenuItem key={selector.id} value={selector.value}>
{selector.name}
</MenuItem>
))}
</Select>
<FormHelperText>{helperText}</FormHelperText>
</FormControl>
);
}
export default SelectBox;

View File

@@ -1,5 +1,5 @@
import { styled } from "@mui/material";
import { Form } from "formik";
import {styled} from "@mui/material";
import {Form} from "formik";
const StyledForm = styled(Form)``;

View File

@@ -1,4 +1,4 @@
import { styled } from "@mui/material";
import {styled} from "@mui/material";
import Image from "next/image";
const StyledImage = styled(Image)``;

View File

@@ -1,15 +1,15 @@
import { useTranslations } from "next-intl";
import {useTranslations} from "next-intl";
import Head from "next/head";
const TitlePage = ({ text }) => {
const t = useTranslations();
return (
<Head>
<title>
{text ? `${t("app_short_name")} | ${t(text)}` : t("app_short_name")}
</title>
</Head>
);
const TitlePage = ({text}) => {
const t = useTranslations();
return (
<Head>
<title>
{text ? `${t("app_short_name")} | ${t(text)}` : t("app_short_name")}
</title>
</Head>
);
};
export default TitlePage;

View File

@@ -1,148 +1,147 @@
import { Box, Button, TextField, Typography } from "@mui/material";
import { useTranslations } from "next-intl";
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";
import {useRef} from "react";
const UploadSystem = ({
selectedImage,
setselectedImage,
handleUploadChange,
fieldname,
setFieldValue,
imageAlt,
imageSize,
fileType,
fileName,
label,
}) => {
const t = useTranslations();
const fileInputRef = useRef(null);
selectedImage,
setselectedImage,
handleUploadChange,
fieldname,
setFieldValue,
imageAlt,
imageSize,
fileType,
fileName,
label,
}) => {
const t = useTranslations();
const fileInputRef = useRef(null);
const handleClick = () => {
fileInputRef.current.click();
};
const handleDeleteImage = () => {
setselectedImage("/images/upload-image.svg");
setFieldValue(fieldname, 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);
};
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 (
<Box sx={{ width: imageSize[0], my: 2 }}>
<Typography
margin={2}
sx={{
fontWeight: 500,
fontSize: "1rem",
color: "#a19d9d",
}}
textAlign="center"
>
{label}
</Typography>
{selectedImage === "/images/upload-image.svg" ? (
<Image
width={imageSize[0]}
height={imageSize[1]}
src={selectedImage}
priority
alt={imageAlt}
onClick={handleClick}
style={{
cursor: "pointer",
objectFit: "contain",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
padding: "5px",
}}
/>
) : fileType && fileType.startsWith("image/") ? (
<Image
width={imageSize[0]}
height={imageSize[1]}
src={selectedImage}
priority
alt={imageAlt}
onClick={handleClick}
style={{
cursor: "pointer",
objectFit: "contain",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
padding: "5px",
}}
/>
) : (
fileType &&
isDocumentFormat(fileType) && (
<Box
sx={{
width: imageSize[0],
height: imageSize[1],
display: "flex",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
alignItems: "center",
justifyContent: "center",
}}
onClick={handleClick}
>
return (
<Box sx={{width: imageSize[0], my: 2}}>
<Typography
margin={2}
sx={{
fontWeight: 600,
fontSize: "1rem",
color: "#a19d9d",
}}
textAlign="center"
margin={2}
sx={{
fontWeight: 500,
fontSize: "1rem",
color: "#a19d9d",
}}
textAlign="center"
>
{fileName}
{label}
</Typography>
</Box>
)
)}
{selectedImage === "/images/upload-image.svg" ? (
<Image
width={imageSize[0]}
height={imageSize[1]}
src={selectedImage}
priority
alt={imageAlt}
onClick={handleClick}
style={{
cursor: "pointer",
objectFit: "contain",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
padding: "5px",
}}
/>
) : fileType && fileType.startsWith("image/") ? (
<Image
width={imageSize[0]}
height={imageSize[1]}
src={selectedImage}
priority
alt={imageAlt}
onClick={handleClick}
style={{
cursor: "pointer",
objectFit: "contain",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
padding: "5px",
}}
/>
) : (
fileType &&
isDocumentFormat(fileType) && (
<Box
sx={{
width: imageSize[0],
height: imageSize[1],
display: "flex",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
alignItems: "center",
justifyContent: "center",
}}
onClick={handleClick}
>
<Typography
margin={2}
sx={{
fontWeight: 600,
fontSize: "1rem",
color: "#a19d9d",
}}
textAlign="center"
>
{fileName}
</Typography>
</Box>
)
)}
<TextField
id="avatar-upload"
type="file"
accept="image/*"
style={{ display: "none" }}
onChange={handleUploadChange}
inputRef={fileInputRef}
/>
<Button
sx={{
width: "100%",
borderTopLeftRadius: "unset",
borderTopRightRadius: "unset",
}}
color="error"
disabled={selectedImage === "/images/upload-image.svg"}
endIcon={<DeleteForeverIcon />}
variant="contained"
onClick={handleDeleteImage}
>
{t("delete")}
</Button>
</Box>
);
<TextField
id="avatar-upload"
type="file"
accept="image/*"
style={{display: "none"}}
onChange={handleUploadChange}
inputRef={fileInputRef}
/>
<Button
sx={{
width: "100%",
borderTopLeftRadius: "unset",
borderTopRightRadius: "unset",
}}
color="error"
disabled={selectedImage === "/images/upload-image.svg"}
endIcon={<DeleteForeverIcon/>}
variant="contained"
onClick={handleDeleteImage}
>
{t("delete")}
</Button>
</Box>
);
};
export default UploadSystem;
//////****** usage document ******/////////
// 1.) use <UploadSystem /> component inside your page
// 2.) list of props that you need to send is down below

View File

@@ -1,8 +1,8 @@
import { NoSsr } from "@mui/material";
import {NoSsr} from "@mui/material";
const NoSsrHandler = ({ isBot, children }) => {
if (isBot) return children;
return <NoSsr>{children}</NoSsr>;
const NoSsrHandler = ({isBot, children}) => {
if (isBot) return children;
return <NoSsr>{children}</NoSsr>;
};
export default NoSsrHandler;

View File

@@ -1,40 +1,40 @@
import DangerousIcon from "@mui/icons-material/Dangerous";
import { Box, Typography } from "@mui/material";
import { toast } from "react-toastify";
import {Box, Typography} from "@mui/material";
import {toast} from "react-toastify";
const ErrorNotification = (directionApp, t, status, message) => {
toast(
({ closeToast }) => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<DangerousIcon color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography color="error" variant="button">
{t("notifications.error")} ({t("notifications.code")}: {status})
</Typography>
<Typography variant="caption">
{message || t("notifications.error_static_text")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
toast(
({closeToast}) => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{display: "flex", alignItems: "center"}}>
<DangerousIcon color="error" sx={{mr: 1.6}}/>
<Box sx={{display: "flex", flexDirection: "column"}}>
<Typography color="error" variant="button">
{t("notifications.error")} ({t("notifications.code")}: {status})
</Typography>
<Typography variant="caption">
{message || t("notifications.error_static_text")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
};
export default ErrorNotification;

View File

@@ -1,43 +1,43 @@
import BeenhereIcon from "@mui/icons-material/Beenhere";
import { Box, Typography } from "@mui/material";
import { toast } from "react-toastify";
import {Box, Typography} from "@mui/material";
import {toast} from "react-toastify";
const SuccessNotification = (directionApp, t, status) => {
toast(
() => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<BeenhereIcon color="success" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography color="success.main" variant="button">
{t("notifications.success")} ({t("notifications.code")}:{" "}
{status})
</Typography>
<Typography variant="caption">
{t("notifications.success_static_text")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
}
);
toast(
() => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{display: "flex", alignItems: "center"}}>
<BeenhereIcon color="success" sx={{mr: 1.6}}/>
<Box sx={{display: "flex", flexDirection: "column"}}>
<Typography color="success.main" variant="button">
{t("notifications.success")} ({t("notifications.code")}:{" "}
{status})
</Typography>
<Typography variant="caption">
{t("notifications.success_static_text")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
}
);
};
export default SuccessNotification;

View File

@@ -1,41 +1,41 @@
import ReportIcon from "@mui/icons-material/Report";
import { Box, Divider, Typography } from "@mui/material";
import { toast } from "react-toastify";
import {Box, Divider, Typography} from "@mui/material";
import {toast} from "react-toastify";
const WarningNotification = (directionApp, t, status) => {
toast(
({ closeToast }) => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<ReportIcon color="warning" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography color="warning.main" variant="button">
{t("warning")} ({t("code")}: {status})
</Typography>
<Typography variant="caption">
{t("warning_static_text")}
</Typography>
</Box>
</Box>
</Box>
<Divider sx={{ my: 1 }} />
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
toast(
({closeToast}) => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{display: "flex", alignItems: "center"}}>
<ReportIcon color="warning" sx={{mr: 1.6}}/>
<Box sx={{display: "flex", flexDirection: "column"}}>
<Typography color="warning.main" variant="button">
{t("warning")} ({t("code")}: {status})
</Typography>
<Typography variant="caption">
{t("warning_static_text")}
</Typography>
</Box>
</Box>
</Box>
<Divider sx={{my: 1}}/>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
};
export default WarningNotification;

View File

@@ -1,45 +1,45 @@
import { toast } from "react-toastify";
import {toast} from "react-toastify";
import ErrorNotification from "./ErrorNotification";
import SuccessNotification from "./SuccessNotification";
import WarningNotification from "./WarningNotification";
const Notifications = async (directionApp, t, response) => {
const { status, data } = response != undefined ? response : ""
toast.dismiss();
switch (status) {
case 200:
SuccessNotification(directionApp, t, status);
break;
case 400:
ErrorNotification(directionApp, t,status);
break;
case 401:
ErrorNotification(directionApp, t, status);
break;
case 403:
ErrorNotification(directionApp, t, status);
break;
case 422:
ErrorNotification(directionApp, t, status, data.message);
break;
case 500:
WarningNotification(directionApp, t, status);
break;
case 503:
WarningNotification(directionApp, t, status);
break;
case 504:
WarningNotification(directionApp, t, status);
break;
default:
toast(t("pending"), {
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
});
break;
}
const {status, data} = response != undefined ? response : ""
toast.dismiss();
switch (status) {
case 200:
SuccessNotification(directionApp, t, status);
break;
case 400:
ErrorNotification(directionApp, t, status);
break;
case 401:
ErrorNotification(directionApp, t, status);
break;
case 403:
ErrorNotification(directionApp, t, status);
break;
case 422:
ErrorNotification(directionApp, t, status, data.message);
break;
case 500:
WarningNotification(directionApp, t, status);
break;
case 503:
WarningNotification(directionApp, t, status);
break;
case 504:
WarningNotification(directionApp, t, status);
break;
default:
toast(t("pending"), {
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
});
break;
}
};
export default Notifications;

View File

@@ -1,7 +1,3 @@
import BorderColorIcon from "@mui/icons-material/BorderColor";
import PasswordIcon from "@mui/icons-material/Password";
const headerProfileItems = [
];
const headerProfileItems = [];
export default headerProfileItems;

View File

@@ -3,29 +3,29 @@ import BookmarkAddedIcon from "@mui/icons-material/BookmarkAdded";
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
const sidebarMenu = [
[
{
key: "sidebar.dashboard",
type: "page",
route: "/dashboard",
icon: <SpaceDashboardIcon />,
selected: false,
},
{
key: "sidebar.loan-request",
type: "page",
route: "/dashboard/loan-request",
icon: <DataSaverOnIcon />,
selected: false,
},
{
key: "sidebar.loan-follow-up",
type: "page",
route: "/dashboard/loan-follow-up",
icon: <BookmarkAddedIcon />,
selected: false,
},
],
[
{
key: "sidebar.dashboard",
type: "page",
route: "/dashboard",
icon: <SpaceDashboardIcon/>,
selected: false,
},
{
key: "sidebar.loan-request",
type: "page",
route: "/dashboard/loan-request",
icon: <DataSaverOnIcon/>,
selected: false,
},
{
key: "sidebar.loan-follow-up",
type: "page",
route: "/dashboard/loan-follow-up",
icon: <BookmarkAddedIcon/>,
selected: false,
},
],
];
export default sidebarMenu;

View File

@@ -1,38 +1,38 @@
import createCache from "@emotion/cache";
import { prefixer } from "stylis";
import {prefixer} from "stylis";
import stylisRTLPlugin from "stylis-plugin-rtl";
const isBrowser = typeof document !== "undefined";
export const createEmotionCacheLtr = () => {
let insertionPoint;
let insertionPoint;
if (isBrowser) {
const emotionInsertionPoint = document.querySelector(
'meta[name="emotion-insertion-point"]'
);
insertionPoint = emotionInsertionPoint ?? undefined;
}
if (isBrowser) {
const emotionInsertionPoint = document.querySelector(
'meta[name="emotion-insertion-point"]'
);
insertionPoint = emotionInsertionPoint ?? undefined;
}
return createCache({
key: "mui-style",
insertionPoint,
});
return createCache({
key: "mui-style",
insertionPoint,
});
};
export const createEmotionCacheRtl = () => {
let insertionPoint;
let insertionPoint;
if (isBrowser) {
const emotionInsertionPoint = document.querySelector(
'meta[name="emotion-insertion-point"]'
);
insertionPoint = emotionInsertionPoint ?? undefined;
}
if (isBrowser) {
const emotionInsertionPoint = document.querySelector(
'meta[name="emotion-insertion-point"]'
);
insertionPoint = emotionInsertionPoint ?? undefined;
}
return createCache({
key: "muirtl",
stylisPlugins: [prefixer, stylisRTLPlugin],
insertionPoint,
});
return createCache({
key: "muirtl",
stylisPlugins: [prefixer, stylisRTLPlugin],
insertionPoint,
});
};

View File

@@ -1,12 +1,12 @@
import { createTheme } from "@mui/material/styles";
import {createTheme} from "@mui/material/styles";
import theme from "./theme";
const themeRtl = createTheme({
direction: "rtl",
typography: {
fontFamily: `IRANSans, sans-serif`,
},
...theme,
direction: "rtl",
typography: {
fontFamily: `IRANSans, sans-serif`,
},
...theme,
});
export default themeRtl;

View File

@@ -1,18 +1,18 @@
const theme = {
palette: {
primary: {
main: "#084070",
contrastText: "#fff",
light: "#2c6291",
dark: "#11293e",
palette: {
primary: {
main: "#084070",
contrastText: "#fff",
light: "#2c6291",
dark: "#11293e",
},
secondary: {
main: "#FF4E00",
contrastText: "#fff",
light: "#ed743e",
dark: "#ad3a07",
},
},
secondary: {
main: "#FF4E00",
contrastText: "#fff",
light: "#ed743e",
dark: "#ad3a07",
},
},
};
export default theme;

View File

@@ -4,96 +4,96 @@ import useLoading from "@/lib/app/hooks/useLoading";
import useUser from "@/lib/app/hooks/useUser";
import Head from "next/head";
import NextNProgress from "nextjs-progressbar";
import { useEffect } from "react";
import {useEffect} from "react";
function AppLayout({ children, isBot }) {
const { languageIsReady } = useLanguage();
const { setLoadingPage } = useLoading();
const { userChangedLanguage, token, isAuth } = useUser();
useEffect(() => {
if (languageIsReady) {
if (token) {
if (isAuth) {
if (userChangedLanguage) {
setLoadingPage(true);
function AppLayout({children, isBot}) {
const {languageIsReady} = useLanguage();
const {setLoadingPage} = useLoading();
const {userChangedLanguage, token, isAuth} = useUser();
useEffect(() => {
if (languageIsReady) {
if (token) {
if (isAuth) {
if (userChangedLanguage) {
setLoadingPage(true);
return;
}
setLoadingPage(false);
return;
}
setLoadingPage(true);
return;
}
setLoadingPage(false);
return;
}
setLoadingPage(false);
return;
}
setLoadingPage(true);
return;
}
setLoadingPage(false);
return;
}, [languageIsReady, token, isAuth, userChangedLanguage]);
if (!isBot) {
if (userChangedLanguage) return;
if (!languageIsReady) return;
}
setLoadingPage(true);
}, [languageIsReady, token, isAuth, userChangedLanguage]);
if (!isBot) {
if (userChangedLanguage) return;
if (!languageIsReady) return;
}
return (
<>
<Head>
<meta
name="application-name"
content={process.env.NEXT_PUBLIC_API_NAME}
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta
name="apple-mobile-web-app-status-bar-style"
content="black-translucent"
/>
<meta
name="apple-mobile-web-app-title"
content={process.env.NEXT_PUBLIC_API_NAME}
/>
<meta name="description" content="Marhaba does it for you" />
<meta name="format-detection" content="telephone=no" />
<meta name="format-detection" content="date=no" />
<meta name="format-detection" content="address=no" />
<meta name="format-detection" content="email=no" />
<meta name="mobile-web-app-capable" content="yes" />
<link rel="apple-touch-icon" href="/icons/maskable_icon_x512.png" />
<link
rel="apple-touch-icon"
sizes="120x120"
href="/icons/maskable_icon_x128.png"
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/icons/maskable_icon_x192.png"
/>
<meta name="google" content="notranslate" />
<meta name="robots" content="noindex" />
<meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
/>
<link
rel="icon"
type="image/svg"
sizes="32x32"
href="/images/logo.png"
/>
<link
rel="icon"
type="image/svg"
sizes="16x16"
href="/images/logo.png"
/>
</Head>
<NextNProgress
color={theme.palette.secondary.dark}
options={{ showSpinner: false }}
/>
{children}
</>
);
return (
<>
<Head>
<meta
name="application-name"
content={process.env.NEXT_PUBLIC_API_NAME}
/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta
name="apple-mobile-web-app-status-bar-style"
content="black-translucent"
/>
<meta
name="apple-mobile-web-app-title"
content={process.env.NEXT_PUBLIC_API_NAME}
/>
<meta name="description" content="Marhaba does it for you"/>
<meta name="format-detection" content="telephone=no"/>
<meta name="format-detection" content="date=no"/>
<meta name="format-detection" content="address=no"/>
<meta name="format-detection" content="email=no"/>
<meta name="mobile-web-app-capable" content="yes"/>
<link rel="apple-touch-icon" href="/icons/maskable_icon_x512.png"/>
<link
rel="apple-touch-icon"
sizes="120x120"
href="/icons/maskable_icon_x128.png"
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/icons/maskable_icon_x192.png"
/>
<meta name="google" content="notranslate"/>
<meta name="robots" content="noindex"/>
<meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
/>
<link
rel="icon"
type="image/svg"
sizes="32x32"
href="/images/logo.png"
/>
<link
rel="icon"
type="image/svg"
sizes="16x16"
href="/images/logo.png"
/>
</Head>
<NextNProgress
color={theme.palette.secondary.dark}
options={{showSpinner: false}}
/>
{children}
</>
);
}
export default AppLayout;

View File

@@ -1,18 +1,18 @@
import { Fade, Stack } from "@mui/material";
import {Fade, Stack} from "@mui/material";
const CenterLayout = (props) => {
return (
<Fade in={true}>
<Stack
alignItems="center"
justifyContent="center"
spacing={props?.spacing}
sx={{ flex: 1, ...props?.sx, py: 3 }}
>
{props.children}
</Stack>
</Fade>
);
return (
<Fade in={true}>
<Stack
alignItems="center"
justifyContent="center"
spacing={props?.spacing}
sx={{flex: 1, ...props?.sx, py: 3}}
>
{props.children}
</Stack>
</Fade>
);
};
export default CenterLayout;

View File

@@ -1,21 +1,21 @@
import { Stack } from "@mui/material";
import {Stack} from "@mui/material";
const FullPageLayout = (props) => {
return (
<Stack
spacing={props?.spacing}
direction={props?.direction}
sx={{
width: "100%",
height: "100%",
overflowY: "scroll",
overflowX: "scroll",
...props?.sx,
}}
>
{props.children}
</Stack>
);
return (
<Stack
spacing={props?.spacing}
direction={props?.direction}
sx={{
width: "100%",
height: "100%",
overflowY: "scroll",
overflowX: "scroll",
...props?.sx,
}}
>
{props.children}
</Stack>
);
};
export default FullPageLayout;

View File

@@ -1,76 +1,74 @@
import NoSsrHandler from "@/core/components/isBotHandler";
import {
createEmotionCacheRtl
} from "@/core/utils/createEmotionCache";
import {createEmotionCacheRtl} from "@/core/utils/createEmotionCache";
import themeRtl from "@/core/utils/theme-rtl";
import { CacheProvider } from "@emotion/react";
import { GlobalStyles } from "@mui/material";
import {CacheProvider} from "@emotion/react";
import {GlobalStyles} from "@mui/material";
import CssBaseline from "@mui/material/CssBaseline";
import { ThemeProvider } from "@mui/material/styles";
import {ThemeProvider} from "@mui/material/styles";
import Head from "next/head";
const clientSideEmotionCacheRtl = createEmotionCacheRtl();
const MuiLayout = ({ children, isBot }) => {
const MuiLayout = ({children, isBot}) => {
const emotionCache = clientSideEmotionCacheRtl;
const emotionCache = clientSideEmotionCacheRtl;
const theme = themeRtl;
return (
<NoSsrHandler isBot={isBot}>
<CacheProvider value={emotionCache}>
<Head>
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
<GlobalStyles
styles={{
"*:not(.MuiTableContainer-root)::-webkit-scrollbar": {
display: "none",
},
"*::-webkit-scrollbar": {
height: "8px",
},
"*::-webkit-scrollbar-thumb": {
background: "#e1e1e1",
borderRadius: "3px",
},
"*:not(.MuiTableContainer-root)": {
scrollbarWidth: "thin",
scrollbarColor: "transparent transparent",
},
const theme = themeRtl;
return (
<NoSsrHandler isBot={isBot}>
<CacheProvider value={emotionCache}>
<Head>
<meta name="viewport" content="initial-scale=1, width=device-width"/>
</Head>
<ThemeProvider theme={theme}>
<GlobalStyles
styles={{
"*:not(.MuiTableContainer-root)::-webkit-scrollbar": {
display: "none",
},
"*::-webkit-scrollbar": {
height: "8px",
},
"*::-webkit-scrollbar-thumb": {
background: "#e1e1e1",
borderRadius: "3px",
},
"*:not(.MuiTableContainer-root)": {
scrollbarWidth: "thin",
scrollbarColor: "transparent transparent",
},
"*": {
scrollbarWidth: "thin",
scrollbarColor: "#e1e1e1 transparent",
},
"*": {
scrollbarWidth: "thin",
scrollbarColor: "#e1e1e1 transparent",
},
"*::-moz-scrollbar-thumb": {
backgroundColor: "#e1e1e1",
},
[`@media (max-width: ${theme.breakpoints.values.sm}px)`]: {
"*::-webkit-scrollbar": {
height: "4px",
},
},
"*::-moz-scrollbar-thumb": {
backgroundColor: "#e1e1e1",
},
[`@media (max-width: ${theme.breakpoints.values.sm}px)`]: {
"*::-webkit-scrollbar": {
height: "4px",
},
},
body: {
width: "100vw",
height: "100vh",
},
"#__next": {
width: "100%",
height: "100%",
},
}}
/>
body: {
width: "100vw",
height: "100vh",
},
"#__next": {
width: "100%",
height: "100%",
},
}}
/>
<CssBaseline />
{children}
</ThemeProvider>
</CacheProvider>
</NoSsrHandler>
);
<CssBaseline/>
{children}
</ThemeProvider>
</CacheProvider>
</NoSsrHandler>
);
};
export default MuiLayout;

View File

@@ -1,25 +1,25 @@
import { Box, Fade } from "@mui/material";
import {Box, Fade} from "@mui/material";
const ScrollableLayout = (props) => {
const overflowY = props?.y || "hidden";
const overflowX = props?.x || "hidden";
const overflowY = props?.y || "hidden";
const overflowX = props?.x || "hidden";
return (
<Fade in={true}>
<Box
spacing={props?.spacing}
sx={{
width: "auto",
height: "auto",
overflowY: overflowY,
overflowX: overflowX,
...props?.sx,
}}
>
{props.children}
</Box>
</Fade>
);
return (
<Fade in={true}>
<Box
spacing={props?.spacing}
sx={{
width: "auto",
height: "auto",
overflowY: overflowY,
overflowX: overflowX,
...props?.sx,
}}
>
{props.children}
</Box>
</Fade>
);
};
export default ScrollableLayout;

View File

@@ -1,19 +1,19 @@
import LinkRouting from "@/core/components/LinkRouting";
import { Typography } from "@mui/material";
import { useTranslations } from "next-intl";
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("/")}`;
const t = useTranslations();
const isLast = props.index === props.RouterArray.length - 1;
const url = `/${props.RouterArray.slice(0, props.index + 1).join("/")}`;
return isLast ? (
<Typography variant="body2" color="primary">
{t("sidebar." + props.label)}
</Typography>
) : (
<LinkRouting underline="hover" color="inherit" passHref href={url}>
<Typography variant="body2">{t("sidebar." + props.label)}</Typography>
</LinkRouting>
);
return isLast ? (
<Typography variant="body2" color="primary">
{t("sidebar." + props.label)}
</Typography>
) : (
<LinkRouting underline="hover" color="inherit" passHref href={url}>
<Typography variant="body2">{t("sidebar." + props.label)}</Typography>
</LinkRouting>
);
}

View File

@@ -1,49 +1,49 @@
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 {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";
const BreadCrumbs = (props) => {
const { isVisible } = props;
const theme = useTheme();
const router = useRouter();
const {isVisible} = props;
const theme = useTheme();
const router = useRouter();
if (!isVisible) {
return null;
}
if (!isVisible) {
return null;
}
const { pathname } = router;
const RouterArray = pathname.split("/").filter((segment) => segment !== "");
const {pathname} = router;
const RouterArray = pathname.split("/").filter((segment) => segment !== "");
if (RouterArray.length === 1) {
return null;
}
if (RouterArray.length === 1) {
return null;
}
return (
<Box p={3} component="span">
<Breadcrumbs
maxItems={2}
separator={
theme.direction === "ltr" ? (
<NavigateNext fontSize="small" />
) : (
<NavigateBefore fontSize="small" />
)
}
aria-label="breadcrumb"
>
{RouterArray.map((segment, index) => (
<BreadcrumbItem
RouterArray={RouterArray}
label={segment}
key={segment}
index={index}
/>
))}
</Breadcrumbs>
</Box>
);
return (
<Box p={3} component="span">
<Breadcrumbs
maxItems={2}
separator={
theme.direction === "ltr" ? (
<NavigateNext fontSize="small"/>
) : (
<NavigateBefore fontSize="small"/>
)
}
aria-label="breadcrumb"
>
{RouterArray.map((segment, index) => (
<BreadcrumbItem
RouterArray={RouterArray}
label={segment}
key={segment}
index={index}
/>
))}
</Breadcrumbs>
</Box>
);
};
export default BreadCrumbs;

View File

@@ -1,15 +1,15 @@
import { Avatar, Stack, Typography } from "@mui/material";
import {Avatar, Stack} from "@mui/material";
import useUser from "@/lib/app/hooks/useUser";
export default function ProfileData() {
const { user } = useUser();
return (
<Stack alignItems="center" spacing={2} sx={{ p: 3 }}>
<Avatar
sx={{ width: "80px", height: "80px" }}
alt="User Image"
src={user.user_avatar}
/>
</Stack>
);
const {user} = useUser();
return (
<Stack alignItems="center" spacing={2} sx={{p: 3}}>
<Avatar
sx={{width: "80px", height: "80px"}}
alt="User Image"
src={user.user_avatar}
/>
</Stack>
);
}

View File

@@ -1,61 +1,62 @@
import { Avatar, Menu, IconButton, Tooltip } from "@mui/material";
import { useState } from "react";
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 {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 t = useTranslations();
const [anchorElUser, setAnchorElUser] = useState(null);
const {user} = useUser();
const handleOpenUserMenu = (event) => {
setAnchorElUser(event.currentTarget);
};
const handleCloseUserMenu = () => {
setAnchorElUser(null);
};
const handleOpenUserMenu = (event) => {
setAnchorElUser(event.currentTarget);
};
const handleCloseUserMenu = () => {
setAnchorElUser(null);
};
return (
<>
<Tooltip title={t("header.open_profile")} arrow>
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
<Avatar
sx={{
width: 24,
height: 24,
backgroundColor: "#fff",
color: "primary.main",
}}
alt="User Image"
src={user.user_avatar}
/>
</IconButton>
</Tooltip>
<Menu
MenuListProps={{ sx: { py: 0 } }}
sx={{
mt: 6,
}}
id="menu-appbar"
anchorEl={anchorElUser}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
keepMounted
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
open={Boolean(anchorElUser)}
onClose={handleCloseUserMenu}
>
<ProfileData />
<ProfileOptions handleCloseUserMenu={handleCloseUserMenu} />
</Menu>
</>
);
return (
<>
<Tooltip title={t("header.open_profile")} arrow>
<IconButton onClick={handleOpenUserMenu} sx={{p: 0}}>
<Avatar
sx={{
width: 24,
height: 24,
backgroundColor: "#fff",
color: "primary.main",
}}
alt="User Image"
src={user.user_avatar}
/>
</IconButton>
</Tooltip>
<Menu
MenuListProps={{sx: {py: 0}}}
sx={{
mt: 6,
}}
id="menu-appbar"
anchorEl={anchorElUser}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
keepMounted
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
open={Boolean(anchorElUser)}
onClose={handleCloseUserMenu}
>
<ProfileData/>
<ProfileOptions handleCloseUserMenu={handleCloseUserMenu}/>
</Menu>
</>
);
}
export default ProfileMenu;

View File

@@ -1,49 +1,49 @@
import { Box, Button, MenuItem, Typography } from "@mui/material";
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";
import {useTranslations} from "next-intl";
export default function ProfileOptionLogOut({ handleCloseUserMenu }) {
const t = useTranslations();
const { clearToken } = useUser();
const handleClickLogOut = () => {
handleCloseUserMenu();
clearToken();
};
return (
<>
<MenuItem
component={Button}
to={{
pathname: "/dashboard/logout",
}}
sx={{
display: "flex",
justifyContent: "center",
borderTop: 1,
px: 3,
py: 1.5,
borderColor: "#e1e1e1",
textTransform: "unset",
}}
onClick={handleClickLogOut}
>
<Box sx={{ display: "flex", alignItems: "center", flex: 1 }}>
<Box
sx={{
display: "flex",
alignItems: "center",
color: "primary.main",
pr: 2,
}}
>
<MeetingRoomIcon />
</Box>
<Typography sx={{ flex: 1 }} textAlign="start">
{t("header.logout")}
</Typography>
</Box>
</MenuItem>
</>
);
export default function ProfileOptionLogOut({handleCloseUserMenu}) {
const t = useTranslations();
const {clearToken} = useUser();
const handleClickLogOut = () => {
handleCloseUserMenu();
clearToken();
};
return (
<>
<MenuItem
component={Button}
to={{
pathname: "/dashboard/logout",
}}
sx={{
display: "flex",
justifyContent: "center",
borderTop: 1,
px: 3,
py: 1.5,
borderColor: "#e1e1e1",
textTransform: "unset",
}}
onClick={handleClickLogOut}
>
<Box sx={{display: "flex", alignItems: "center", flex: 1}}>
<Box
sx={{
display: "flex",
alignItems: "center",
color: "primary.main",
pr: 2,
}}
>
<MeetingRoomIcon/>
</Box>
<Typography sx={{flex: 1}} textAlign="start">
{t("header.logout")}
</Typography>
</Box>
</MenuItem>
</>
);
}

View File

@@ -1,49 +1,49 @@
import { Box, MenuItem, Typography } from "@mui/material";
import { NextLinkComposed } from "@/core/components/LinkRouting";
import { useTranslations } from "next-intl";
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();
export default function ProfileOptions({handleCloseUserMenu}) {
const t = useTranslations();
return (
<>
{headerProfileItems.map((profile_item) => (
<MenuItem
component={NextLinkComposed}
to={{
pathname: profile_item.route,
}}
sx={{
display: "flex",
justifyContent: "center",
borderTop: 1,
px: 3,
py: 1.5,
borderColor: "#e1e1e1",
}}
key={profile_item.key}
onClick={handleCloseUserMenu}
>
<Box sx={{ display: "flex", alignItems: "center", flex: 1 }}>
<Box
sx={{
display: "flex",
alignItems: "center",
color: "primary.main",
pr: 2,
}}
>
{profile_item.icon}
</Box>
<Typography sx={{ flex: 1 }} textAlign="start">
{t(profile_item.name)}
</Typography>
</Box>
</MenuItem>
))}
<ProfileOptionLogOut handleCloseUserMenu={handleCloseUserMenu} />
</>
);
return (
<>
{headerProfileItems.map((profile_item) => (
<MenuItem
component={NextLinkComposed}
to={{
pathname: profile_item.route,
}}
sx={{
display: "flex",
justifyContent: "center",
borderTop: 1,
px: 3,
py: 1.5,
borderColor: "#e1e1e1",
}}
key={profile_item.key}
onClick={handleCloseUserMenu}
>
<Box sx={{display: "flex", alignItems: "center", flex: 1}}>
<Box
sx={{
display: "flex",
alignItems: "center",
color: "primary.main",
pr: 2,
}}
>
{profile_item.icon}
</Box>
<Typography sx={{flex: 1}} textAlign="start">
{t(profile_item.name)}
</Typography>
</Box>
</MenuItem>
))}
<ProfileOptionLogOut handleCloseUserMenu={handleCloseUserMenu}/>
</>
);
}

View File

@@ -1,80 +1,72 @@
import MenuIcon from "@mui/icons-material/Menu";
import {
AppBar,
Box,
Container,
CssBaseline,
IconButton,
Stack,
Toolbar,
useTheme
} from "@mui/material";
import {AppBar, Box, Container, CssBaseline, IconButton, Stack, Toolbar, useTheme} from "@mui/material";
import ProfileMenu from "./ProfileMenu";
function Header({ drawerWidth, handleDrawerToggle }) {
const theme = useTheme();
function Header({drawerWidth, handleDrawerToggle}) {
const theme = useTheme();
return (
<>
<CssBaseline />
<AppBar
position="fixed"
sx={{
width: { md: `calc(100% - ${drawerWidth}px)` },
ml: { md: `${drawerWidth}px` },
}}
>
<Container maxWidth="xxl">
<Toolbar
disableGutters
sx={{
display: "flex",
}}
>
<Stack direction="row" justifyContent="flex-start" sx={{ flex: 1 }}>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerToggle}
edge="start"
sx={{ display: { md: "none" }, m: 0 }}
>
<MenuIcon />
</IconButton>
</Stack>
<Stack
direction="row"
justifyContent="center"
sx={{
flex: 1,
position: "relative",
...theme.mixins.toolbar,
}}
>
<Box
return (
<>
<CssBaseline/>
<AppBar
position="fixed"
sx={{
position: "relative",
my: 1,
width: 56,
height: 56,
"@media (min-width:600px)": { maxWidth: 64, maxHeight: 64 },
"@media (min-width:0px)": {
"@media (orientation: landscape)": {
width: 48,
height: 48,
},
},
width: {md: `calc(100% - ${drawerWidth}px)`},
ml: {md: `${drawerWidth}px`},
}}
>
</Box>
</Stack>
<Stack direction="row" justifyContent="flex-end" sx={{ flex: 1 }}>
<ProfileMenu />
</Stack>
</Toolbar>
</Container>
</AppBar>
</>
);
>
<Container maxWidth="xxl">
<Toolbar
disableGutters
sx={{
display: "flex",
}}
>
<Stack direction="row" justifyContent="flex-start" sx={{flex: 1}}>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerToggle}
edge="start"
sx={{display: {md: "none"}, m: 0}}
>
<MenuIcon/>
</IconButton>
</Stack>
<Stack
direction="row"
justifyContent="center"
sx={{
flex: 1,
position: "relative",
...theme.mixins.toolbar,
}}
>
<Box
sx={{
position: "relative",
my: 1,
width: 56,
height: 56,
"@media (min-width:600px)": {maxWidth: 64, maxHeight: 64},
"@media (min-width:0px)": {
"@media (orientation: landscape)": {
width: 48,
height: 48,
},
},
}}
>
</Box>
</Stack>
<Stack direction="row" justifyContent="flex-end" sx={{flex: 1}}>
<ProfileMenu/>
</Stack>
</Toolbar>
</Container>
</AppBar>
</>
);
}
export default Header;

View File

@@ -1,50 +1,50 @@
import { useState } from "react";
import {useState} from "react";
import FullPageLayout from "../FullPageLayout";
import Header from "./header";
import Sidebar from "./sidebar";
import { Toolbar } from "@mui/material";
import {Toolbar} from "@mui/material";
import BreadCrumbs from "./breadcrumbs";
import { ToastContainer } from "react-toastify";
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 {directionApp} = useDirection();
const {window} = props;
const [mobileOpen, setMobileOpen] = useState(false);
const container =
window !== undefined ? () => window().document.body : undefined;
const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen);
};
return (
<FullPageLayout direction="row">
<Header
handleDrawerToggle={handleDrawerToggle}
drawerWidth={drawerWidth}
/>
<Sidebar
container={container}
mobileOpen={mobileOpen}
handleDrawerToggle={handleDrawerToggle}
drawerWidth={drawerWidth}
/>
<FullPageLayout
component="main"
sx={{ flexGrow: 1, width: { sm: `calc(100% - ${drawerWidth}px)` } }}
>
<Toolbar />
<FullPageLayout sx={{ mt: 3 }}>
<BreadCrumbs isVisible={true} />
{props.children}
const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen);
};
return (
<FullPageLayout direction="row">
<Header
handleDrawerToggle={handleDrawerToggle}
drawerWidth={drawerWidth}
/>
<Sidebar
container={container}
mobileOpen={mobileOpen}
handleDrawerToggle={handleDrawerToggle}
drawerWidth={drawerWidth}
/>
<FullPageLayout
component="main"
sx={{flexGrow: 1, width: {sm: `calc(100% - ${drawerWidth}px)`}}}
>
<Toolbar/>
<FullPageLayout sx={{mt: 3}}>
<BreadCrumbs isVisible={true}/>
{props.children}
</FullPageLayout>
</FullPageLayout>
{directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
</FullPageLayout>
</FullPageLayout>
{directionApp === "rtl" ? <ToastContainer rtl /> : <ToastContainer ltr />}
</FullPageLayout>
);
);
};
export default DashboardLayouts;

View File

@@ -1,26 +1,26 @@
import useUser from "@/lib/app/hooks/useUser";
import { Divider, Stack, Toolbar, Typography } from "@mui/material";
import { useTranslations } from "next-intl";
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();
const SidebarDrawer = ({handleDrawerToggle}) => {
const {user} = useUser();
const t = useTranslations();
return (
<>
<Toolbar>
<Stack>
<Typography variant="h6" sx={{ color: "primary.main" }}>
{t("app_short_name")}
</Typography>
<Typography variant="caption">{user.type_name}</Typography>
</Stack>
</Toolbar>
<Divider />
<SidebarList handleDrawerToggle={handleDrawerToggle} />
</>
);
return (
<>
<Toolbar>
<Stack>
<Typography variant="h6" sx={{color: "primary.main"}}>
{t("app_short_name")}
</Typography>
<Typography variant="caption">{user.type_name}</Typography>
</Stack>
</Toolbar>
<Divider/>
<SidebarList handleDrawerToggle={handleDrawerToggle}/>
</>
);
};
export default SidebarDrawer;

View File

@@ -1,56 +1,56 @@
import { Divider, List } from "@mui/material";
import { Fragment, useEffect, useReducer } from "react";
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 {useRouter} from "next/router";
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();
}
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);
export default function SidebarList({handleDrawerToggle}) {
const [itemMenu, dispatch] = useReducer(reducer, sidebarMenu);
// activate current page in menu
const router = useRouter();
useEffect(() => {
dispatch({ type: "SELECTED", route: router.pathname });
}, [router.pathname]);
// activate current page in menu
const router = useRouter();
useEffect(() => {
dispatch({type: "SELECTED", route: router.pathname});
}, [router.pathname]);
return (
<List>
{itemMenu.map((itemArr, index) => (
<Fragment key={index}>
{itemArr.map((item) => (
<SidebarListItem
item={item}
dispatch={dispatch}
key={item.key}
handleDrawerToggle={handleDrawerToggle}
/>
))}
<Divider />
</Fragment>
))}
</List>
);
return (
<List>
{itemMenu.map((itemArr, index) => (
<Fragment key={index}>
{itemArr.map((item) => (
<SidebarListItem
item={item}
dispatch={dispatch}
key={item.key}
handleDrawerToggle={handleDrawerToggle}
/>
))}
<Divider/>
</Fragment>
))}
</List>
);
}

View File

@@ -1,64 +1,59 @@
import { NextLinkComposed } from "@/core/components/LinkRouting";
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 {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();
const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
const t = useTranslations();
return (
<Fragment key={item.key}>
<ListItem disablePadding sx={{ display: "block" }}>
<ListItemButton
selected={item.selected}
{...(item.type == "page" && {
component: NextLinkComposed,
to: {
pathname: item.route,
},
})}
onClick={() => {
if (item.type == "menu") {
dispatch({ type: "COLLAPSE_MENU", key: item.key });
}
handleDrawerToggle();
}}
sx={{
minHeight: 48,
}}
>
<ListItemIcon
sx={{
minWidth: 0,
justifyContent: "center",
color: "primary.main",
pr: 2,
}}
>
{item.icon}
</ListItemIcon>
<ListItemText primary={t(item.key)} />
return (
<Fragment key={item.key}>
<ListItem disablePadding sx={{display: "block"}}>
<ListItemButton
selected={item.selected}
{...(item.type == "page" && {
component: NextLinkComposed,
to: {
pathname: item.route,
},
})}
onClick={() => {
if (item.type == "menu") {
dispatch({type: "COLLAPSE_MENU", key: item.key});
}
handleDrawerToggle();
}}
sx={{
minHeight: 48,
}}
>
<ListItemIcon
sx={{
minWidth: 0,
justifyContent: "center",
color: "primary.main",
pr: 2,
}}
>
{item.icon}
</ListItemIcon>
<ListItemText primary={t(item.key)}/>
{item.type == "menu" &&
(item.showSubItem ? <ExpandLess /> : <ExpandMore />)}
</ListItemButton>
</ListItem>
{item.subItem && (
<SidebarListSubItem
item={item}
handleDrawerToggle={handleDrawerToggle}
/>
)}
</Fragment>
);
{item.type == "menu" &&
(item.showSubItem ? <ExpandLess/> : <ExpandMore/>)}
</ListItemButton>
</ListItem>
{item.subItem && (
<SidebarListSubItem
item={item}
handleDrawerToggle={handleDrawerToggle}
/>
)}
</Fragment>
);
};
export default SidebarListItem;

View File

@@ -1,54 +1,48 @@
import { NextLinkComposed } from "@/core/components/LinkRouting";
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";
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();
const SidebarListSubItem = ({item, handleDrawerToggle}) => {
const t = useTranslations();
return (
<Collapse in={item.showSubItem} timeout="auto" unmountOnExit>
<List component="div" disablePadding sx={{ bgcolor: "#f6f6f6" }}>
{item.subItem.map((subitem, index) => (
<Fragment key={subitem.key}>
<ListItemButton
component={NextLinkComposed}
to={{
pathname: subitem.route,
}}
sx={{
minHeight: 48,
}}
onClick={(event) => {
if (item.type == "menu") {
dispatch({ type: "COLLAPSE_MENU", key: item.key });
}
handleDrawerToggle();
}}
>
<ListItemIcon
sx={{
minWidth: 0,
justifyContent: "center",
pr: 2,
}}
>
<InboxIcon />
</ListItemIcon>
<ListItemText primary={t(subitem.key)} />
</ListItemButton>
</Fragment>
))}
</List>
</Collapse>
);
return (
<Collapse in={item.showSubItem} timeout="auto" unmountOnExit>
<List component="div" disablePadding sx={{bgcolor: "#f6f6f6"}}>
{item.subItem.map((subitem, index) => (
<Fragment key={subitem.key}>
<ListItemButton
component={NextLinkComposed}
to={{
pathname: subitem.route,
}}
sx={{
minHeight: 48,
}}
onClick={(event) => {
if (item.type == "menu") {
dispatch({type: "COLLAPSE_MENU", key: item.key});
}
handleDrawerToggle();
}}
>
<ListItemIcon
sx={{
minWidth: 0,
justifyContent: "center",
pr: 2,
}}
>
<InboxIcon/>
</ListItemIcon>
<ListItemText primary={t(subitem.key)}/>
</ListItemButton>
</Fragment>
))}
</List>
</Collapse>
);
};
export default SidebarListSubItem;

View File

@@ -1,46 +1,46 @@
import { Box, Drawer } from "@mui/material";
import {Box, Drawer} from "@mui/material";
import SidebarDrawer from "./SidebarDrawer";
const Sidebar = (props) => {
return (
<Box
component="nav"
sx={{ width: { md: props.drawerWidth }, flexShrink: { sm: 0 } }}
aria-label="mailbox folders"
>
<Drawer
container={props.container}
variant="temporary"
open={props.mobileOpen}
onClose={props.handleDrawerToggle}
ModalProps={{
keepMounted: true,
}}
sx={{
display: { xs: "block", md: "none" },
"& .MuiDrawer-paper": {
boxSizing: "border-box",
width: props.drawerWidth,
},
}}
>
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle} />
</Drawer>
<Drawer
variant="permanent"
sx={{
display: { xs: "none", md: "block" },
"& .MuiDrawer-paper": {
boxSizing: "border-box",
width: props.drawerWidth,
},
}}
open
>
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle} />
</Drawer>
</Box>
);
return (
<Box
component="nav"
sx={{width: {md: props.drawerWidth}, flexShrink: {sm: 0}}}
aria-label="mailbox folders"
>
<Drawer
container={props.container}
variant="temporary"
open={props.mobileOpen}
onClose={props.handleDrawerToggle}
ModalProps={{
keepMounted: true,
}}
sx={{
display: {xs: "block", md: "none"},
"& .MuiDrawer-paper": {
boxSizing: "border-box",
width: props.drawerWidth,
},
}}
>
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle}/>
</Drawer>
<Drawer
variant="permanent"
sx={{
display: {xs: "none", md: "block"},
"& .MuiDrawer-paper": {
boxSizing: "border-box",
width: props.drawerWidth,
},
}}
open
>
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle}/>
</Drawer>
</Box>
);
};
export default Sidebar;

View File

@@ -1,99 +1,99 @@
import { FA_DATATABLE_LOCALIZATION } from "&/locales/fa/datatable";
import { useRouter } from "next/router";
import { createContext, useEffect, useState } from "react";
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,
export const LanguageProvider = ({children}) => {
const router = useRouter();
const languageList = [
{
locale: languageApp,
key: "fa",
dir: "rtl",
name: "فارسی",
fontFamily: `IRANSans, sans-serif`,
tableLocalization: FA_DATATABLE_LOCALIZATION,
}
);
return;
}
for (const lang of languageList) {
if (languageApp != lang.key) continue;
setDirectionApp(lang.dir);
document.dir = lang.dir;
}
];
const {user, userChangedLanguage, changeLanguageState} = useUser();
const [languageIsReady, setLanguageIsReady] = useState(false);
const [languageApp, setLanguageApp] = useState();
const [directionApp, setDirectionApp] = useState(
process.env.NEXT_PUBLIC_DEFAULT_DIRECTION
);
const timer = setTimeout(() => {
changeLanguageState(false);
setLanguageIsReady(true);
}, 1000);
useEffect(() => {
const lang = localStorage.getItem("_language");
return () => {
clearTimeout(timer);
};
}, [router.locale, router.isReady, userChangedLanguage, languageApp]);
if (!lang && !languageApp) {
setLanguageApp(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE);
} else if (lang) {
setLanguageApp(lang);
}
}, []);
return (
<LanguageContext.Provider
value={{
languageApp,
setLanguageApp,
directionApp,
languageIsReady,
setLanguageIsReady,
languageList,
}}
>
{children}
</LanguageContext.Provider>
);
useEffect(() => {
if (!languageApp) return;
const lang = localStorage.getItem("_language");
if (!lang) {
localStorage.setItem("_language", languageApp);
} else {
if (languageApp != lang) {
localStorage.setItem("_language", languageApp);
}
}
}, [languageApp]);
useEffect(() => {
if (!router.isReady) return;
if (user.user_language) {
if (user.user_language != languageApp) {
setLanguageApp(user.user_language);
return;
}
}
if (languageApp != router.locale) {
router.replace(
{pathname: router.pathname, query: router.query},
router.asPath,
{
locale: languageApp,
}
);
return;
}
for (const lang of languageList) {
if (languageApp != lang.key) continue;
setDirectionApp(lang.dir);
document.dir = lang.dir;
}
const timer = setTimeout(() => {
changeLanguageState(false);
setLanguageIsReady(true);
}, 1000);
return () => {
clearTimeout(timer);
};
}, [router.locale, router.isReady, userChangedLanguage, languageApp]);
return (
<LanguageContext.Provider
value={{
languageApp,
setLanguageApp,
directionApp,
languageIsReady,
setLanguageIsReady,
languageList,
}}
>
{children}
</LanguageContext.Provider>
);
};

View File

@@ -1,14 +1,14 @@
import LoadingHardPage from "@/core/components/LoadingHardPage";
import { createContext, useState } from "react";
import {createContext, useState} from "react";
export const LoadingContext = createContext();
export const LoadingProvider = ({ children }) => {
const [loadingPage, setLoadingPage] = useState(false);
return (
<LoadingContext.Provider value={{ loadingPage, setLoadingPage }}>
<LoadingHardPage loading={loadingPage} />
{children}
</LoadingContext.Provider>
);
export const LoadingProvider = ({children}) => {
const [loadingPage, setLoadingPage] = useState(false);
return (
<LoadingContext.Provider value={{loadingPage, setLoadingPage}}>
<LoadingHardPage loading={loadingPage}/>
{children}
</LoadingContext.Provider>
);
};

View File

@@ -1,121 +1,122 @@
import { USER_INFO } from "@/core/data/apiRoutes";
import {USER_INFO} from "@/core/data/apiRoutes";
import axios from "axios";
import { createContext, useCallback, useEffect, useReducer } from "react";
import {createContext, useCallback, useEffect, useReducer} from "react";
const initialUser = {
isAuth: false,
userChangedLanguage: false,
token: null,
user: {},
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;
}
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);
export const UserProvider = ({children}) => {
const [state, dispatch] = useReducer(reducer, initialUser);
const clearUser = useCallback(() => {
dispatch({ type: "CLEAR_USER" });
}, []);
const clearUser = useCallback(() => {
dispatch({type: "CLEAR_USER"});
}, []);
const changeUser = useCallback((user) => {
dispatch({ type: "CHANGE_USER", user });
}, []);
const changeUser = useCallback((user) => {
dispatch({type: "CHANGE_USER", user});
}, []);
const changeUserLanguage = useCallback(/* for multi language app */);
const changeUserLanguage = useCallback(/* for multi language app */);
const changeAuthState = useCallback((isAuth) => {
dispatch({ type: "CHANGE_AUTH_STATE", isAuth });
}, []);
const changeAuthState = useCallback((isAuth) => {
dispatch({type: "CHANGE_AUTH_STATE", isAuth});
}, []);
const changeLanguageState = useCallback((userChangedLanguage) => {
dispatch({ type: "CHANGE_LANGUAGE_STATE", userChangedLanguage });
}, []);
const changeLanguageState = useCallback((userChangedLanguage) => {
dispatch({type: "CHANGE_LANGUAGE_STATE", userChangedLanguage});
}, []);
const clearToken = useCallback(() => {
dispatch({ type: "CLEAR_TOKEN" });
}, []);
const clearToken = useCallback(() => {
dispatch({type: "CLEAR_TOKEN"});
}, []);
const setToken = useCallback((token) => {
dispatch({ type: "SET_TOKEN", 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);
const getUser = useCallback(
(callback = () => {
}) => {
axios
.get(USER_INFO, {
headers: {authorization: `Bearer ${state.token}`},
})
.then(({data}) => {
if (typeof callback === "function") callback(data);
});
},
[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]
);
}, [state.token]);
useEffect(() => {
const localToken = localStorage.getItem("_token");
if (localToken) dispatch({ type: "SET_TOKEN", token: localToken });
}, []);
useEffect(() => {
if (!state.token) {
clearUser();
changeAuthState(false);
changeLanguageState(false);
return;
}
getUser((data) => {
changeUser(data);
changeAuthState(true);
changeLanguageState(true);
});
}, [state.token]);
return (
<UserContext.Provider
value={{
isAuth: state.isAuth,
userChangedLanguage: state.userChangedLanguage,
token: state.token,
user: state.user,
getUser,
clearUser,
changeUser,
changeUserLanguage,
changeAuthState,
changeLanguageState,
clearToken,
setToken,
}}
>
{children}
</UserContext.Provider>
);
return (
<UserContext.Provider
value={{
isAuth: state.isAuth,
userChangedLanguage: state.userChangedLanguage,
token: state.token,
user: state.user,
getUser,
clearUser,
changeUser,
changeUserLanguage,
changeAuthState,
changeLanguageState,
clearToken,
setToken,
}}
>
{children}
</UserContext.Provider>
);
};

View File

@@ -1,10 +1,10 @@
import { useContext } from "react";
import { LanguageContext } from "../contexts/language";
import {useContext} from "react";
import {LanguageContext} from "../contexts/language";
const useDirection = () => {
const { directionApp } = useContext(LanguageContext);
const {directionApp} = useContext(LanguageContext);
return { directionApp };
return {directionApp};
};
export default useDirection;

View File

@@ -1,28 +1,28 @@
import { useContext } from "react";
import { LanguageContext } from "../contexts/language";
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 {isAuth, changeUserLanguage} = useUser();
const {
languageApp,
setLanguageApp,
languageIsReady,
setLanguageIsReady,
languageList,
} = useContext(LanguageContext);
const changeLanguage = (lang) => {
if (lang == languageApp) return;
const changeLanguage = (lang) => {
if (lang == languageApp) return;
setLanguageIsReady(false);
setLanguageApp(lang);
if (isAuth) {
changeUserLanguage(lang);
}
};
setLanguageIsReady(false);
setLanguageApp(lang);
if (isAuth) {
changeUserLanguage(lang);
}
};
return { languageApp, changeLanguage, languageIsReady, languageList };
return {languageApp, changeLanguage, languageIsReady, languageList};
};
export default useLanguage;

View File

@@ -1,10 +1,10 @@
import { useContext } from "react";
import { LoadingContext } from "../contexts/loading";
import {useContext} from "react";
import {LoadingContext} from "../contexts/loading";
const useLoading = () => {
const { setLoadingPage } = useContext(LoadingContext);
const {setLoadingPage} = useContext(LoadingContext);
return { setLoadingPage };
return {setLoadingPage};
};
export default useLoading;

View File

@@ -1,36 +1,36 @@
import { useContext } from "react";
import { UserContext } from "../contexts/user";
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);
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,
};
return {
isAuth,
userChangedLanguage,
token,
user,
getUser,
clearUser,
changeUser,
changeUserLanguage,
changeAuthState,
changeLanguageState,
clearToken,
setToken,
};
};
export default useUser;

View File

@@ -1,41 +1,41 @@
import { NextLinkComposed } from "@/core/components/LinkRouting";
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";
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();
const WithAuthMiddleware = ({children}) => {
const {isAuth} = useUser();
const t = useTranslations();
const router = useRouter();
if (!isAuth)
return (
<Message
text={
<Typography sx={{ textAlign: "center" }}>
{t(
"Authorization.typography_your_access_to_this_page_has_expired_Please_login_again"
)}
</Typography>
}
actions={
<>
<Button
variant="contained"
component={NextLinkComposed}
to={{
pathname: "/",
}}
>
{t("login")}
</Button>
</>
}
/>
);
return <>{children}</>;
if (!isAuth)
return (
<Message
text={
<Typography sx={{textAlign: "center"}}>
{t(
"Authorization.typography_your_access_to_this_page_has_expired_Please_login_again"
)}
</Typography>
}
actions={
<>
<Button
variant="contained"
component={NextLinkComposed}
to={{
pathname: "/",
}}
>
{t("login")}
</Button>
</>
}
/>
);
return <>{children}</>;
};
export default WithAuthMiddleware;

View File

@@ -1,56 +1,56 @@
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";
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();
const WithoutAuthMiddleware = ({children}) => {
const {isAuth} = useUser();
const t = useTranslations();
const router = useRouter();
// gettin url query
const searchParams = useSearchParams();
const backUrlDecodedPath = searchParams.get("back_url");
// 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);
useEffect(() => {
if (!isAuth) return;
const timer = setTimeout(() => {
router.replace(
backUrlDecodedPath
? decodeURIComponent(backUrlDecodedPath)
: "/dashboard"
);
}, 2000);
return () => {
clearTimeout(timer);
};
}, [isAuth]);
return () => {
clearTimeout(timer);
};
}, [isAuth]);
if (isAuth)
return (
<Message
text={
<Stack alignItems="center" spacing={2}>
<Typography sx={{ textAlign: "center" }}>
{t(
"Authorization.typography_your_login_is_valid_and_you_do_not_need_to_login_again"
)}
</Typography>
<Typography>
{t("Authorization.typography_redirect_to")}{" "}
{backUrlDecodedPath
? t("Authorization.typography_routing_previuos_page")
: t("Authorization.typography_routing_dashbaord_page")}
</Typography>
</Stack>
}
/>
);
return <>{children}</>;
if (isAuth)
return (
<Message
text={
<Stack alignItems="center" spacing={2}>
<Typography sx={{textAlign: "center"}}>
{t(
"Authorization.typography_your_login_is_valid_and_you_do_not_need_to_login_again"
)}
</Typography>
<Typography>
{t("Authorization.typography_redirect_to")}{" "}
{backUrlDecodedPath
? t("Authorization.typography_routing_previuos_page")
: t("Authorization.typography_routing_dashbaord_page")}
</Typography>
</Stack>
}
/>
);
return <>{children}</>;
};
export default WithoutAuthMiddleware;

View File

@@ -2,12 +2,12 @@ import NotFoundComponent from "@/components/not-found";
import Head from "next/head";
export default function NotFound() {
return (
<>
<Head>
<title>یافت نشد</title>
</Head>
<NotFoundComponent />
</>
);
return (
<>
<Head>
<title>یافت نشد</title>
</Head>
<NotFoundComponent/>
</>
);
}

View File

@@ -1,30 +1,30 @@
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 {LanguageProvider} from "@/lib/app/contexts/language";
import {LoadingProvider} from "@/lib/app/contexts/loading";
import {UserProvider} from "@/lib/app/contexts/user";
import "moment/locale/fa";
import { NextIntlProvider } from "next-intl";
import {NextIntlProvider} from "next-intl";
const App = ({ Component, pageProps }) => {
return (
<>
<UserProvider>
<LanguageProvider>
<NextIntlProvider messages={pageProps.messages}>
<MuiLayout isBot={pageProps.isBot}>
<LoadingProvider>
<AppLayout isBot={pageProps.isBot}>
<Component {...pageProps} />
</AppLayout>
</LoadingProvider>
</MuiLayout>
</NextIntlProvider>
</LanguageProvider>
</UserProvider>
</>
);
const App = ({Component, pageProps}) => {
return (
<>
<UserProvider>
<LanguageProvider>
<NextIntlProvider messages={pageProps.messages}>
<MuiLayout isBot={pageProps.isBot}>
<LoadingProvider>
<AppLayout isBot={pageProps.isBot}>
<Component {...pageProps} />
</AppLayout>
</LoadingProvider>
</MuiLayout>
</NextIntlProvider>
</LanguageProvider>
</UserProvider>
</>
);
};
export default App;

View File

@@ -1,67 +1,65 @@
import {
createEmotionCacheLtr
} from "@/core/utils/createEmotionCache";
import {createEmotionCacheLtr} 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 Document, {Head, Html, Main, NextScript} from "next/document";
export default function MyDocument(props) {
const { emotionStyleTags } = props;
const {emotionStyleTags} = props;
return (
<Html>
<Head>
<meta name="theme-color" content={theme.palette.primary.main} />
<meta name="emotion-insertion-point" content="" />
<link rel="shortcut icon" href="/icons/favicon.ico" />
<link rel="manifest" href="/manifest.json" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
{emotionStyleTags}
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
return (
<Html>
<Head>
<meta name="theme-color" content={theme.palette.primary.main}/>
<meta name="emotion-insertion-point" content=""/>
<link rel="shortcut icon" href="/icons/favicon.ico"/>
<link rel="manifest" href="/manifest.json"/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
{emotionStyleTags}
</Head>
<body>
<Main/>
<NextScript/>
</body>
</Html>
);
}
MyDocument.getInitialProps = async (ctx) => {
const originalRenderPage = ctx.renderPage;
let cache;
switch (ctx.locale) {
case "fa":
cache = createEmotionCacheLtr();
break;
}
const originalRenderPage = ctx.renderPage;
let cache;
switch (ctx.locale) {
case "fa":
cache = createEmotionCacheLtr();
break;
}
const { extractCriticalToChunks } = createEmotionServer(cache);
const {extractCriticalToChunks} = createEmotionServer(cache);
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) =>
function EnhanceApp(props) {
return <App emotionCache={cache} {...props} />;
},
});
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) =>
function EnhanceApp(props) {
return <App emotionCache={cache} {...props} />;
},
});
const initialProps = await Document.getInitialProps(ctx);
const initialProps = await Document.getInitialProps(ctx);
const emotionStyles = extractCriticalToChunks(initialProps.html);
const emotionStyleTags = emotionStyles.styles.map((style) => (
<style
data-emotion={`${style.key} ${style.ids.join(" ")}`}
key={style.key}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: style.css }}
/>
));
const emotionStyles = extractCriticalToChunks(initialProps.html);
const emotionStyleTags = emotionStyles.styles.map((style) => (
<style
data-emotion={`${style.key} ${style.ids.join(" ")}`}
key={style.key}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{__html: style.css}}
/>
));
return {
...initialProps,
emotionStyleTags,
};
return {
...initialProps,
emotionStyleTags,
};
};

View File

@@ -1,23 +1,23 @@
import DashboardFirstComponent from "@/components/dashboard/first";
import TitlePage from "@/core/components/TitlePage";
import WithAuthMiddleware from "@/middlewares/WithAuth";
import { parse } from "next-useragent";
import {parse} from "next-useragent";
export default function Dashboard() {
return (
<WithAuthMiddleware>
<TitlePage text="Dashboard.dashboard_page" />
<DashboardFirstComponent />
</WithAuthMiddleware>
);
return (
<WithAuthMiddleware>
<TitlePage text="Dashboard.dashboard_page"/>
<DashboardFirstComponent/>
</WithAuthMiddleware>
);
}
export async function getServerSideProps({ req, locale }) {
const { isBot } = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
export async function getServerSideProps({req, locale}) {
const {isBot} = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
}

View File

@@ -1,23 +1,23 @@
import DashboardLoanFollowUpComponent from "@/components/dashboard/loan-follow-up";
import TitlePage from "@/core/components/TitlePage";
import WithAuthMiddleware from "@/middlewares/WithAuth";
import { parse } from "next-useragent";
import {parse} from "next-useragent";
export default function LoanFollowUp() {
return (
<WithAuthMiddleware>
<TitlePage text="LoanFollowUp.loan_follow_up_page" />
<DashboardLoanFollowUpComponent />
</WithAuthMiddleware>
);
return (
<WithAuthMiddleware>
<TitlePage text="LoanFollowUp.loan_follow_up_page"/>
<DashboardLoanFollowUpComponent/>
</WithAuthMiddleware>
);
}
export async function getServerSideProps({ req, locale }) {
const { isBot } = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
export async function getServerSideProps({req, locale}) {
const {isBot} = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
}

View File

@@ -1,23 +1,23 @@
import DashboardLoanRequestComponent from "@/components/dashboard/loan-request";
import TitlePage from "@/core/components/TitlePage";
import WithAuthMiddleware from "@/middlewares/WithAuth";
import { parse } from "next-useragent";
import {parse} from "next-useragent";
export default function LoanRequest() {
return (
<WithAuthMiddleware>
<TitlePage text="LoanFollowUp.loan_follow_up_page" />
<DashboardLoanRequestComponent />
</WithAuthMiddleware>
);
return (
<WithAuthMiddleware>
<TitlePage text="LoanFollowUp.loan_follow_up_page"/>
<DashboardLoanRequestComponent/>
</WithAuthMiddleware>
);
}
export async function getServerSideProps({ req, locale }) {
const { isBot } = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
export async function getServerSideProps({req, locale}) {
const {isBot} = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
}

View File

@@ -1,22 +1,22 @@
import FirstComponent from "@/components/first";
import TitlePage from "@/core/components/TitlePage";
import { parse } from "next-useragent";
import {parse} from "next-useragent";
export default function Home() {
return (
<>
<TitlePage text="first_page" />
<FirstComponent />
</>
);
return (
<>
<TitlePage text="first_page"/>
<FirstComponent/>
</>
);
}
export async function getServerSideProps({ req, locale }) {
const { isBot } = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
export async function getServerSideProps({req, locale}) {
const {isBot} = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
}

View File

@@ -1,28 +1,28 @@
import LoginComponent from "@/components/login";
import TitlePage from "@/core/components/TitlePage";
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
import { parse } from "next-useragent";
import {parse} from "next-useragent";
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify";
import {ToastContainer} from "react-toastify";
import useDirection from "@/lib/app/hooks/useDirection";
export default function Login() {
const { directionApp } = useDirection();
return (
<WithoutAuthMiddleware>
<TitlePage text="Titles.title_login_page" />
<LoginComponent />
{directionApp === "rtl" ? <ToastContainer rtl /> : <ToastContainer ltr />}
</WithoutAuthMiddleware>
);
const {directionApp} = useDirection();
return (
<WithoutAuthMiddleware>
<TitlePage text="Titles.title_login_page"/>
<LoginComponent/>
{directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
</WithoutAuthMiddleware>
);
}
export async function getServerSideProps({ req, locale }) {
const { isBot } = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
export async function getServerSideProps({req, locale}) {
const {isBot} = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
}

View File

@@ -1,28 +1,28 @@
import RegisterComponent from "@/components/register";
import TitlePage from "@/core/components/TitlePage";
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
import { parse } from "next-useragent";
import {parse} from "next-useragent";
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify";
import {ToastContainer} from "react-toastify";
import useDirection from "@/lib/app/hooks/useDirection";
export default function Register() {
const { directionApp } = useDirection();
return (
<WithoutAuthMiddleware>
<TitlePage text="Titles.title_register_page" />
<RegisterComponent />
{directionApp === "rtl" ? <ToastContainer rtl /> : <ToastContainer ltr />}
</WithoutAuthMiddleware>
);
const {directionApp} = useDirection();
return (
<WithoutAuthMiddleware>
<TitlePage text="Titles.title_register_page"/>
<RegisterComponent/>
{directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
</WithoutAuthMiddleware>
);
}
export async function getServerSideProps({ req, locale }) {
const { isBot } = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
export async function getServerSideProps({req, locale}) {
const {isBot} = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
}

View File

@@ -1,28 +1,28 @@
import NavyComponent from "@/components/register/navy";
import TitlePage from "@/core/components/TitlePage";
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
import { parse } from "next-useragent";
import {parse} from "next-useragent";
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify";
import {ToastContainer} from "react-toastify";
import useDirection from "@/lib/app/hooks/useDirection";
export default function Register() {
const { directionApp } = useDirection();
return (
<WithoutAuthMiddleware>
<TitlePage text="Titles.title_register_navy_page" />
<NavyComponent />
{directionApp === "rtl" ? <ToastContainer rtl /> : <ToastContainer ltr />}
</WithoutAuthMiddleware>
);
const {directionApp} = useDirection();
return (
<WithoutAuthMiddleware>
<TitlePage text="Titles.title_register_navy_page"/>
<NavyComponent/>
{directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
</WithoutAuthMiddleware>
);
}
export async function getServerSideProps({ req, locale }) {
const { isBot } = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
export async function getServerSideProps({req, locale}) {
const {isBot} = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
}

View File

@@ -1,28 +1,28 @@
import WelfareServicesComponent from "@/components/register/welfare-services";
import TitlePage from "@/core/components/TitlePage";
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
import { parse } from "next-useragent";
import {parse} from "next-useragent";
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify";
import {ToastContainer} from "react-toastify";
import useDirection from "@/lib/app/hooks/useDirection";
export default function Register() {
const { directionApp } = useDirection();
return (
<WithoutAuthMiddleware>
<TitlePage text="Titles.title_register_welfare_services_page" />
<WelfareServicesComponent />
{directionApp === "rtl" ? <ToastContainer rtl /> : <ToastContainer ltr />}
</WithoutAuthMiddleware>
);
const {directionApp} = useDirection();
return (
<WithoutAuthMiddleware>
<TitlePage text="Titles.title_register_welfare_services_page"/>
<WelfareServicesComponent/>
{directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
</WithoutAuthMiddleware>
);
}
export async function getServerSideProps({ req, locale }) {
const { isBot } = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
export async function getServerSideProps({req, locale}) {
const {isBot} = parse(req.headers["user-agent"]);
return {
props: {
messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot,
},
};
}