use witel webapp builder
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
images: {
|
images: {
|
||||||
domains: ['loan.witel.ir', /* other domains */],
|
domains: [process.env.NEXT_PUBLIC_BASE_URL],
|
||||||
},
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultLocale: 'fa',
|
defaultLocale: 'fa',
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
"@mui/icons-material": "^5.11.16",
|
"@mui/icons-material": "^5.11.16",
|
||||||
"@mui/lab": "^5.0.0-alpha.152",
|
"@mui/lab": "^5.0.0-alpha.152",
|
||||||
"@mui/material": "^5.12.0",
|
"@mui/material": "^5.12.0",
|
||||||
|
"@witel/webapp-builder": "^1.0.2",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"colord": "^2.9.3",
|
"colord": "^2.9.3",
|
||||||
"eslint": "8.36.0",
|
"eslint": "8.36.0",
|
||||||
|
|||||||
2
public/global.scss
Normal file
2
public/global.scss
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
@import "fontiran";
|
||||||
|
@import 'react-toastify/dist/ReactToastify.css';
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"short_name": "Loan Facilities Dashboard",
|
"short_name": "Loan Facilities",
|
||||||
"name": "Loan Facilities User Dashboard",
|
"name": "Loan Facilities User Dashboard",
|
||||||
"description": "Loan Facilities",
|
"description": "Loan Facilities",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
|
||||||
|
|
||||||
const FirstComponent = () => {
|
const FirstComponent = () => {
|
||||||
return <DashboardLayouts></DashboardLayouts>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FirstComponent;
|
export default FirstComponent;
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import CenterLayout from "@/layouts/CenterLayout";
|
|
||||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
|
||||||
import {Button, Typography} from "@mui/material";
|
import {Button, Typography} from "@mui/material";
|
||||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
|
||||||
import {useTranslations} from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import TitlePage from "@/core/components/TitlePage";
|
import TitlePage from "@/core/components/TitlePage";
|
||||||
import Svg403 from "@/core/components/svgs/Svg403";
|
import Svg403 from "@/core/components/svgs/Svg403";
|
||||||
|
import {CenterLayout, FullPageLayout, NextLinkComposed} from "@witel/webapp-builder";
|
||||||
|
|
||||||
const UnAuthorizedComponent = () => {
|
const UnAuthorizedComponent = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import CenterLayout from "@/layouts/CenterLayout";
|
|
||||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
|
||||||
import {Button, Typography} from "@mui/material";
|
import {Button, Typography} from "@mui/material";
|
||||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
|
||||||
import {useTranslations} from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import TitlePage from "@/core/components/TitlePage";
|
import TitlePage from "@/core/components/TitlePage";
|
||||||
import Svg404 from "@/core/components/svgs/Svg404";
|
import Svg404 from "@/core/components/svgs/Svg404";
|
||||||
|
import {CenterLayout, FullPageLayout, NextLinkComposed} from "@witel/webapp-builder";
|
||||||
|
|
||||||
const NotFoundComponent = () => {
|
const NotFoundComponent = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import CenterLayout from "@/layouts/CenterLayout";
|
|
||||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
|
||||||
import {Button, Typography} from "@mui/material";
|
import {Button, Typography} from "@mui/material";
|
||||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
|
||||||
import {useTranslations} from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import TitlePage from "@/core/components/TitlePage";
|
import TitlePage from "@/core/components/TitlePage";
|
||||||
import Svg500 from "@/core/components/svgs/Svg500";
|
import Svg500 from "@/core/components/svgs/Svg500";
|
||||||
|
import {CenterLayout, FullPageLayout, NextLinkComposed} from "@witel/webapp-builder";
|
||||||
|
|
||||||
const ServerErrorComponent = () => {
|
const ServerErrorComponent = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|||||||
@@ -1,23 +1,24 @@
|
|||||||
import {Box, Button, Container, Grid, Stack, Typography} from "@mui/material";
|
import {Box, Button, Container, Grid, Stack, Typography} from "@mui/material";
|
||||||
import LinkRouting from "@/core/components/LinkRouting";
|
|
||||||
import {useTranslations} from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
import {LinkRouting} from "@witel/webapp-builder";
|
||||||
|
|
||||||
const FooterDetails = () => {
|
const FooterDetails = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
return(
|
return (
|
||||||
<Box sx={{backgroundColor : 'black', color : 'white'}}>
|
<Box sx={{backgroundColor: 'black', color: 'white'}}>
|
||||||
<Container sx={{py : 2}} maxWidth="xl">
|
<Container sx={{py: 2}} maxWidth="xl">
|
||||||
<Grid container sx={{py : 2}}>
|
<Grid container sx={{py: 2}}>
|
||||||
<Grid item xs={12} md={8}>
|
<Grid item xs={12} md={8}>
|
||||||
<Button disabled>
|
<Button disabled>
|
||||||
<Typography color={'white'}>کلیه حقوق محفوظ و متعلق به سازمان راهداری و حمل و نقل جاده ای می باشد</Typography>
|
<Typography color={'white'}>کلیه حقوق محفوظ و متعلق به سازمان راهداری و حمل و نقل جاده ای می
|
||||||
|
باشد</Typography>
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} md={4}>
|
<Grid item xs={12} md={4}>
|
||||||
<Stack direction="row" alignItems="center" justifyContent="center">
|
<Stack direction="row" alignItems="center" justifyContent="center">
|
||||||
<img src='/icons/logoLandingPage.png' width={25} alt="Your Alt Text" />
|
<img src='/icons/logoLandingPage.png' width={25} alt="Your Alt Text"/>
|
||||||
<LinkRouting
|
<LinkRouting
|
||||||
sx={{margin: 0.5, fontSize: "20px", color : "white"}}
|
sx={{margin: 0.5, fontSize: "20px", color: "white"}}
|
||||||
href={process.env.NEXT_PUBLIC_POWERED_BY_URL}
|
href={process.env.NEXT_PUBLIC_POWERED_BY_URL}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
underline="hover"
|
underline="hover"
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import {Box, Button, Container, Grid} from "@mui/material";
|
import {Box, Button, Container, Grid} from "@mui/material";
|
||||||
|
|
||||||
const HeaderDetails = () => {
|
const HeaderDetails = () => {
|
||||||
return(
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Container sx={{py : 3}} maxWidth="xl">
|
<Container sx={{py: 3}} maxWidth="xl">
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item sx={12} md={8}>
|
<Grid item xs={12} md={8}>
|
||||||
<Button startIcon={<img src='/icons/headerLogo.png' alt='icon'/>} />
|
<Button startIcon={<img src='/icons/headerLogo.png' alt='icon'/>}/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -1,39 +1,43 @@
|
|||||||
import {Box, Button, Chip, Container, Grid, Link, Stack, Typography} from "@mui/material";
|
import {Box, Button, Chip, Container, Grid, Link, Typography} from "@mui/material";
|
||||||
import {useTranslations} from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import DownloadIcon from '@mui/icons-material/Download';
|
import DownloadIcon from '@mui/icons-material/Download';
|
||||||
|
|
||||||
const LoanCondition = () => {
|
const LoanCondition = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
return(
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Container sx={{py : 3}} maxWidth="xl">
|
<Container sx={{py: 3}} maxWidth="xl">
|
||||||
<Typography sx={{my : 3}} variant={'h3'}>
|
<Typography sx={{my: 3}} variant={'h3'}>
|
||||||
تخصیص وام
|
تخصیص وام
|
||||||
</Typography>
|
</Typography>
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item xs={12} md={8}>
|
<Grid item xs={12} md={8}>
|
||||||
<Box sx={{padding : 3}}>
|
<Box sx={{padding: 3}}>
|
||||||
<Typography variant={'h5'}>
|
<Typography variant={'h5'}>
|
||||||
قوانین دریافت وام
|
قوانین دریافت وام
|
||||||
</Typography>
|
</Typography>
|
||||||
<Grid item sx={{my : 2}} spacing={2}>
|
<Grid item sx={{my: 2}}>
|
||||||
<Chip sx={{m : 1}} label="1 . فقط به زوجین ایرانی تعلق میگیرد" />
|
<Chip sx={{m: 1}} label="1 . فقط به زوجین ایرانی تعلق میگیرد"/>
|
||||||
<Chip sx={{m : 1}} label="2 . فقط به زوجین ایرانی تعلق میگیرد" />
|
<Chip sx={{m: 1}} label="2 . فقط به زوجین ایرانی تعلق میگیرد"/>
|
||||||
<Chip sx={{m : 1}} label="3 . فقط به زوجین ایرانی تعلق میگیرد" />
|
<Chip sx={{m: 1}} label="3 . فقط به زوجین ایرانی تعلق میگیرد"/>
|
||||||
<Chip sx={{m : 1}} label="4 . فقط به زوجین ایرانی تعلق میگیرد" />
|
<Chip sx={{m: 1}} label="4 . فقط به زوجین ایرانی تعلق میگیرد"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Typography textAlign={'justify'}> این یکی از محبوبترین انواع وام در ایران است. دلیل این محبوبیت سرعت آن در پرداخت و سود بسیار پایین آن است.
|
<Typography textAlign={'justify'}> این یکی از محبوبترین انواع وام در ایران است. دلیل این
|
||||||
|
محبوبیت سرعت آن در پرداخت و سود بسیار پایین آن است.
|
||||||
تنها یک شرط برای اخذ این وام وجود دارد و آن این است که باید به تازگی ازدواج کرده باشید.
|
تنها یک شرط برای اخذ این وام وجود دارد و آن این است که باید به تازگی ازدواج کرده باشید.
|
||||||
همچنین فقط یک بار از این وام میتوانید استفاده کنید. یعنی این وام فقط یک بار به هر فرد تعلق میگیرد.
|
همچنین فقط یک بار از این وام میتوانید استفاده کنید. یعنی این وام فقط یک بار به هر فرد
|
||||||
محل تامین بودجه آن حسابهای قرض الحسنهایست که افراد در بانکها باز میکنند و مرجع اصلی آرائه آن، بانک مرکزی است.
|
تعلق میگیرد.
|
||||||
|
محل تامین بودجه آن حسابهای قرض الحسنهایست که افراد در بانکها باز میکنند و مرجع اصلی
|
||||||
|
آرائه آن، بانک مرکزی است.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid sx={{display : 'flex' , alignItems : "center", justifyContent : "center"}} item xs={12} md={4}>
|
<Grid sx={{display: 'flex', alignItems: "center", justifyContent: "center"}} item xs={12} md={4}>
|
||||||
<Box>
|
<Box>
|
||||||
<Button variant="contained" startIcon={<DownloadIcon />}>
|
<Button variant="contained" startIcon={<DownloadIcon/>}>
|
||||||
<Link
|
<Link
|
||||||
variant="subtitle1"
|
variant="subtitle1"
|
||||||
sx={{padding : 1}}
|
sx={{padding: 1}}
|
||||||
color={'white'}
|
color={'white'}
|
||||||
download
|
download
|
||||||
underline="none"
|
underline="none"
|
||||||
|
|||||||
@@ -1,31 +1,39 @@
|
|||||||
import {Box, Container, Grid, Typography} from "@mui/material";
|
import {Box, Container, Grid, Typography} from "@mui/material";
|
||||||
import {Timeline, TimelineConnector, TimelineContent, TimelineDot, TimelineItem, TimelineSeparator} from "@mui/lab";
|
|
||||||
import {useTranslations} from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import TimeLineDetails from "@/components/first/LoanDescription/TimeLineDetails";
|
import TimeLineDetails from "@/components/first/LoanDescription/TimeLineDetails";
|
||||||
|
|
||||||
const LoanDescription = () => {
|
const LoanDescription = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
return(
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Container sx={{py : 3}} maxWidth="xl">
|
<Container sx={{py: 3}} maxWidth="xl">
|
||||||
<Typography sx={{my : 3}} variant={'h3'}>
|
<Typography sx={{my: 3}} variant={'h3'}>
|
||||||
توضیحات دریافت وام
|
توضیحات دریافت وام
|
||||||
</Typography>
|
</Typography>
|
||||||
<Grid sx={{py : 2}} container spacing={2}>
|
<Grid sx={{py: 2}} container spacing={2}>
|
||||||
<Grid item xs={12} md={7}>
|
<Grid item xs={12} md={7}>
|
||||||
<Typography variant={'subtitle1'} textAlign={'justify'}>
|
<Typography variant={'subtitle1'} textAlign={'justify'}>
|
||||||
وام خرید کالای مهر ایران یا کالا کارت با هدف خرید مایحتاج خانه و کالاهای ضروری زندگی داده میشود. سقف کالا کارت ۱۵۰ میلیون تومان و سود آن ۴ درصد است.
|
وام خرید کالای مهر ایران یا کالا کارت با هدف خرید مایحتاج خانه و کالاهای ضروری زندگی داده
|
||||||
|
میشود. سقف کالا کارت ۱۵۰ میلیون تومان و سود آن ۴ درصد است.
|
||||||
با دریافت کالا کارت میتوانید وسایل موردنیازتان را از فروشگاههای طرف قرارداد
|
با دریافت کالا کارت میتوانید وسایل موردنیازتان را از فروشگاههای طرف قرارداد
|
||||||
این فروشگاهها با نام گلدیران در شهرهای تهران، شیراز، اهواز، نور، اصفهان، تبریز، ساری و رشت فعالیت میکنند.
|
این فروشگاهها با نام گلدیران در شهرهای تهران، شیراز، اهواز، نور، اصفهان، تبریز، ساری و رشت
|
||||||
طبق قوانین جدید و در راستای حمایت از طرح افزایش جمیعت، مبلغ آن برای زوجینی که مرد زیر ۲۵ سال و زن زیر ۲۳ سال داشته باشد، <Typography sx={{color : "secondary.main"}} variant={'h5'} fontWeight={'bold'} component={'span'}>440</Typography> میلیون یا ۲۲۰ میلیون به ازای هر نفر است.
|
فعالیت میکنند.
|
||||||
|
طبق قوانین جدید و در راستای حمایت از طرح افزایش جمیعت، مبلغ آن برای زوجینی که مرد زیر ۲۵ سال
|
||||||
|
و زن زیر ۲۳ سال داشته باشد، <Typography sx={{color: "secondary.main"}} variant={'h5'}
|
||||||
|
fontWeight={'bold'}
|
||||||
|
component={'span'}>440</Typography> میلیون یا ۲۲۰
|
||||||
|
میلیون به ازای هر نفر است.
|
||||||
در این قانون هریک از زوجین که شرایط آنها در این قانون نگنجد،
|
در این قانون هریک از زوجین که شرایط آنها در این قانون نگنجد،
|
||||||
مبلغ تغییر کرده و به زوج <Typography sx={{color : "secondary.main"}} variant={'h5'} fontWeight={'bold'} component={'span'}>400</Typography> میلیون وام تعلق خواهد گرفت.
|
مبلغ تغییر کرده و به زوج <Typography sx={{color: "secondary.main"}} variant={'h5'}
|
||||||
|
fontWeight={'bold'}
|
||||||
|
component={'span'}>400</Typography> میلیون وام تعلق
|
||||||
|
خواهد گرفت.
|
||||||
حداکثر زمان بازپرداخت وام خرید کالا ۲۴ ماه است و برای گرفتن آن به یک ضامن رسمی احتیاج دارید.
|
حداکثر زمان بازپرداخت وام خرید کالا ۲۴ ماه است و برای گرفتن آن به یک ضامن رسمی احتیاج دارید.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} md={5}>
|
<Grid item xs={12} md={5}>
|
||||||
<Box>
|
<Box>
|
||||||
<TimeLineDetails />
|
<TimeLineDetails/>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,34 +1,45 @@
|
|||||||
import {Box, Container, Grid, Stack, Typography} from "@mui/material";
|
import {Box, Container, Grid, Stack, Typography} from "@mui/material";
|
||||||
import LinkRouting from "@/core/components/LinkRouting";
|
|
||||||
import {useTranslations} from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
import {LinkRouting} from "@witel/webapp-builder";
|
||||||
|
|
||||||
const LoanRegister = () => {
|
const LoanRegister = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
return(
|
return (
|
||||||
<Box sx={{backgroundColor : "primary.light"}}>
|
<Box sx={{backgroundColor: "primary.light"}}>
|
||||||
<Container sx={{padding : 3, color : "white"}} maxWidth="xl">
|
<Container sx={{padding: 3, color: "white"}} maxWidth="xl">
|
||||||
<Typography sx={{my : 3}} variant={'h3'}>
|
<Typography sx={{my: 3}} variant={'h3'}>
|
||||||
{t("app_name")}
|
{t("app_name")}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Stack sx={{color : "white"}}>
|
<Stack sx={{color: "white"}}>
|
||||||
<Grid sx={{py : 4}} container spacing={2}>
|
<Grid sx={{py: 4}} container spacing={2}>
|
||||||
<Grid item xs={12} md={6}>
|
<Grid item xs={12} md={6}>
|
||||||
<Box sx={{paddingBottom : 4}}>
|
<Box sx={{paddingBottom: 4}}>
|
||||||
<Typography>
|
<Typography>
|
||||||
برای استفاده از تسهیلات این سامانه و دریافت وام می بایست ابتدا وارد سامانه شوید و یا اگر ثبت نام نکرده اید ثبت نام کنید
|
برای استفاده از تسهیلات این سامانه و دریافت وام می بایست ابتدا وارد سامانه شوید و یا
|
||||||
|
اگر ثبت نام نکرده اید ثبت نام کنید
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} md={6}>
|
<Grid item xs={12} md={6}>
|
||||||
<Stack spacing={3} alignItems={'center'} justifyContent={'center'}>
|
<Stack spacing={3} alignItems={'center'} justifyContent={'center'}>
|
||||||
<Container maxWidth={'xs'} sx={{backgroundColor : "primary.main", textAlign : "center", borderRadius : 2, padding : 1}}>
|
<Container maxWidth={'xs'} sx={{
|
||||||
|
backgroundColor: "primary.main",
|
||||||
|
textAlign: "center",
|
||||||
|
borderRadius: 2,
|
||||||
|
padding: 1
|
||||||
|
}}>
|
||||||
<LinkRouting underline="none" color="inherit" href={'/login'}>
|
<LinkRouting underline="none" color="inherit" href={'/login'}>
|
||||||
<Typography variant="h6">
|
<Typography variant="h6">
|
||||||
{t("firstPage.login_button")}
|
{t("firstPage.login_button")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</LinkRouting>
|
</LinkRouting>
|
||||||
</Container>
|
</Container>
|
||||||
<Container maxWidth={'xs'} sx={{backgroundColor : "primary.main", textAlign : "center", borderRadius : 2 ,padding : 1}}>
|
<Container maxWidth={'xs'} sx={{
|
||||||
|
backgroundColor: "primary.main",
|
||||||
|
textAlign: "center",
|
||||||
|
borderRadius: 2,
|
||||||
|
padding: 1
|
||||||
|
}}>
|
||||||
<LinkRouting underline="none" color="inherit" href={'/register'}>
|
<LinkRouting underline="none" color="inherit" href={'/register'}>
|
||||||
<Typography variant="h6">
|
<Typography variant="h6">
|
||||||
{t("firstPage.register_button")}
|
{t("firstPage.register_button")}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
|
||||||
import {Stack} from "@mui/material";
|
import {Stack} from "@mui/material";
|
||||||
import {useTranslations} from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import LoanRegister from "@/components/first/LoanRegister";
|
import LoanRegister from "@/components/first/LoanRegister";
|
||||||
@@ -6,6 +5,7 @@ import LoanCondition from "@/components/first/LoanCondition";
|
|||||||
import FooterDetails from "@/components/first/FooterDetails";
|
import FooterDetails from "@/components/first/FooterDetails";
|
||||||
import HeaderDetails from "@/components/first/HeaderDetails";
|
import HeaderDetails from "@/components/first/HeaderDetails";
|
||||||
import LoanDescription from "@/components/first/LoanDescription";
|
import LoanDescription from "@/components/first/LoanDescription";
|
||||||
|
import {FullPageLayout} from "@witel/webapp-builder";
|
||||||
|
|
||||||
const FirstComponent = () => {
|
const FirstComponent = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
@@ -13,11 +13,11 @@ const FirstComponent = () => {
|
|||||||
return (
|
return (
|
||||||
<FullPageLayout>
|
<FullPageLayout>
|
||||||
<Stack>
|
<Stack>
|
||||||
<HeaderDetails />
|
<HeaderDetails/>
|
||||||
<LoanRegister />
|
<LoanRegister/>
|
||||||
<LoanDescription />
|
<LoanDescription/>
|
||||||
<LoanCondition />
|
<LoanCondition/>
|
||||||
<FooterDetails />
|
<FooterDetails/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</FullPageLayout>
|
</FullPageLayout>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,116 +0,0 @@
|
|||||||
import MuiLink from "@mui/material/Link";
|
|
||||||
import {styled} from "@mui/material/styles";
|
|
||||||
import clsx from "clsx";
|
|
||||||
import NextLink from "next/link";
|
|
||||||
import {useRouter} from "next/router";
|
|
||||||
import * as React from "react";
|
|
||||||
|
|
||||||
// Add support for the sx prop for consistency with the other branches.
|
|
||||||
const Anchor = styled("a")({});
|
|
||||||
|
|
||||||
export const NextLinkComposed = React.forwardRef(function NextLinkComposed(
|
|
||||||
props,
|
|
||||||
ref
|
|
||||||
) {
|
|
||||||
const {
|
|
||||||
to,
|
|
||||||
linkAs,
|
|
||||||
replace,
|
|
||||||
scroll,
|
|
||||||
shallow,
|
|
||||||
prefetch,
|
|
||||||
legacyBehavior = true,
|
|
||||||
locale,
|
|
||||||
...other
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<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 router = useRouter();
|
|
||||||
const pathname = typeof href === "string" ? href : href.pathname;
|
|
||||||
const className = clsx(classNameProps, {
|
|
||||||
[activeClassName]: router.pathname === pathname && activeClassName,
|
|
||||||
});
|
|
||||||
|
|
||||||
const isExternal =
|
|
||||||
typeof href === "string" &&
|
|
||||||
(href.indexOf("http") === 0 || href.indexOf("mailto:") === 0);
|
|
||||||
|
|
||||||
if (isExternal) {
|
|
||||||
if (noLinkStyle) {
|
|
||||||
return <Anchor 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,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (noLinkStyle) {
|
|
||||||
return (
|
|
||||||
<NextLinkComposed
|
|
||||||
className={className}
|
|
||||||
ref={ref}
|
|
||||||
{...nextjsProps}
|
|
||||||
{...other}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MuiLink
|
|
||||||
component={NextLinkComposed}
|
|
||||||
className={className}
|
|
||||||
ref={ref}
|
|
||||||
{...nextjsProps}
|
|
||||||
{...other}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default LinkRouting;
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
import {Backdrop, Box, Fade, styled} from "@mui/material";
|
|
||||||
import SvgLoading from "@/core/components/svgs/SvgLoading";
|
|
||||||
|
|
||||||
const LoadingImage = styled(Box)({
|
|
||||||
"@keyframes load": {
|
|
||||||
"0%": {
|
|
||||||
// opacity: 0,
|
|
||||||
transform: "scale(1)",
|
|
||||||
},
|
|
||||||
"50%": {
|
|
||||||
// opacity: 1,
|
|
||||||
transform: "scale(2)",
|
|
||||||
},
|
|
||||||
"100%": {
|
|
||||||
// opacity: 0,
|
|
||||||
transform: "scale(1)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
animation: "load 2s infinite",
|
|
||||||
});
|
|
||||||
|
|
||||||
const LoadingHardPage = ({children, loading}) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Backdrop
|
|
||||||
sx={{bgcolor: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1}}
|
|
||||||
open={loading}
|
|
||||||
>
|
|
||||||
<Fade in={true}>
|
|
||||||
<LoadingImage
|
|
||||||
width={100}
|
|
||||||
height={100}
|
|
||||||
>
|
|
||||||
<SvgLoading width={100}
|
|
||||||
height={100}/>
|
|
||||||
</LoadingImage>
|
|
||||||
</Fade>
|
|
||||||
</Backdrop>
|
|
||||||
{children}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default LoadingHardPage;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import CenterLayout from "@/layouts/CenterLayout";
|
|
||||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
|
||||||
import SvgLoading from "@/core/components/svgs/SvgLoading";
|
|
||||||
|
|
||||||
const Message = ({text, actions}) => {
|
|
||||||
return (
|
|
||||||
<FullPageLayout sx={{p: 1}}>
|
|
||||||
<CenterLayout spacing={3}>
|
|
||||||
<SvgLoading width={100}
|
|
||||||
height={100}/>
|
|
||||||
{text}
|
|
||||||
{actions}
|
|
||||||
</CenterLayout>
|
|
||||||
</FullPageLayout>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Message;
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import useNetwork from "@/lib/app/hooks/useNetwork";
|
|
||||||
import {useEffect, useRef} from "react";
|
|
||||||
import {toast} from "react-toastify";
|
|
||||||
import WifiIcon from '@mui/icons-material/Wifi';
|
|
||||||
import WifiOffIcon from '@mui/icons-material/WifiOff';
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
|
|
||||||
const NetworkComponent = () => {
|
|
||||||
const toastId = useRef(null);
|
|
||||||
const network = useNetwork()
|
|
||||||
const t = useTranslations()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (network.online) {
|
|
||||||
toast.update(toastId.current, {
|
|
||||||
type: toast.TYPE.SUCCESS,
|
|
||||||
render: t('online_message'),
|
|
||||||
autoClose: 2000,
|
|
||||||
closeButton: true,
|
|
||||||
closeOnClick: true,
|
|
||||||
icon: <WifiIcon/>
|
|
||||||
});
|
|
||||||
return
|
|
||||||
}
|
|
||||||
toast.dismiss()
|
|
||||||
toastId.current = toast.warn(t('offline_message'), {
|
|
||||||
autoClose: false, closeButton: false, closeOnClick: false, icon: <WifiOffIcon/>
|
|
||||||
})
|
|
||||||
}, [network.online]);
|
|
||||||
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
export default NetworkComponent
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import {NoSsr} from "@mui/material";
|
|
||||||
|
|
||||||
const NoSsrHandler = ({isBot, children}) => {
|
|
||||||
if (isBot) return children;
|
|
||||||
return <NoSsr>{children}</NoSsr>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NoSsrHandler;
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import DangerousIcon from "@mui/icons-material/Dangerous";
|
|
||||||
import {Box, Typography} from "@mui/material";
|
|
||||||
import {toast} from "react-toastify";
|
|
||||||
|
|
||||||
const ErrorNotification = (t, status, message) => {
|
|
||||||
toast(
|
|
||||||
() => (
|
|
||||||
<>
|
|
||||||
<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>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
{
|
|
||||||
autoClose: false,
|
|
||||||
closeOnClick: false,
|
|
||||||
draggable: false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ErrorNotification;
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import {toast} from "react-toastify";
|
|
||||||
|
|
||||||
const PendingNotification = (t) => {
|
|
||||||
toast(t("notifications.pending"), {
|
|
||||||
autoClose: false,
|
|
||||||
closeButton: false,
|
|
||||||
closeOnClick: false,
|
|
||||||
draggable: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default PendingNotification;
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
import BeenhereIcon from "@mui/icons-material/Beenhere";
|
|
||||||
import {Box, Typography} from "@mui/material";
|
|
||||||
import {toast} from "react-toastify";
|
|
||||||
|
|
||||||
const SuccessNotification = (t, status) => {
|
|
||||||
toast(
|
|
||||||
() => (
|
|
||||||
<>
|
|
||||||
<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>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
{
|
|
||||||
autoClose: 3000,
|
|
||||||
hideProgressBar: true,
|
|
||||||
pauseOnHover: true,
|
|
||||||
closeOnClick: false,
|
|
||||||
draggable: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SuccessNotification;
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import ReportIcon from "@mui/icons-material/Report";
|
|
||||||
import {Box, Typography} from "@mui/material";
|
|
||||||
import {toast} from "react-toastify";
|
|
||||||
|
|
||||||
const WarningNotification = (t, status) => {
|
|
||||||
toast(
|
|
||||||
() => (
|
|
||||||
<>
|
|
||||||
<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("notifications.warning")} ({t("notifications.code")}:{" "}
|
|
||||||
{status})
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="caption">
|
|
||||||
{t("notifications.warning_static_text")}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
{
|
|
||||||
autoClose: false,
|
|
||||||
closeOnClick: false,
|
|
||||||
draggable: false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default WarningNotification;
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
import {toast} from "react-toastify";
|
|
||||||
import ErrorNotification from "./ErrorNotification";
|
|
||||||
import SuccessNotification from "./SuccessNotification";
|
|
||||||
import WarningNotification from "./WarningNotification";
|
|
||||||
|
|
||||||
const Notifications = async (t, response) => {
|
|
||||||
const {status, data} = response != undefined ? response : ""
|
|
||||||
toast.dismiss();
|
|
||||||
switch (status) {
|
|
||||||
case 200:
|
|
||||||
SuccessNotification(t, status);
|
|
||||||
break;
|
|
||||||
case 400:
|
|
||||||
ErrorNotification(t, status);
|
|
||||||
break;
|
|
||||||
case 401:
|
|
||||||
ErrorNotification(t, status);
|
|
||||||
break;
|
|
||||||
case 403:
|
|
||||||
ErrorNotification(t, status);
|
|
||||||
break;
|
|
||||||
case 422:
|
|
||||||
ErrorNotification(t, status, data.message);
|
|
||||||
break;
|
|
||||||
case 500:
|
|
||||||
WarningNotification(t, status);
|
|
||||||
break;
|
|
||||||
case 503:
|
|
||||||
WarningNotification(t, status);
|
|
||||||
break;
|
|
||||||
case 504:
|
|
||||||
WarningNotification(t, status);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
toast(t("pending"), {
|
|
||||||
autoClose: false,
|
|
||||||
closeOnClick: false,
|
|
||||||
draggable: false,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Notifications;
|
|
||||||
|
|
||||||
/*
|
|
||||||
usage document
|
|
||||||
|
|
||||||
** for pending use ( Notifications( t, undefined) ) this before your request.
|
|
||||||
** for success use ( Notifications( t, response) ) this inside .then() of your request.
|
|
||||||
** for Error and Warning use ( Notifications( t, error.response) ) this inside .catche() of your request.
|
|
||||||
|
|
||||||
end usage document
|
|
||||||
*/
|
|
||||||
@@ -5,7 +5,8 @@ export const LOGIN = BASE_URL + "/login";
|
|||||||
// export const REGISTER_SEND_OTP_TOKEN = BASE_URL + "/register/send_otp";
|
// export const REGISTER_SEND_OTP_TOKEN = BASE_URL + "/register/send_otp";
|
||||||
export const SEND_OTP_TOKEN = BASE_URL + "/otp";
|
export const SEND_OTP_TOKEN = BASE_URL + "/otp";
|
||||||
export const REGISTER = BASE_URL + "/register";
|
export const REGISTER = BASE_URL + "/register";
|
||||||
export const USER_INFO = BASE_URL + "/profile/info";
|
export const GET_USER = BASE_URL + "/profile/info";
|
||||||
|
export const GET_SIDEBAR_NOTIFICATION = "";
|
||||||
export const SHOW_LOAN_REQUEST_NAVGAN = BASE_URL + "/navgan/loan/index";
|
export const SHOW_LOAN_REQUEST_NAVGAN = BASE_URL + "/navgan/loan/index";
|
||||||
export const SEND_LOAN_REQUEST_NAVGAN = BASE_URL + "/navgan/loan/store";
|
export const SEND_LOAN_REQUEST_NAVGAN = BASE_URL + "/navgan/loan/store";
|
||||||
export const SHOW_LOAN_REQUEST_WELFARE = BASE_URL + "/refahi/loan/index";
|
export const SHOW_LOAN_REQUEST_WELFARE = BASE_URL + "/refahi/loan/index";
|
||||||
|
|||||||
14
src/core/data/languageList.js
Normal file
14
src/core/data/languageList.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import {FA_DATATABLE_LOCALIZATION} from "&/locales/fa/datatable";
|
||||||
|
|
||||||
|
const languageList = [
|
||||||
|
{
|
||||||
|
key: "fa",
|
||||||
|
dir: 'rtl',
|
||||||
|
name: "فارسی",
|
||||||
|
fontFamily: `IRANSans, sans-serif`,
|
||||||
|
tableLocalization: FA_DATATABLE_LOCALIZATION,
|
||||||
|
chartLocalization: null
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export default languageList;
|
||||||
@@ -9,7 +9,6 @@ const sidebarMenu = [
|
|||||||
type: "page",
|
type: "page",
|
||||||
route: "/dashboard",
|
route: "/dashboard",
|
||||||
icon: <SpaceDashboardIcon/>,
|
icon: <SpaceDashboardIcon/>,
|
||||||
userType: 0,
|
|
||||||
selected: false,
|
selected: false,
|
||||||
permission_name: "all"
|
permission_name: "all"
|
||||||
},
|
},
|
||||||
@@ -18,7 +17,6 @@ const sidebarMenu = [
|
|||||||
type: "page",
|
type: "page",
|
||||||
route: "/dashboard/navgan/add-request-loan",
|
route: "/dashboard/navgan/add-request-loan",
|
||||||
icon: <DataSaverOnIcon/>,
|
icon: <DataSaverOnIcon/>,
|
||||||
userType: 1,
|
|
||||||
selected: false,
|
selected: false,
|
||||||
permission_name: "can_request_a_new_loan"
|
permission_name: "can_request_a_new_loan"
|
||||||
},
|
},
|
||||||
@@ -27,25 +25,6 @@ const sidebarMenu = [
|
|||||||
type: "page",
|
type: "page",
|
||||||
route: "/dashboard/navgan/followUp-loan",
|
route: "/dashboard/navgan/followUp-loan",
|
||||||
icon: <BookmarkAddedIcon/>,
|
icon: <BookmarkAddedIcon/>,
|
||||||
userType: 1,
|
|
||||||
selected: false,
|
|
||||||
permission_name: "all"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "sidebar.add-request-loan",
|
|
||||||
type: "page",
|
|
||||||
route: "/dashboard/refahi/add-request-loan",
|
|
||||||
icon: <DataSaverOnIcon/>,
|
|
||||||
userType: 2,
|
|
||||||
selected: false,
|
|
||||||
permission_name: "can_request_a_new_loan"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "sidebar.followUp-loan",
|
|
||||||
type: "page",
|
|
||||||
route: "/dashboard/refahi/followUp-loan",
|
|
||||||
icon: <BookmarkAddedIcon/>,
|
|
||||||
userType: 2,
|
|
||||||
selected: false,
|
selected: false,
|
||||||
permission_name: "all"
|
permission_name: "all"
|
||||||
},
|
},
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import createCache from "@emotion/cache";
|
|
||||||
import {prefixer} from "stylis";
|
|
||||||
import stylisRTLPlugin from "stylis-plugin-rtl";
|
|
||||||
|
|
||||||
const isBrowser = typeof document !== "undefined";
|
|
||||||
|
|
||||||
export const createEmotionCacheLtr = () => {
|
|
||||||
let insertionPoint;
|
|
||||||
|
|
||||||
if (isBrowser) {
|
|
||||||
const emotionInsertionPoint = document.querySelector(
|
|
||||||
'meta[name="emotion-insertion-point"]'
|
|
||||||
);
|
|
||||||
insertionPoint = emotionInsertionPoint ?? undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return createCache({
|
|
||||||
key: "mui-style",
|
|
||||||
insertionPoint,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createEmotionCacheRtl = () => {
|
|
||||||
let insertionPoint;
|
|
||||||
|
|
||||||
if (isBrowser) {
|
|
||||||
const emotionInsertionPoint = document.querySelector(
|
|
||||||
'meta[name="emotion-insertion-point"]'
|
|
||||||
);
|
|
||||||
insertionPoint = emotionInsertionPoint ?? undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return createCache({
|
|
||||||
key: "muirtl",
|
|
||||||
stylisPlugins: [prefixer, stylisRTLPlugin],
|
|
||||||
insertionPoint,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import ErrorNotification from "@/core/components/notifications/ErrorNotification";
|
|
||||||
import WarningNotification from "@/core/components/notifications/WarningNotification";
|
|
||||||
import {toast} from "react-toastify";
|
|
||||||
|
|
||||||
export const errorSetting = (t, notification) => {
|
|
||||||
if (notification) toast.dismiss();
|
|
||||||
}
|
|
||||||
|
|
||||||
export const errorRequest = (t, notification) => {
|
|
||||||
if (notification) toast.dismiss();
|
|
||||||
}
|
|
||||||
|
|
||||||
export const errorResponse = (response, clearToken, t, notification) => {
|
|
||||||
if (notification) toast.dismiss();
|
|
||||||
if (isServerError(response.status)) {
|
|
||||||
errorServer(response, t, notification)
|
|
||||||
} else if (isClientError(response.status)) {
|
|
||||||
errorClient(response, clearToken, t, notification)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorServer = (response, t, notification) => {
|
|
||||||
if (notification) WarningNotification(t, response.status);
|
|
||||||
}
|
|
||||||
const errorClient = (response, clearToken, t, notification) => {
|
|
||||||
switch (response.status) {
|
|
||||||
case 401:
|
|
||||||
clearToken()
|
|
||||||
if (notification) ErrorNotification(t, response.status)
|
|
||||||
break;
|
|
||||||
case 422:
|
|
||||||
if ('type' in response.data) {
|
|
||||||
errorLogic(response, t, notification)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
errorValidation(response, t, notification)
|
|
||||||
break;
|
|
||||||
case 429:
|
|
||||||
if (notification) ErrorNotification(t, response.status)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
if (notification) ErrorNotification(t, response.status)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const isServerError = status => status >= 500 && status <= 599;
|
|
||||||
const isClientError = status => status >= 400 && status <= 499;
|
|
||||||
|
|
||||||
const errorLogic = (response, t, notification) => {
|
|
||||||
if (notification) ErrorNotification(t, response.status, response.data.message)
|
|
||||||
}
|
|
||||||
const errorValidation = (response, t, notification) => {
|
|
||||||
if (notification) {
|
|
||||||
const errorsMap = Object.keys(response.data.errors)
|
|
||||||
const errorsArray = response.data.errors
|
|
||||||
|
|
||||||
errorsMap.map((item, index) => {
|
|
||||||
ErrorNotification(t, response.status, errorsArray[item][0]);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import SuccessNotification from "@/core/components/notifications/SuccessNotification";
|
|
||||||
import {toast} from "react-toastify";
|
|
||||||
|
|
||||||
export const successRequest = (response, t, options) => {
|
|
||||||
if (options.notification && options.success.notification.show) {
|
|
||||||
toast.dismiss();
|
|
||||||
SuccessNotification(t, response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
import theme from "@/core/utils/theme";
|
|
||||||
import useLanguage from "@/lib/app/hooks/useLanguage";
|
|
||||||
import useLoading from "@/lib/app/hooks/useLoading";
|
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
|
||||||
import NextNProgress from "nextjs-progressbar";
|
|
||||||
import {useEffect} from "react";
|
|
||||||
import {ToastContainer} from "react-toastify";
|
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
|
||||||
import "react-toastify/dist/ReactToastify.css";
|
|
||||||
import NetworkComponent from "@/core/components/NetworkComponent";
|
|
||||||
import GlobalHead from "@/core/components/GlobalHead";
|
|
||||||
|
|
||||||
function AppLayout({children, isBot}) {
|
|
||||||
const {languageIsReady} = useLanguage();
|
|
||||||
const {setLoadingPage} = useLoading();
|
|
||||||
const {userChangedLanguage, token, isAuth} = useUser();
|
|
||||||
const {directionApp} = useDirection();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (languageIsReady) {
|
|
||||||
if (token) {
|
|
||||||
if (isAuth) {
|
|
||||||
if (userChangedLanguage) {
|
|
||||||
setLoadingPage(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setLoadingPage(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setLoadingPage(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setLoadingPage(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setLoadingPage(true);
|
|
||||||
}, [languageIsReady, token, isAuth, userChangedLanguage]);
|
|
||||||
|
|
||||||
if (!isBot) {
|
|
||||||
if (userChangedLanguage) return;
|
|
||||||
if (!languageIsReady) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (<>
|
|
||||||
<GlobalHead/>
|
|
||||||
<NextNProgress
|
|
||||||
color={theme.palette.secondary.dark}
|
|
||||||
options={{showSpinner: false}}
|
|
||||||
/>
|
|
||||||
<ToastContainer position={directionApp === "ltr" ? "top-left" : "top-right"} rtl={directionApp === 'rtl'}/>
|
|
||||||
<NetworkComponent/>
|
|
||||||
{children}
|
|
||||||
</>);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AppLayout;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CenterLayout;
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
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>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default FullPageLayout;
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
import NoSsrHandler from "@/core/components/NoSsrHandler";
|
|
||||||
import {createEmotionCacheRtl} from "@/core/utils/createEmotionCache";
|
|
||||||
import themeRtl from "@/core/utils/theme-rtl";
|
|
||||||
import {CacheProvider} from "@emotion/react";
|
|
||||||
import {GlobalStyles} from "@mui/material";
|
|
||||||
import CssBaseline from "@mui/material/CssBaseline";
|
|
||||||
import {ThemeProvider} from "@mui/material/styles";
|
|
||||||
import Head from "next/head";
|
|
||||||
|
|
||||||
const clientSideEmotionCacheRtl = createEmotionCacheRtl();
|
|
||||||
|
|
||||||
const MuiLayout = ({children, isBot}) => {
|
|
||||||
|
|
||||||
const emotionCache = clientSideEmotionCacheRtl;
|
|
||||||
|
|
||||||
const theme = themeRtl;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<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: `${theme.palette.primary.light}80`,
|
|
||||||
borderRadius: "3px",
|
|
||||||
},
|
|
||||||
"*:not(.MuiTableContainer-root)": {
|
|
||||||
scrollbarWidth: "thin",
|
|
||||||
scrollbarColor: "transparent transparent",
|
|
||||||
},
|
|
||||||
|
|
||||||
"*": {
|
|
||||||
scrollbarWidth: "thin",
|
|
||||||
scrollbarColor: `${theme.palette.primary.light}80 transparent`,
|
|
||||||
},
|
|
||||||
|
|
||||||
"*::-moz-scrollbar-thumb": {
|
|
||||||
backgroundColor: `${theme.palette.primary.light}80`,
|
|
||||||
},
|
|
||||||
[`@media (max-width: ${theme.breakpoints.values.sm}px)`]: {
|
|
||||||
"*::-webkit-scrollbar": {
|
|
||||||
height: "4px",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
body: {
|
|
||||||
width: "100vw",
|
|
||||||
height: "100vh",
|
|
||||||
},
|
|
||||||
"#__next": {
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<CssBaseline/>
|
|
||||||
{children}
|
|
||||||
</ThemeProvider>
|
|
||||||
</CacheProvider>
|
|
||||||
</NoSsrHandler>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MuiLayout;
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import {Box, Fade} from "@mui/material";
|
|
||||||
|
|
||||||
const ScrollableLayout = (props) => {
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ScrollableLayout;
|
|
||||||
15
src/layouts/dashboard.jsx
Normal file
15
src/layouts/dashboard.jsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import {DashboardLayout as DashboardLayoutPure} from "@witel/webapp-builder";
|
||||||
|
import headerProfileItems from "@/core/data/headerProfileItems";
|
||||||
|
import sidebarMenu from "@/core/data/sidebarMenu";
|
||||||
|
import {GET_SIDEBAR_NOTIFICATION} from "@/core/data/apiRoutes";
|
||||||
|
|
||||||
|
const DashboardLayout = (props) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DashboardLayoutPure headerProfileItems={headerProfileItems} sidebarMenu={sidebarMenu}
|
||||||
|
urlNotification={GET_SIDEBAR_NOTIFICATION} {...props} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DashboardLayout
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import LinkRouting from "@/core/components/LinkRouting";
|
|
||||||
import {Typography} from "@mui/material";
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
|
|
||||||
export default function BreadcrumbItem(props) {
|
|
||||||
const t = useTranslations();
|
|
||||||
const isLast = props.index === props.RouterArray.length - 1;
|
|
||||||
const url = `/${props.RouterArray.slice(0, props.index + 1).join("/")}`;
|
|
||||||
|
|
||||||
return isLast ? (
|
|
||||||
<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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import {useRouter} from "next/router";
|
|
||||||
import {Box, Breadcrumbs} from "@mui/material";
|
|
||||||
import {useTheme} from "@mui/material/styles";
|
|
||||||
import {NavigateBefore, NavigateNext} from "@mui/icons-material";
|
|
||||||
import BreadcrumbItem from "./BreadcrumbItem";
|
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
|
||||||
|
|
||||||
const BreadCrumbs = (props) => {
|
|
||||||
const {isVisible} = props;
|
|
||||||
const theme = useTheme();
|
|
||||||
const router = useRouter();
|
|
||||||
const {user} = useUser();
|
|
||||||
|
|
||||||
if (!isVisible) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {pathname} = router;
|
|
||||||
const RouterArray = pathname.split("/").filter((segment) => segment !== "");
|
|
||||||
|
|
||||||
// every part of your router you want to remove add it to this array
|
|
||||||
const segmentsToRemove = ["navgan", "refahi", "[id]"];
|
|
||||||
|
|
||||||
segmentsToRemove.forEach((segmentToRemove) => {
|
|
||||||
const index = RouterArray.indexOf(segmentToRemove);
|
|
||||||
if (index !== -1) {
|
|
||||||
RouterArray.splice(index, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
if (RouterArray.length === 1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<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;
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import {Avatar, Stack} from "@mui/material";
|
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
|
||||||
|
|
||||||
export default function ProfileData() {
|
|
||||||
const {user} = useUser();
|
|
||||||
return (
|
|
||||||
<Stack alignItems="center" spacing={2} sx={{p: 3}}>
|
|
||||||
<Avatar
|
|
||||||
sx={{width: "80px", height: "80px"}}
|
|
||||||
alt="User Image"
|
|
||||||
src={user.user_avatar}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import {Avatar, IconButton, Menu, Tooltip} from "@mui/material";
|
|
||||||
import {useState} from "react";
|
|
||||||
import ProfileData from "./ProfileData";
|
|
||||||
import ProfileOptions from "./ProfileOptions";
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
|
||||||
|
|
||||||
function ProfileMenu() {
|
|
||||||
const t = useTranslations();
|
|
||||||
const [anchorElUser, setAnchorElUser] = useState(null);
|
|
||||||
const {user} = useUser();
|
|
||||||
|
|
||||||
const handleOpenUserMenu = (event) => {
|
|
||||||
setAnchorElUser(event.currentTarget);
|
|
||||||
};
|
|
||||||
const handleCloseUserMenu = () => {
|
|
||||||
setAnchorElUser(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<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;
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import {Box, Button, MenuItem, Typography} from "@mui/material";
|
|
||||||
import MeetingRoomIcon from "@mui/icons-material/MeetingRoom";
|
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
|
|
||||||
export default function ProfileOptionLogOut({handleCloseUserMenu}) {
|
|
||||||
const t = useTranslations();
|
|
||||||
const {clearToken} = useUser();
|
|
||||||
const handleClickLogOut = () => {
|
|
||||||
handleCloseUserMenu();
|
|
||||||
clearToken();
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<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>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import {Box, MenuItem, Typography} from "@mui/material";
|
|
||||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
import headerProfileItems from "@/core/data/headerProfileItems";
|
|
||||||
import ProfileOptionLogOut from "./ProfileOptionLogOut";
|
|
||||||
|
|
||||||
export default function ProfileOptions({handleCloseUserMenu}) {
|
|
||||||
const t = useTranslations();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{headerProfileItems.map((profile_item) => (
|
|
||||||
<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}/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import MenuIcon from "@mui/icons-material/Menu";
|
|
||||||
import {AppBar, Box, Container, CssBaseline, IconButton, Stack, Toolbar, useTheme} from "@mui/material";
|
|
||||||
import ProfileMenu from "./ProfileMenu";
|
|
||||||
|
|
||||||
function Header({drawerWidth, handleDrawerToggle}) {
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<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
|
|
||||||
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;
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import {useState} from "react";
|
|
||||||
import FullPageLayout from "../FullPageLayout";
|
|
||||||
import Header from "./header";
|
|
||||||
import Sidebar from "./sidebar";
|
|
||||||
import {Toolbar} from "@mui/material";
|
|
||||||
import BreadCrumbs from "./breadcrumbs";
|
|
||||||
import {ToastContainer} from "react-toastify";
|
|
||||||
import "react-toastify/dist/ReactToastify.css";
|
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
|
||||||
|
|
||||||
const drawerWidth = 240;
|
|
||||||
|
|
||||||
const DashboardLayouts = (props) => {
|
|
||||||
const {directionApp} = useDirection();
|
|
||||||
const {window} = props;
|
|
||||||
const [mobileOpen, setMobileOpen] = useState(false);
|
|
||||||
const container =
|
|
||||||
window !== undefined ? () => window().document.body : undefined;
|
|
||||||
|
|
||||||
const handleDrawerToggle = () => {
|
|
||||||
setMobileOpen(!mobileOpen);
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<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>
|
|
||||||
</FullPageLayout>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DashboardLayouts;
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import useUser from "@/lib/app/hooks/useUser";
|
|
||||||
import {Divider, Stack, Toolbar, Typography} from "@mui/material";
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
import SidebarList from "./SidebarList";
|
|
||||||
|
|
||||||
const SidebarDrawer = ({handleDrawerToggle}) => {
|
|
||||||
const {user} = useUser();
|
|
||||||
const t = useTranslations();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<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;
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
import {Divider, List} from "@mui/material";
|
|
||||||
import {Fragment, useEffect, useReducer} from "react";
|
|
||||||
import SidebarListItem from "./SidebarListItem";
|
|
||||||
import sidebarMenu from "@/core/data/sidebarMenu";
|
|
||||||
import {useRouter} from "next/router";
|
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
|
||||||
|
|
||||||
function reducer(state, action) {
|
|
||||||
switch (action.type) {
|
|
||||||
case "COLLAPSE_MENU":
|
|
||||||
return state.map((itemsArr) =>
|
|
||||||
itemsArr.map((item) =>
|
|
||||||
action.key == item.key
|
|
||||||
? {...item, showSubItem: !item.showSubItem}
|
|
||||||
: item
|
|
||||||
)
|
|
||||||
);
|
|
||||||
case "SELECTED":
|
|
||||||
return state.map((itemsArr) =>
|
|
||||||
itemsArr.map((item) =>
|
|
||||||
action.route == item.route
|
|
||||||
? {...item, selected: true}
|
|
||||||
: {...item, selected: false}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
throw new Error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SidebarList({handleDrawerToggle}) {
|
|
||||||
const [itemMenu, dispatch] = useReducer(reducer, sidebarMenu);
|
|
||||||
const {user} = useUser();
|
|
||||||
|
|
||||||
// activate current page in menu
|
|
||||||
const router = useRouter();
|
|
||||||
useEffect(() => {
|
|
||||||
dispatch({type: "SELECTED", route: router.pathname});
|
|
||||||
}, [router.pathname]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<List>
|
|
||||||
{itemMenu.map((itemArr, index) => (
|
|
||||||
<Fragment key={index}>
|
|
||||||
{itemArr.map((item) => {
|
|
||||||
if (
|
|
||||||
(item.userType === user.type_id || item.userType === 0) &&
|
|
||||||
(user[item.permission_name] || item.permission_name === "all")
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
<SidebarListItem
|
|
||||||
item={item}
|
|
||||||
dispatch={dispatch}
|
|
||||||
key={item.key}
|
|
||||||
handleDrawerToggle={handleDrawerToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
<Divider/>
|
|
||||||
</Fragment>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</List>
|
|
||||||
)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
|
||||||
import ExpandLess from "@mui/icons-material/ExpandLess";
|
|
||||||
import ExpandMore from "@mui/icons-material/ExpandMore";
|
|
||||||
import {ListItem, ListItemButton, ListItemIcon, ListItemText,} from "@mui/material";
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
import {Fragment} from "react";
|
|
||||||
import SidebarListSubItem from "./SidebarListSubItem";
|
|
||||||
|
|
||||||
const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
|
|
||||||
const t = useTranslations();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<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>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SidebarListItem;
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
|
||||||
import InboxIcon from "@mui/icons-material/MoveToInbox";
|
|
||||||
import {Collapse, List, ListItemButton, ListItemIcon, ListItemText,} from "@mui/material";
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
import {Fragment} from "react";
|
|
||||||
|
|
||||||
const SidebarListSubItem = ({item, handleDrawerToggle}) => {
|
|
||||||
const t = useTranslations();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<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;
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
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>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Sidebar;
|
|
||||||
16
src/layouts/index.jsx
Normal file
16
src/layouts/index.jsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import {Fragment} from "react";
|
||||||
|
|
||||||
|
const layoutList = (await import('./list'))
|
||||||
|
|
||||||
|
const Layout = ({layout, children}) => {
|
||||||
|
const Component = layoutList[layout?.name] || Fragment
|
||||||
|
const props = layout?.props || {}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Component {...props}>
|
||||||
|
{children}
|
||||||
|
</Component>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Layout
|
||||||
3
src/layouts/list.jsx
Normal file
3
src/layouts/list.jsx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import DashboardLayout from './dashboard'
|
||||||
|
|
||||||
|
export {DashboardLayout}
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
import {FA_DATATABLE_LOCALIZATION} from "&/locales/fa/datatable";
|
|
||||||
import {useRouter} from "next/router";
|
|
||||||
import {createContext, useEffect, useState} from "react";
|
|
||||||
import useUser from "../hooks/useUser";
|
|
||||||
|
|
||||||
export const LanguageContext = createContext();
|
|
||||||
|
|
||||||
export const LanguageProvider = ({children}) => {
|
|
||||||
const router = useRouter();
|
|
||||||
const languageList = [
|
|
||||||
{
|
|
||||||
key: "fa",
|
|
||||||
dir: "rtl",
|
|
||||||
name: "فارسی",
|
|
||||||
fontFamily: `IRANSans, sans-serif`,
|
|
||||||
tableLocalization: FA_DATATABLE_LOCALIZATION,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
const {user, userChangedLanguage, changeLanguageState} = useUser();
|
|
||||||
const [languageIsReady, setLanguageIsReady] = useState(false);
|
|
||||||
const [languageApp, setLanguageApp] = useState();
|
|
||||||
const [directionApp, setDirectionApp] = useState(
|
|
||||||
process.env.NEXT_PUBLIC_DEFAULT_DIRECTION
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const lang = localStorage.getItem("_language");
|
|
||||||
|
|
||||||
if (!lang && !languageApp) {
|
|
||||||
setLanguageApp(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE);
|
|
||||||
} else if (lang) {
|
|
||||||
setLanguageApp(lang);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!languageApp) return;
|
|
||||||
|
|
||||||
const lang = localStorage.getItem("_language");
|
|
||||||
|
|
||||||
if (!lang) {
|
|
||||||
localStorage.setItem("_language", languageApp);
|
|
||||||
} else {
|
|
||||||
if (languageApp != lang) {
|
|
||||||
localStorage.setItem("_language", languageApp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [languageApp]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!router.isReady) return;
|
|
||||||
if (user.user_language) {
|
|
||||||
if (user.user_language != languageApp) {
|
|
||||||
setLanguageApp(user.user_language);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (languageApp != router.locale) {
|
|
||||||
router.replace(
|
|
||||||
{pathname: router.pathname, query: router.query},
|
|
||||||
router.asPath,
|
|
||||||
{
|
|
||||||
locale: languageApp,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const lang of languageList) {
|
|
||||||
if (languageApp != lang.key) continue;
|
|
||||||
setDirectionApp(lang.dir);
|
|
||||||
document.dir = lang.dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
changeLanguageState(false);
|
|
||||||
setLanguageIsReady(true);
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearTimeout(timer);
|
|
||||||
};
|
|
||||||
}, [router.locale, router.isReady, userChangedLanguage, languageApp]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LanguageContext.Provider
|
|
||||||
value={{
|
|
||||||
languageApp,
|
|
||||||
setLanguageApp,
|
|
||||||
directionApp,
|
|
||||||
languageIsReady,
|
|
||||||
setLanguageIsReady,
|
|
||||||
languageList,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</LanguageContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import LoadingHardPage from "@/core/components/LoadingHardPage";
|
|
||||||
import {createContext, useState} from "react";
|
|
||||||
|
|
||||||
export const LoadingContext = createContext();
|
|
||||||
|
|
||||||
export const LoadingProvider = ({children}) => {
|
|
||||||
const [loadingPage, setLoadingPage] = useState(false);
|
|
||||||
return (
|
|
||||||
<LoadingContext.Provider value={{loadingPage, setLoadingPage}}>
|
|
||||||
<LoadingHardPage loading={loadingPage}/>
|
|
||||||
{children}
|
|
||||||
</LoadingContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
import {USER_INFO} from "@/core/data/apiRoutes";
|
|
||||||
import axios from "axios";
|
|
||||||
import {createContext, useCallback, useEffect, useReducer} from "react";
|
|
||||||
import {errorRequest, errorResponse, errorSetting} from "@/core/utils/errorHandler";
|
|
||||||
|
|
||||||
const initialUser = {
|
|
||||||
isAuth: false,
|
|
||||||
userChangedLanguage: false,
|
|
||||||
token: null,
|
|
||||||
user: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
const reducer = (state, action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case "CLEAR_USER":
|
|
||||||
return {...state, user: {}};
|
|
||||||
case "CHANGE_USER":
|
|
||||||
return {...state, user: action.user};
|
|
||||||
case "CHANGE_USER_LANGUAGE":
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
user: {...state.user, user_language: action.language},
|
|
||||||
};
|
|
||||||
case "CHANGE_AUTH_STATE":
|
|
||||||
return {...state, isAuth: action.isAuth};
|
|
||||||
case "CHANGE_LANGUAGE_STATE":
|
|
||||||
return {...state, userChangedLanguage: action.userChangedLanguage};
|
|
||||||
case "CLEAR_TOKEN":
|
|
||||||
localStorage.removeItem("_token");
|
|
||||||
return {...state, token: null};
|
|
||||||
case "SET_TOKEN":
|
|
||||||
localStorage.setItem("_token", action.token);
|
|
||||||
return {...state, token: action.token};
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const UserContext = createContext();
|
|
||||||
|
|
||||||
export const UserProvider = ({children}) => {
|
|
||||||
const [state, dispatch] = useReducer(reducer, initialUser);
|
|
||||||
|
|
||||||
const clearUser = useCallback(() => {
|
|
||||||
dispatch({type: "CLEAR_USER"});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const changeUser = useCallback((user) => {
|
|
||||||
dispatch({type: "CHANGE_USER", user});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const changeUserLanguage = useCallback(/* for multi language app */);
|
|
||||||
|
|
||||||
const changeAuthState = useCallback((isAuth) => {
|
|
||||||
dispatch({type: "CHANGE_AUTH_STATE", isAuth});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const changeLanguageState = useCallback((userChangedLanguage) => {
|
|
||||||
dispatch({type: "CHANGE_LANGUAGE_STATE", userChangedLanguage});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const clearToken = useCallback(() => {
|
|
||||||
dispatch({type: "CLEAR_TOKEN"});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const setToken = useCallback((token) => {
|
|
||||||
dispatch({type: "SET_TOKEN", token});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const getUser = useCallback(
|
|
||||||
(callback = () => {
|
|
||||||
}) => {
|
|
||||||
axios
|
|
||||||
.get(USER_INFO, {
|
|
||||||
headers: {authorization: `Bearer ${state.token}`},
|
|
||||||
})
|
|
||||||
.then(({data}) => {
|
|
||||||
if (typeof callback === "function") callback(data);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
if (error.response) {
|
|
||||||
errorResponse(error.response, clearToken, null, false)
|
|
||||||
} else if (error.request) {
|
|
||||||
errorRequest(null, false)
|
|
||||||
} else {
|
|
||||||
errorSetting(null, false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
[state.token]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const localToken = localStorage.getItem("_token");
|
|
||||||
if (localToken) dispatch({type: "SET_TOKEN", token: localToken});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!state.token) {
|
|
||||||
clearUser();
|
|
||||||
changeAuthState(false);
|
|
||||||
changeLanguageState(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
getUser((data) => {
|
|
||||||
changeUser(data);
|
|
||||||
changeAuthState(true);
|
|
||||||
changeLanguageState(true);
|
|
||||||
});
|
|
||||||
}, [state.token]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<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>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import {useContext} from "react";
|
|
||||||
import {LanguageContext} from "../contexts/language";
|
|
||||||
|
|
||||||
const useDirection = () => {
|
|
||||||
const {directionApp} = useContext(LanguageContext);
|
|
||||||
|
|
||||||
return {directionApp};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useDirection;
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import {useContext} from "react";
|
|
||||||
import {LanguageContext} from "../contexts/language";
|
|
||||||
import useUser from "./useUser";
|
|
||||||
|
|
||||||
const useLanguage = () => {
|
|
||||||
const {isAuth, changeUserLanguage} = useUser();
|
|
||||||
const {
|
|
||||||
languageApp,
|
|
||||||
setLanguageApp,
|
|
||||||
languageIsReady,
|
|
||||||
setLanguageIsReady,
|
|
||||||
languageList,
|
|
||||||
} = useContext(LanguageContext);
|
|
||||||
|
|
||||||
const changeLanguage = (lang) => {
|
|
||||||
if (lang == languageApp) return;
|
|
||||||
|
|
||||||
setLanguageIsReady(false);
|
|
||||||
setLanguageApp(lang);
|
|
||||||
if (isAuth) {
|
|
||||||
changeUserLanguage(lang);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return {languageApp, changeLanguage, languageIsReady, languageList};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useLanguage;
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import {useContext} from "react";
|
|
||||||
import {LoadingContext} from "../contexts/loading";
|
|
||||||
|
|
||||||
const useLoading = () => {
|
|
||||||
const {setLoadingPage} = useContext(LoadingContext);
|
|
||||||
|
|
||||||
return {setLoadingPage};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useLoading;
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
import {useEffect, useState} from "react";
|
|
||||||
|
|
||||||
function getNetworkConnection() {
|
|
||||||
return (
|
|
||||||
navigator.connection ||
|
|
||||||
navigator.mozConnection ||
|
|
||||||
navigator.webkitConnection ||
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNetworkConnectionInfo() {
|
|
||||||
const connection = getNetworkConnection();
|
|
||||||
if (!connection) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
rtt: connection.rtt,
|
|
||||||
type: connection.type,
|
|
||||||
saveData: connection.saveData,
|
|
||||||
downLink: connection.downLink,
|
|
||||||
downLinkMax: connection.downLinkMax,
|
|
||||||
effectiveType: connection.effectiveType,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function useNetwork() {
|
|
||||||
const [state, setState] = useState(() => {
|
|
||||||
return {
|
|
||||||
online: navigator.onLine,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
const handleOnline = () => {
|
|
||||||
setState((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
online: true,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
const handleOffline = () => {
|
|
||||||
setState((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
online: false,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener("online", handleOnline);
|
|
||||||
window.addEventListener("offline", handleOffline);
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener("online", handleOnline);
|
|
||||||
window.removeEventListener("offline", handleOffline);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useNetwork;
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import axios from "axios";
|
|
||||||
import {successRequest} from "@/core/utils/succesHandler";
|
|
||||||
import PendingNotification from "@/core/components/notifications/PendingNotification";
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
|
||||||
import {errorRequest, errorResponse, errorSetting} from "@/core/utils/errorHandler";
|
|
||||||
import useNetwork from "@/lib/app/hooks/useNetwork";
|
|
||||||
|
|
||||||
const defaultOptions = {
|
|
||||||
auth: false, data: {}, requestOptions: {
|
|
||||||
headers: {}
|
|
||||||
}, notification: true, pending: true, success: {
|
|
||||||
notification: {
|
|
||||||
show: true,
|
|
||||||
},
|
|
||||||
}, failed: {
|
|
||||||
notification: {
|
|
||||||
show: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const useRequest = (initOptions) => {
|
|
||||||
const network = useNetwork()
|
|
||||||
const t = useTranslations()
|
|
||||||
const {token, clearToken} = useUser()
|
|
||||||
let _options = {...defaultOptions, ...initOptions}
|
|
||||||
|
|
||||||
function requestServer(url = '', method = 'get', options) {
|
|
||||||
_options = {..._options, ...options}
|
|
||||||
if (_options.auth) _options = {
|
|
||||||
..._options, requestOptions: {
|
|
||||||
..._options.requestOptions,
|
|
||||||
headers: {..._options.requestOptions.headers, authorization: `Bearer ${token}`}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (!network.online) {
|
|
||||||
reject()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (_options.notification && _options.failed.notification.show && _options.pending) PendingNotification(t)
|
|
||||||
axios({
|
|
||||||
url: url, method: method, data: _options.data, ..._options.requestOptions
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
successRequest(response, t, _options)
|
|
||||||
resolve(response)
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
if (error.response) {
|
|
||||||
errorResponse(error.response, clearToken, t, _options.notification && _options.failed.notification.show)
|
|
||||||
} else if (error.request) {
|
|
||||||
errorRequest(t, _options.notification && _options.failed.notification.show)
|
|
||||||
} else {
|
|
||||||
errorSetting(t, _options.notification && _options.failed.notification.show)
|
|
||||||
}
|
|
||||||
reject(error)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return requestServer
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useRequest
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import {useContext} from "react";
|
|
||||||
import {UserContext} from "../contexts/user";
|
|
||||||
|
|
||||||
const useUser = () => {
|
|
||||||
const {
|
|
||||||
isAuth,
|
|
||||||
userChangedLanguage,
|
|
||||||
token,
|
|
||||||
user,
|
|
||||||
getUser,
|
|
||||||
clearUser,
|
|
||||||
changeUser,
|
|
||||||
changeUserLanguage,
|
|
||||||
changeAuthState,
|
|
||||||
changeLanguageState,
|
|
||||||
clearToken,
|
|
||||||
setToken,
|
|
||||||
} = useContext(UserContext);
|
|
||||||
|
|
||||||
return {
|
|
||||||
isAuth,
|
|
||||||
userChangedLanguage,
|
|
||||||
token,
|
|
||||||
user,
|
|
||||||
getUser,
|
|
||||||
clearUser,
|
|
||||||
changeUser,
|
|
||||||
changeUserLanguage,
|
|
||||||
changeAuthState,
|
|
||||||
changeLanguageState,
|
|
||||||
clearToken,
|
|
||||||
setToken,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useUser;
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
|
||||||
import Message from "@/core/components/Messages";
|
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
|
||||||
import {Button, Typography} from "@mui/material";
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
|
|
||||||
const UserTypeMiddleware = ({children, user_type}) => {
|
|
||||||
const {user} = useUser();
|
|
||||||
const t = useTranslations();
|
|
||||||
|
|
||||||
const userPermission = user.type_id === user_type;
|
|
||||||
|
|
||||||
if (!userPermission) {
|
|
||||||
return (
|
|
||||||
<Message
|
|
||||||
text={
|
|
||||||
<Typography sx={{textAlign: "center"}}>
|
|
||||||
{t("Permission.typography_you_dont_have_access")}
|
|
||||||
</Typography>
|
|
||||||
}
|
|
||||||
actions={
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
component={NextLinkComposed}
|
|
||||||
to={{
|
|
||||||
pathname: "/dashboard",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("Permission.button_back_dashboard")}
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <>{children}</>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UserTypeMiddleware;
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
|
||||||
import Message from "@/core/components/Messages";
|
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
|
||||||
import {Button, Typography} from "@mui/material";
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
import {useRouter} from "next/router";
|
|
||||||
|
|
||||||
const WithAuthMiddleware = ({children}) => {
|
|
||||||
const {isAuth} = useUser();
|
|
||||||
const t = useTranslations();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
if (!isAuth)
|
|
||||||
return (
|
|
||||||
<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: "/login",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("login")}
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
return <>{children}</>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default WithAuthMiddleware;
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
import Message from "@/core/components/Messages";
|
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
|
||||||
import {Stack, Typography} from "@mui/material";
|
|
||||||
import {useTranslations} from "next-intl";
|
|
||||||
import {useSearchParams} from "next/navigation";
|
|
||||||
import {useRouter} from "next/router";
|
|
||||||
import {useEffect} from "react";
|
|
||||||
|
|
||||||
const WithoutAuthMiddleware = ({children}) => {
|
|
||||||
const {isAuth} = useUser();
|
|
||||||
const t = useTranslations();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
// gettin url query
|
|
||||||
const searchParams = useSearchParams();
|
|
||||||
const backUrlDecodedPath = searchParams.get("back_url");
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isAuth) return;
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
router.replace(
|
|
||||||
backUrlDecodedPath
|
|
||||||
? decodeURIComponent(backUrlDecodedPath)
|
|
||||||
: "/dashboard"
|
|
||||||
);
|
|
||||||
}, 2000);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearTimeout(timer);
|
|
||||||
};
|
|
||||||
}, [isAuth]);
|
|
||||||
|
|
||||||
if (isAuth)
|
|
||||||
return (
|
|
||||||
<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;
|
|
||||||
@@ -1,25 +1,41 @@
|
|||||||
import "&/fontiran.scss";
|
import "&/global.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 "moment/locale/fa";
|
import "moment/locale/fa";
|
||||||
|
import {
|
||||||
|
AppLayout,
|
||||||
|
LanguageProvider,
|
||||||
|
LoadingProvider,
|
||||||
|
MuiLayout,
|
||||||
|
NetworkProvider,
|
||||||
|
ToastProvider,
|
||||||
|
UserProvider
|
||||||
|
} from "@witel/webapp-builder";
|
||||||
|
import {GET_USER} from "@/core/data/apiRoutes";
|
||||||
|
import languageList from "@/core/data/languageList";
|
||||||
import {NextIntlProvider} from "next-intl";
|
import {NextIntlProvider} from "next-intl";
|
||||||
|
import themeRtl from "@/core/utils/theme-rtl";
|
||||||
import TitlePage from "@/core/components/TitlePage";
|
import TitlePage from "@/core/components/TitlePage";
|
||||||
|
import GlobalHead from "@/core/components/GlobalHead";
|
||||||
|
import Layout from "@/layouts";
|
||||||
|
|
||||||
const App = ({Component, pageProps}) => {
|
const App = ({Component, pageProps}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<UserProvider>
|
<UserProvider urlGetUser={GET_USER} schemaGetUser={(data) => data}>
|
||||||
<LanguageProvider>
|
<LanguageProvider defaultLanguage={process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE}
|
||||||
<NextIntlProvider messages={pageProps.messages || {}}>
|
languageList={languageList}>
|
||||||
<MuiLayout isBot={pageProps.isBot}>
|
<NextIntlProvider locale={pageProps.locale} messages={pageProps.messages || {}}>
|
||||||
|
<MuiLayout themes={{rtl: themeRtl}} isBot={pageProps.isBot}>
|
||||||
{pageProps.messages ? <TitlePage text={pageProps.title}/> : ''}
|
{pageProps.messages ? <TitlePage text={pageProps.title}/> : ''}
|
||||||
<LoadingProvider>
|
<LoadingProvider>
|
||||||
<AppLayout isBot={pageProps.isBot}>
|
<ToastProvider>
|
||||||
<Component {...pageProps} />
|
<AppLayout headComponent={GlobalHead} isBot={pageProps.isBot}>
|
||||||
</AppLayout>
|
<NetworkProvider>
|
||||||
|
<Layout layout={pageProps.layout}>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</Layout>
|
||||||
|
</NetworkProvider>
|
||||||
|
</AppLayout>
|
||||||
|
</ToastProvider>
|
||||||
</LoadingProvider>
|
</LoadingProvider>
|
||||||
</MuiLayout>
|
</MuiLayout>
|
||||||
</NextIntlProvider>
|
</NextIntlProvider>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import {createEmotionCacheRtl} from "@/core/utils/createEmotionCache";
|
|
||||||
import theme from "@/core/utils/theme";
|
import theme from "@/core/utils/theme";
|
||||||
import createEmotionServer from "@emotion/server/create-instance";
|
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";
|
||||||
|
import {createEmotionCacheLtr, createEmotionCacheRtl} from "@witel/webapp-builder";
|
||||||
|
import languageList from "@/core/data/languageList";
|
||||||
|
|
||||||
export default function MyDocument(props) {
|
export default function MyDocument(props) {
|
||||||
const {emotionStyleTags} = props;
|
const {emotionStyleTags} = props;
|
||||||
@@ -26,10 +27,13 @@ export default function MyDocument(props) {
|
|||||||
MyDocument.getInitialProps = async (ctx) => {
|
MyDocument.getInitialProps = async (ctx) => {
|
||||||
const originalRenderPage = ctx.renderPage;
|
const originalRenderPage = ctx.renderPage;
|
||||||
let cache;
|
let cache;
|
||||||
switch (ctx.locale) {
|
for (const lang of languageList) {
|
||||||
case "fa":
|
if (ctx.locale !== lang.key) continue;
|
||||||
|
if (lang.dir === 'rtl') {
|
||||||
cache = createEmotionCacheRtl();
|
cache = createEmotionCacheRtl();
|
||||||
break;
|
} else {
|
||||||
|
cache = createEmotionCacheLtr();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const {extractCriticalToChunks} = createEmotionServer(cache);
|
const {extractCriticalToChunks} = createEmotionServer(cache);
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
import FirstComponent from "@/components/dashboard/first";
|
import FirstComponent from "@/components/dashboard/first";
|
||||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
|
||||||
import {parse} from "next-useragent";
|
import {parse} from "next-useragent";
|
||||||
|
|
||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
return (
|
return (
|
||||||
<WithAuthMiddleware>
|
<FirstComponent/>
|
||||||
<FirstComponent/>
|
|
||||||
</WithAuthMiddleware>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,6 +14,8 @@ export async function getServerSideProps({req, locale}) {
|
|||||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||||
title: "Dashboard.dashboard_page",
|
title: "Dashboard.dashboard_page",
|
||||||
isBot,
|
isBot,
|
||||||
|
locale,
|
||||||
|
layout: {name: 'DashboardLayout'}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,9 @@
|
|||||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
|
||||||
import {parse} from "next-useragent";
|
import {parse} from "next-useragent";
|
||||||
import UserTypeMiddleware from "@/middlewares/UserType";
|
|
||||||
import LoanRequestComponent from "@/components/dashboard/navgan/add-request-loan";
|
import LoanRequestComponent from "@/components/dashboard/navgan/add-request-loan";
|
||||||
|
|
||||||
const user_type = 1;
|
|
||||||
export default function AddLoanRequest() {
|
export default function AddLoanRequest() {
|
||||||
return (
|
return (
|
||||||
<WithAuthMiddleware>
|
<LoanRequestComponent/>
|
||||||
<UserTypeMiddleware user_type={user_type}>
|
|
||||||
<LoanRequestComponent/>
|
|
||||||
</UserTypeMiddleware>
|
|
||||||
</WithAuthMiddleware>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +14,8 @@ export async function getServerSideProps({req, locale}) {
|
|||||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||||
title: "LoanRequest.loan_request_page",
|
title: "LoanRequest.loan_request_page",
|
||||||
isBot,
|
isBot,
|
||||||
|
locale,
|
||||||
|
layout: {name: 'DashboardLayout'}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,9 @@
|
|||||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
|
||||||
import {parse} from "next-useragent";
|
import {parse} from "next-useragent";
|
||||||
import UserTypeMiddleware from "@/middlewares/UserType";
|
|
||||||
import LoanFollowUpComponent from "@/components/dashboard/navgan/followUp-loan";
|
import LoanFollowUpComponent from "@/components/dashboard/navgan/followUp-loan";
|
||||||
|
|
||||||
const user_type = 1;
|
|
||||||
export default function FollowUpLoan() {
|
export default function FollowUpLoan() {
|
||||||
return (
|
return (
|
||||||
<WithAuthMiddleware>
|
<LoanFollowUpComponent/>
|
||||||
<UserTypeMiddleware user_type={user_type}>
|
|
||||||
<LoanFollowUpComponent/>
|
|
||||||
</UserTypeMiddleware>
|
|
||||||
</WithAuthMiddleware>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +14,8 @@ export async function getServerSideProps({req, locale}) {
|
|||||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||||
title: "LoanRequest.loan_request_page",
|
title: "LoanRequest.loan_request_page",
|
||||||
isBot,
|
isBot,
|
||||||
|
locale,
|
||||||
|
layout: {name: 'DashboardLayout'}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
|
||||||
import {parse} from "next-useragent";
|
|
||||||
|
|
||||||
const user_type = 2;
|
|
||||||
export default function AddLoanRequest() {
|
|
||||||
return (
|
|
||||||
<WithAuthMiddleware>
|
|
||||||
{/*<UserTypeMiddleware user_type={user_type}>*/}
|
|
||||||
{/* <LoanRequestComponent/>*/}
|
|
||||||
{/*</UserTypeMiddleware>*/}
|
|
||||||
</WithAuthMiddleware>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getServerSideProps({req, locale}) {
|
|
||||||
const {isBot} = parse(req.headers["user-agent"]);
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
|
||||||
title: "LoanRequest.loan_request_page",
|
|
||||||
isBot,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
|
||||||
import {parse} from "next-useragent";
|
|
||||||
|
|
||||||
const user_type = 2;
|
|
||||||
export default function EditLoanRequest() {
|
|
||||||
return (
|
|
||||||
<WithAuthMiddleware>
|
|
||||||
{/*<UserTypeMiddleware user_type={user_type}>*/}
|
|
||||||
{/* <LoanRequestComponent/>*/}
|
|
||||||
{/*</UserTypeMiddleware>*/}
|
|
||||||
</WithAuthMiddleware>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getServerSideProps({req, locale}) {
|
|
||||||
const {isBot} = parse(req.headers["user-agent"]);
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
|
||||||
title: "EditLoanRequest.edit_loan_request_page",
|
|
||||||
isBot,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
|
||||||
import {parse} from "next-useragent";
|
|
||||||
|
|
||||||
const user_type = 2;
|
|
||||||
export default function FollowUpLoan() {
|
|
||||||
return (
|
|
||||||
<WithAuthMiddleware>
|
|
||||||
{/*<UserTypeMiddleware user_type={user_type}>*/}
|
|
||||||
{/* <LoanFollowUpComponent/>*/}
|
|
||||||
{/*</UserTypeMiddleware>*/}
|
|
||||||
</WithAuthMiddleware>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getServerSideProps({req, locale}) {
|
|
||||||
const {isBot} = parse(req.headers["user-agent"]);
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
|
||||||
title: "LoanFollowUp.loan_follow_up_page",
|
|
||||||
isBot,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import LoginComponent from "@/components/login";
|
import LoginComponent from "@/components/login";
|
||||||
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
|
|
||||||
import {parse} from "next-useragent";
|
import {parse} from "next-useragent";
|
||||||
|
import {WithoutAuthMiddleware} from "@witel/webapp-builder";
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
return (
|
return (
|
||||||
<WithoutAuthMiddleware>
|
<WithoutAuthMiddleware defaultUrl={'/'}>
|
||||||
<LoginComponent/>
|
<LoginComponent/>
|
||||||
</WithoutAuthMiddleware>
|
</WithoutAuthMiddleware>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import RegisterComponent from "@/components/register";
|
import RegisterComponent from "@/components/register";
|
||||||
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
|
|
||||||
import {parse} from "next-useragent";
|
import {parse} from "next-useragent";
|
||||||
|
import {WithoutAuthMiddleware} from "@witel/webapp-builder";
|
||||||
|
|
||||||
export default function Register() {
|
export default function Register() {
|
||||||
return (
|
return (
|
||||||
<WithoutAuthMiddleware>
|
<WithoutAuthMiddleware defaultUrl={'/'}>
|
||||||
<RegisterComponent/>
|
<RegisterComponent/>
|
||||||
</WithoutAuthMiddleware>
|
</WithoutAuthMiddleware>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user