CFE-1 create project from the tamplate project and config project
This commit is contained in:
149
src/components/dashboard/change-password/index.jsx
Normal file
149
src/components/dashboard/change-password/index.jsx
Normal file
@@ -0,0 +1,149 @@
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||
import {Button, Container, Paper, Stack, Typography,} from "@mui/material";
|
||||
import {Formik} from "formik";
|
||||
import * as Yup from "yup";
|
||||
import {useTranslations} from "next-intl";
|
||||
import PasswordField from "@/core/components/PasswordField";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import {SET_USER_PASSWORD} from "@/core/data/apiRoutes";
|
||||
import SvgChangePassword from "@/core/components/svgs/SvgChangePassword";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
|
||||
const DashboardChangePasswordComponent = () => {
|
||||
const t = useTranslations();
|
||||
const requestServer = useRequest({auth: true})
|
||||
|
||||
const handleSubmit = (values, {setSubmitting, resetForm}) => {
|
||||
requestServer(SET_USER_PASSWORD, 'post', {
|
||||
data: {
|
||||
current_password: values.current_password,
|
||||
new_password: values.new_password,
|
||||
new_password_confirmation: values.new_password_confirmation,
|
||||
},
|
||||
}).then((response) => {
|
||||
resetForm();
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
setSubmitting(false);
|
||||
});
|
||||
};
|
||||
const initialValues = {
|
||||
current_password: "",
|
||||
new_password: "",
|
||||
new_password_confirmation: "",
|
||||
};
|
||||
const validationSchema = Yup.object().shape({
|
||||
current_password: Yup.string().required(
|
||||
t("ChangePassword.error_message_required")
|
||||
),
|
||||
new_password: Yup.string()
|
||||
.min(8, t("ChangePassword.error_message_password_length"))
|
||||
.required(t("ChangePassword.error_message_required")),
|
||||
new_password_confirmation: Yup.string()
|
||||
.required(t("ChangePassword.error_message_required"))
|
||||
.test(
|
||||
t("ChangePassword.error_message_password_match"),
|
||||
t("ChangePassword.error_message_password_not_match"),
|
||||
function (value) {
|
||||
return this.parent.new_password === value;
|
||||
}
|
||||
),
|
||||
});
|
||||
|
||||
return (
|
||||
<DashboardLayouts>
|
||||
<CenterLayout>
|
||||
<Container maxWidth="sm">
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validationSchema={validationSchema}
|
||||
>
|
||||
{(props) => (
|
||||
<StyledForm
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
props.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<Paper elevation={0}>
|
||||
<Stack spacing={3} sx={{p: 5}} component="div">
|
||||
<SvgChangePassword width={300} height={200}/>
|
||||
<Typography margin={2} variant="h4" textAlign="center">
|
||||
{t("ChangePassword.typography_change_password")}
|
||||
</Typography>
|
||||
<Stack spacing={1} component="div">
|
||||
<PasswordField
|
||||
name="current_password"
|
||||
label={t("ChangePassword.label_current_password")}
|
||||
error={
|
||||
props.touched.current_password &&
|
||||
props.errors.current_password
|
||||
? true
|
||||
: false
|
||||
}
|
||||
helperText={
|
||||
props.touched.current_password
|
||||
? props.errors.current_password
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack spacing={1} component="div">
|
||||
<PasswordField
|
||||
name="new_password"
|
||||
label={t("ChangePassword.label_new_password")}
|
||||
error={
|
||||
props.touched.new_password &&
|
||||
props.errors.new_password
|
||||
? true
|
||||
: false
|
||||
}
|
||||
helperText={
|
||||
props.touched.new_password
|
||||
? props.errors.new_password
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack spacing={1} component="div">
|
||||
<PasswordField
|
||||
name="new_password_confirmation"
|
||||
label={t("ChangePassword.label_confirm_password")}
|
||||
error={
|
||||
props.touched.new_password_confirmation &&
|
||||
props.errors.new_password_confirmation
|
||||
? true
|
||||
: false
|
||||
}
|
||||
helperText={
|
||||
props.touched.new_password_confirmation
|
||||
? props.errors.new_password_confirmation
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
<Button
|
||||
type="submit"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
color="primary"
|
||||
size="large"
|
||||
disabled={props.isSubmitting}
|
||||
>
|
||||
{props.isSubmitting
|
||||
? t("SubmitButton.button_while_submit")
|
||||
: t("SubmitButton.button_submit")}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</StyledForm>
|
||||
)}
|
||||
</Formik>
|
||||
</Container>
|
||||
</CenterLayout>
|
||||
</DashboardLayouts>
|
||||
);
|
||||
};
|
||||
export default DashboardChangePasswordComponent;
|
||||
223
src/components/dashboard/edit-profile/index.jsx
Normal file
223
src/components/dashboard/edit-profile/index.jsx
Normal file
@@ -0,0 +1,223 @@
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import {Box, Container, Grid, Paper, Stack, TextField, Typography,} from "@mui/material";
|
||||
import * as Yup from "yup";
|
||||
import {Field, Formik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
import AvatarUpload from "@/core/components/AvatarUpload";
|
||||
import axios from "axios";
|
||||
import {UPDATE_AVATAR} from "@/core/data/apiRoutes";
|
||||
import useDirection from "@/lib/app/hooks/useDirection";
|
||||
import Notifications from "@/core/components/notifications";
|
||||
import ImageResizer from "@/core/components/ImageConvertor";
|
||||
|
||||
const DashboardEditProfile = () => {
|
||||
const t = useTranslations();
|
||||
const {user, token, getUser, changeUser} = useUser();
|
||||
const {directionApp} = useDirection();
|
||||
|
||||
const editAvatar = async (avatar) => {
|
||||
Notifications(t);
|
||||
try {
|
||||
const formData = new FormData();
|
||||
|
||||
if (avatar != null) {
|
||||
var resizedAvatar;
|
||||
resizedAvatar = await ImageResizer(avatar);
|
||||
formData.append("avatar", resizedAvatar);
|
||||
}
|
||||
|
||||
await axios.post(UPDATE_AVATAR, formData, {
|
||||
headers: {
|
||||
authorization: `Bearer ${token}`,
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
Notifications(t, error.response);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
const handleSubmit = (values, {setSubmitting}) => {
|
||||
|
||||
};
|
||||
const initialValues = {
|
||||
expert_avatar: null,
|
||||
username: user.username,
|
||||
name: user.name,
|
||||
email: user.email,
|
||||
province_name: user.province_name,
|
||||
position: user.position,
|
||||
};
|
||||
const validationSchema = Yup.object().shape({});
|
||||
|
||||
return (
|
||||
<DashboardLayouts>
|
||||
<CenterLayout>
|
||||
<Container maxWidth="sm">
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validationSchema={validationSchema}
|
||||
>
|
||||
{(props) => (
|
||||
<StyledForm
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
props.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<Paper elevation={0}>
|
||||
<Stack spacing={3} sx={{p: 5}} component="div">
|
||||
<Typography margin={2} variant="h4" textAlign="center">
|
||||
{t("UpdateProfile.typography_edit_profile")}
|
||||
</Typography>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<AvatarUpload
|
||||
user={user}
|
||||
setFieldValue={props.setFieldValue}
|
||||
valueAvatar="expert_avatar"
|
||||
changeFlag="change_avatar"
|
||||
/>
|
||||
</Box>
|
||||
<Grid container spacing={2} sx={{pb: 2}}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Field
|
||||
as={TextField}
|
||||
name="username"
|
||||
label={t("UpdateProfile.text_field_username")}
|
||||
variant="outlined"
|
||||
margin="normal"
|
||||
size="small"
|
||||
disabled={true}
|
||||
error={
|
||||
props.touched.username && props.errors.username
|
||||
? true
|
||||
: false
|
||||
}
|
||||
helperText={
|
||||
props.touched.username
|
||||
? props.errors.username
|
||||
: null
|
||||
}
|
||||
sx={{
|
||||
width: "100%",
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Field
|
||||
as={TextField}
|
||||
name="name"
|
||||
label={t("UpdateProfile.text_field_name")}
|
||||
variant="outlined"
|
||||
margin="normal"
|
||||
size="small"
|
||||
disabled={true}
|
||||
error={
|
||||
props.touched.name && props.errors.name
|
||||
? true
|
||||
: false
|
||||
}
|
||||
helperText={
|
||||
props.touched.name ? props.errors.name : null
|
||||
}
|
||||
sx={{
|
||||
width: "100%",
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Field
|
||||
as={TextField}
|
||||
name="email"
|
||||
label={t("UpdateProfile.text_field_email")}
|
||||
variant="outlined"
|
||||
margin="normal"
|
||||
size="small"
|
||||
disabled={true}
|
||||
error={
|
||||
props.touched.email && props.errors.email
|
||||
? true
|
||||
: false
|
||||
}
|
||||
helperText={
|
||||
props.touched.email ? props.errors.email : null
|
||||
}
|
||||
sx={{
|
||||
width: "100%",
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Field
|
||||
as={TextField}
|
||||
name="province_name"
|
||||
label={t("UpdateProfile.text_field_province_name")}
|
||||
variant="outlined"
|
||||
margin="normal"
|
||||
size="small"
|
||||
disabled={true}
|
||||
error={
|
||||
props.touched.province_name &&
|
||||
props.errors.province_name
|
||||
? true
|
||||
: false
|
||||
}
|
||||
helperText={
|
||||
props.touched.province_name
|
||||
? props.errors.province_name
|
||||
: null
|
||||
}
|
||||
sx={{
|
||||
width: "100%",
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Field
|
||||
as={TextField}
|
||||
name="position"
|
||||
label={t("UpdateProfile.text_field_position")}
|
||||
variant="outlined"
|
||||
margin="normal"
|
||||
size="small"
|
||||
disabled={true}
|
||||
error={
|
||||
props.touched.position && props.errors.position
|
||||
? true
|
||||
: false
|
||||
}
|
||||
helperText={
|
||||
props.touched.position
|
||||
? props.errors.position
|
||||
: null
|
||||
}
|
||||
sx={{
|
||||
width: "100%",
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</StyledForm>
|
||||
)}
|
||||
</Formik>
|
||||
</Container>
|
||||
</CenterLayout>
|
||||
</DashboardLayouts>
|
||||
);
|
||||
};
|
||||
|
||||
export default DashboardEditProfile;
|
||||
7
src/components/dashboard/first/index.jsx
Normal file
7
src/components/dashboard/first/index.jsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||
|
||||
const DashboardFirstComponent = () => {
|
||||
return <DashboardLayouts></DashboardLayouts>;
|
||||
};
|
||||
|
||||
export default DashboardFirstComponent;
|
||||
37
src/components/errors/403.jsx
Normal file
37
src/components/errors/403.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import {Button, Typography} from "@mui/material";
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import {useTranslations} from "next-intl";
|
||||
import TitlePage from "@/core/components/TitlePage";
|
||||
import Svg403 from "@/core/components/svgs/Svg403";
|
||||
|
||||
const UnAuthorizedComponent = () => {
|
||||
const t = useTranslations();
|
||||
|
||||
return (
|
||||
<>
|
||||
<TitlePage text="Titles.title_custom_403"/>
|
||||
<FullPageLayout sx={{p: 1}}>
|
||||
<CenterLayout spacing={3}>
|
||||
<Svg403 width={300} height={200}/>
|
||||
<Typography margin={2} variant="h6" textAlign="center">
|
||||
{t("ErrorPage.custom_403")}
|
||||
</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: "/",
|
||||
}}
|
||||
>
|
||||
{t("ErrorPage.link_routing_back_to")}{" "}
|
||||
{t("ErrorPage.link_routing_main_page")}
|
||||
</Button>
|
||||
</CenterLayout>
|
||||
</FullPageLayout>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default UnAuthorizedComponent;
|
||||
37
src/components/errors/404.jsx
Normal file
37
src/components/errors/404.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import {Button, Typography} from "@mui/material";
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import {useTranslations} from "next-intl";
|
||||
import TitlePage from "@/core/components/TitlePage";
|
||||
import Svg404 from "@/core/components/svgs/Svg404";
|
||||
|
||||
const NotFoundComponent = () => {
|
||||
const t = useTranslations();
|
||||
|
||||
return (
|
||||
<>
|
||||
<TitlePage text="Titles.title_custom_404"/>
|
||||
<FullPageLayout sx={{p: 1}}>
|
||||
<CenterLayout spacing={3}>
|
||||
<Svg404 width={300} height={200}/>
|
||||
<Typography margin={2} variant="h6" textAlign="center">
|
||||
{t("ErrorPage.custom_404")}
|
||||
</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: "/",
|
||||
}}
|
||||
>
|
||||
{t("ErrorPage.link_routing_back_to")}{" "}
|
||||
{t("ErrorPage.link_routing_main_page")}
|
||||
</Button>
|
||||
</CenterLayout>
|
||||
</FullPageLayout>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotFoundComponent;
|
||||
48
src/components/errors/500.jsx
Normal file
48
src/components/errors/500.jsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import {Box, Button, Container, Stack, Typography} from "@mui/material";
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import {useTranslations} from "next-intl";
|
||||
import Image from "next/image";
|
||||
import TitlePage from "@/core/components/TitlePage";
|
||||
|
||||
const ServerErrorComponent = () => {
|
||||
const t = useTranslations();
|
||||
|
||||
return (
|
||||
<>
|
||||
<TitlePage text="Titles.title_custom_500"/>
|
||||
<FullPageLayout sx={{p: 1}}>
|
||||
<CenterLayout>
|
||||
<Container maxWidth="sm">
|
||||
<Stack spacing={4} sx={{p: 4}}>
|
||||
<Box sx={{position: "relative", width: "100%", height: 200}}>
|
||||
<Image
|
||||
fill
|
||||
src="/images/500.svg"
|
||||
alt={t("app_name")}
|
||||
priority
|
||||
/>
|
||||
</Box>
|
||||
<Typography margin={2} variant="h6" textAlign="center">
|
||||
{t("ErrorPage.custom_500")}
|
||||
</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: "/",
|
||||
}}
|
||||
>
|
||||
{t("ErrorPage.link_routing_back_to")}{" "}
|
||||
{t("ErrorPage.link_routing_main_page")}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Container>
|
||||
</CenterLayout>
|
||||
</FullPageLayout>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ServerErrorComponent;
|
||||
55
src/components/first/index.jsx
Normal file
55
src/components/first/index.jsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import {Button, Stack, Typography} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import SvgDashboard from "@/core/components/svgs/SvgDashboard";
|
||||
|
||||
const FirstComponent = () => {
|
||||
const t = useTranslations();
|
||||
const {isAuth} = useUser();
|
||||
|
||||
return (
|
||||
<FullPageLayout sx={{p: 1}}>
|
||||
<CenterLayout spacing={3}>
|
||||
<SvgDashboard width={300} height={200}/>
|
||||
<Typography variant="h5" sx={{textAlign: "center"}}>
|
||||
{t("app_name")}
|
||||
</Typography>
|
||||
{isAuth ? (
|
||||
<Button
|
||||
variant="outlined"
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: "/dashboard",
|
||||
}}
|
||||
>
|
||||
{t("dashboard")}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
sx={{mx: 2}}
|
||||
variant="contained"
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: "/login-expert",
|
||||
}}
|
||||
>
|
||||
{t("login_expert")}
|
||||
</Button>
|
||||
)}
|
||||
</CenterLayout>
|
||||
<Stack direction="row" alignItems="center" justifyContent="center">
|
||||
<Typography variant={"caption"}
|
||||
sx={{
|
||||
color: 'primary.main',
|
||||
fontFamily: 'Arial',
|
||||
fontWeight: 'bold'
|
||||
}}>v{process.env.NEXT_PUBLIC_API_VERSION}</Typography>
|
||||
</Stack>
|
||||
</FullPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default FirstComponent;
|
||||
153
src/components/login-expert/index.jsx
Normal file
153
src/components/login-expert/index.jsx
Normal file
@@ -0,0 +1,153 @@
|
||||
import LinkRouting from "@/core/components/LinkRouting";
|
||||
import PasswordField from "@/core/components/PasswordField";
|
||||
import StyledForm from "@/core/components/StyledForm";
|
||||
import {GET_USER_TOKEN} from "@/core/data/apiRoutes";
|
||||
import CenterLayout from "@/layouts/CenterLayout";
|
||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import LoginIcon from "@mui/icons-material/Login";
|
||||
import {Box, Button, Container, Paper, Stack, TextField, Typography,} from "@mui/material";
|
||||
import {Field, Formik} from "formik";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {useSearchParams} from "next/navigation";
|
||||
import * as Yup from "yup";
|
||||
import useDirection from "@/lib/app/hooks/useDirection";
|
||||
import SvgLogin from "@/core/components/svgs/SvgLogin";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
|
||||
const LoginComponent = () => {
|
||||
const t = useTranslations();
|
||||
const {directionApp} = useDirection(); // should delete because we don't have direction anymore
|
||||
const {setToken} = useUser(); // pass token to set token
|
||||
const requestServer = useRequest()
|
||||
|
||||
// getting url query
|
||||
const searchParams = useSearchParams();
|
||||
const backUrlDecodedPath = searchParams.get("back_url");
|
||||
|
||||
//formik properties
|
||||
const handleSubmit = (values, props) => {
|
||||
requestServer(GET_USER_TOKEN, 'post', {
|
||||
data: {
|
||||
username: values.username,
|
||||
password: values.password,
|
||||
},
|
||||
success: {
|
||||
notification: {show: false}
|
||||
}
|
||||
}).then((response) => {
|
||||
setToken(response.data.token)
|
||||
}).catch(() => {
|
||||
props.setSubmitting(false)
|
||||
})
|
||||
};
|
||||
const initialValues = {
|
||||
username: "",
|
||||
password: "",
|
||||
};
|
||||
const validationSchema = Yup.object().shape({
|
||||
username: Yup.string().required(t("LoginPage.error_message_required")),
|
||||
password: Yup.string().required(t("LoginPage.error_message_required")),
|
||||
});
|
||||
|
||||
return (
|
||||
<FullPageLayout sx={{p: 1}}>
|
||||
<CenterLayout>
|
||||
<Container maxWidth="sm">
|
||||
<Paper elevation={0}>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validationSchema={validationSchema}
|
||||
>
|
||||
{(props) => (
|
||||
<Stack spacing={2} sx={{p: 2}}>
|
||||
<Stack
|
||||
sx={{width: "100%"}}
|
||||
alignItems='center'
|
||||
>
|
||||
<SvgLogin width={300} height={200}/>
|
||||
</Stack>
|
||||
<Typography margin={2} variant="h4" textAlign="center">
|
||||
{t("login_expert")}
|
||||
</Typography>
|
||||
<StyledForm sx={{width: "100%"}}>
|
||||
<Stack spacing={3} sx={{p: 2}}>
|
||||
<Field
|
||||
as={TextField}
|
||||
name="username"
|
||||
variant="outlined"
|
||||
label={t("LoginPage.text_field_user_name")}
|
||||
placeholder={t(
|
||||
"LoginPage.text_field_enter_your_username"
|
||||
)}
|
||||
type={"text"}
|
||||
error={
|
||||
props.touched.username && props.errors.username
|
||||
? true
|
||||
: false
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
props.touched.username ? props.errors.username : null
|
||||
}
|
||||
/>
|
||||
<PasswordField
|
||||
name="password"
|
||||
label={t("LoginPage.text_field_password")}
|
||||
error={
|
||||
props.touched.password && props.errors.password
|
||||
? true
|
||||
: false
|
||||
}
|
||||
helperText={
|
||||
props.touched.password ? props.errors.password : null
|
||||
}
|
||||
placeholder={t(
|
||||
"LoginPage.text_field_enter_your_password"
|
||||
)}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
fullWidth
|
||||
size="medium"
|
||||
endIcon={<LoginIcon/>}
|
||||
disabled={props.isSubmitting}
|
||||
>
|
||||
{t("LoginPage.button_submit")}
|
||||
</Button>
|
||||
</Box>
|
||||
</Stack>
|
||||
</StyledForm>
|
||||
</Stack>
|
||||
)}
|
||||
</Formik>
|
||||
</Paper>
|
||||
</Container>
|
||||
</CenterLayout>
|
||||
<Stack direction="row" alignItems="center" justifyContent="center">
|
||||
<LinkRouting
|
||||
sx={{margin: 2}}
|
||||
href={
|
||||
backUrlDecodedPath ? decodeURIComponent(backUrlDecodedPath) : "/"
|
||||
}
|
||||
>
|
||||
{t("LoginPage.link_routing_back_to")}{" "}
|
||||
{backUrlDecodedPath
|
||||
? t("LoginPage.link_routing_previuos_page")
|
||||
: t("LoginPage.link_routing_main_page")}
|
||||
</LinkRouting>
|
||||
</Stack>
|
||||
</FullPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginComponent;
|
||||
128
src/core/components/AvatarUpload.jsx
Normal file
128
src/core/components/AvatarUpload.jsx
Normal file
@@ -0,0 +1,128 @@
|
||||
import {Avatar, Box, TextField} from "@mui/material";
|
||||
import {useState} from "react";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
|
||||
const AvatarUpload = ({user, setFieldValue, valueAvatar, changeFlag}) => {
|
||||
const [selectedImage, setSelectedImage] = useState(user.expert_avatar);
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
const handleImageChange = (event) => {
|
||||
const newImage = event.target?.files?.[0];
|
||||
if (newImage) {
|
||||
setSelectedImage(URL.createObjectURL(newImage));
|
||||
setFieldValue(valueAvatar, newImage);
|
||||
setFieldValue(changeFlag, true);
|
||||
} else {
|
||||
setSelectedImage("");
|
||||
setFieldValue(valueAvatar, null);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteImage = () => {
|
||||
setSelectedImage("");
|
||||
setFieldValue(valueAvatar, null);
|
||||
setFieldValue(changeFlag, true);
|
||||
};
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
setIsHovered(true);
|
||||
};
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
setIsHovered(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "inline-block",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
component="label"
|
||||
htmlFor="avatar-upload"
|
||||
sx={{
|
||||
display: "inline-block",
|
||||
width: "fit-content",
|
||||
height: "fit-content",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
component="div"
|
||||
className={`avatar-container ${isHovered ? "hovered" : ""}`}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
sx={{
|
||||
position: "relative",
|
||||
width: 150,
|
||||
height: 150,
|
||||
borderRadius: "50%",
|
||||
overflow: "hidden",
|
||||
transition: "transform 0.3s ease-in-out",
|
||||
}}
|
||||
>
|
||||
<Avatar
|
||||
alt="User Avatar"
|
||||
src={selectedImage}
|
||||
sx={{
|
||||
width: 150,
|
||||
height: 150,
|
||||
cursor: "pointer",
|
||||
position: "relative",
|
||||
}}
|
||||
/>
|
||||
{isHovered && (
|
||||
<Box
|
||||
component="div"
|
||||
className="avatar-overlay"
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
backgroundColor: "rgba(0, 0, 0, 0.6)",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
transition: "transform 0.3s ease-in-out",
|
||||
transform: `scale(${isHovered ? 1 : 0})`,
|
||||
}}
|
||||
>
|
||||
{selectedImage ? (
|
||||
<DeleteIcon
|
||||
sx={{
|
||||
color: "#fff",
|
||||
width: 35,
|
||||
height: 35,
|
||||
}}
|
||||
onClick={handleDeleteImage}
|
||||
/>
|
||||
) : (
|
||||
<AddIcon
|
||||
sx={{
|
||||
color: "#fff",
|
||||
width: 35,
|
||||
height: 35,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<TextField
|
||||
id="avatar-upload"
|
||||
type="file"
|
||||
accept="image/*"
|
||||
sx={{display: "none"}}
|
||||
onChange={handleImageChange}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default AvatarUpload;
|
||||
176
src/core/components/DataTable.jsx
Normal file
176
src/core/components/DataTable.jsx
Normal file
@@ -0,0 +1,176 @@
|
||||
import {useTranslations} from "next-intl";
|
||||
import useLanguage from "@/lib/app/hooks/useLanguage";
|
||||
import {useEffect, useMemo, useState} from "react";
|
||||
import moment from "moment-jalaali";
|
||||
import useSWR from "swr";
|
||||
import {Typography} from "@mui/material";
|
||||
import MaterialReactTable from "material-react-table";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
|
||||
function DataTable(props) {
|
||||
const requestServer = useRequest({auth: true})
|
||||
const fetcher = (...args) => {
|
||||
return requestServer(args, 'get', {
|
||||
pending: false,
|
||||
success: {notification: {show: false}}
|
||||
}).then((response) => {
|
||||
setRowCount(response.data.meta.totalRowCount);
|
||||
return response.data.data;
|
||||
}).catch(() => {
|
||||
})
|
||||
};
|
||||
const t = useTranslations();
|
||||
const {languageApp, languageList} = useLanguage();
|
||||
const [columnFilters, setColumnFilters] = useState([]);
|
||||
const [sorting, setSorting] = useState([]);
|
||||
const [pagination, setPagination] = useState({pageIndex: 0, pageSize: 10});
|
||||
const [rowCount, setRowCount] = useState(0);
|
||||
const [columnFilterFns, setColumnFilterFns] = useState(() => {
|
||||
let output = {};
|
||||
const list = props.columns.map((item) =>
|
||||
item.enableColumnFilter ? {[item.id]: item.filterFn} : {[item.id]: ""}
|
||||
);
|
||||
for (var key in list) {
|
||||
var nestedObj = list[key];
|
||||
for (var nestedKey in nestedObj) {
|
||||
output[nestedKey] = nestedObj[nestedKey];
|
||||
}
|
||||
}
|
||||
return output;
|
||||
});
|
||||
|
||||
const [updateTime, setupdateTime] = useState(
|
||||
moment().format("HH:mm | jYYYY/jM/jD")
|
||||
);
|
||||
|
||||
const tableLocalization = useMemo(
|
||||
() =>
|
||||
languageList.find((item) => item.key == languageApp).tableLocalization,
|
||||
[languageApp, languageList]
|
||||
);
|
||||
|
||||
const fetchUrl = useMemo(() => {
|
||||
const url = new URL(props.tableUrl);
|
||||
url.searchParams.set(
|
||||
"start",
|
||||
`${pagination.pageIndex * pagination.pageSize}`
|
||||
);
|
||||
const filters = columnFilters.map((filter) => {
|
||||
let datatype;
|
||||
for (const i in props.columns) {
|
||||
if (props.columns[i].id == filter.id) {
|
||||
datatype = props.columns[i].datatype;
|
||||
}
|
||||
}
|
||||
return {
|
||||
...filter,
|
||||
fn: columnFilterFns[filter.id],
|
||||
datatype: datatype,
|
||||
};
|
||||
});
|
||||
url.searchParams.set("size", pagination.pageSize);
|
||||
url.searchParams.set("filters", JSON.stringify(filters ?? []));
|
||||
url.searchParams.set("sorting", JSON.stringify(sorting ?? []));
|
||||
return url;
|
||||
}, [
|
||||
props.tableUrl,
|
||||
columnFilters,
|
||||
columnFilterFns,
|
||||
pagination,
|
||||
sorting,
|
||||
props.columns,
|
||||
]);
|
||||
|
||||
const {data, isValidating, mutate} = useSWR(fetchUrl, fetcher, {
|
||||
revalidateIfStale: false,
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: false
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setupdateTime(moment().format("HH:mm | jYYYY/jM/jD"));
|
||||
}, [isValidating, languageApp]);
|
||||
|
||||
return (
|
||||
<MaterialReactTable
|
||||
localization={tableLocalization}
|
||||
data={data ?? []}
|
||||
manualFiltering
|
||||
manualPagination
|
||||
manualSorting
|
||||
enableRowSelection={props.selectableRow} /* send condition */
|
||||
enablePinning={props.enablePinning} /* send condition */
|
||||
enableColumnFilters={props.enableColumnFilters} /* send condition */
|
||||
enableDensityToggle={props.enableDensityToggle}
|
||||
enableHiding={props.enableHiding} /* send condition */
|
||||
enableFullScreenToggle={props.enableFullScreenToggle} /* send condition */
|
||||
enableColumnResizing={props.enableColumnResizing}
|
||||
muiTableHeadCellProps={{
|
||||
sx: {
|
||||
color: "primary.main",
|
||||
borderLeft: "1px solid #e1e1e1",
|
||||
"&:first-of-type": {
|
||||
borderLeft: "unset"
|
||||
},
|
||||
"& .Mui-TableHeadCell-Content": {justifyContent: "space-between"},
|
||||
},
|
||||
}}
|
||||
muiTableBodyCellProps={{
|
||||
sx: {
|
||||
borderLeft: "1px solid #e1e1e1",
|
||||
"&:first-of-type": {
|
||||
borderLeft: "unset"
|
||||
}
|
||||
},
|
||||
}}
|
||||
enableColumnFilterModes
|
||||
muiTablePaperProps={{elevation: 0}}
|
||||
rowCount={rowCount}
|
||||
onColumnFilterFnsChange={setColumnFilterFns}
|
||||
onColumnFiltersChange={setColumnFilters}
|
||||
onPaginationChange={setPagination}
|
||||
onSortingChange={setSorting}
|
||||
positionToolbarAlertBanner="bottom"
|
||||
renderTopToolbarCustomActions={({table}) => (
|
||||
<>
|
||||
{props.enableCustomToolbar /* send condition */
|
||||
? props.CustomToolbar /* send component */
|
||||
: ""}
|
||||
</>
|
||||
)}
|
||||
renderBottomToolbarCustomActions={({table}) => (
|
||||
<>
|
||||
{props.enableLastUpdate /* send condition */ ? (
|
||||
<Typography
|
||||
sx={{
|
||||
color: "primary.main",
|
||||
alignSelf: "center",
|
||||
whiteSpace: "nowrap",
|
||||
maxWidth: {xs: 100, sm: "100%"},
|
||||
overflowX: "scroll",
|
||||
}}
|
||||
variant="caption"
|
||||
>
|
||||
{t("last_updated_at")}: {updateTime}
|
||||
</Typography>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
state={{
|
||||
isLoading: isValidating,
|
||||
columnFilters,
|
||||
columnFilterFns,
|
||||
pagination,
|
||||
sorting,
|
||||
}}
|
||||
positionActionsColumn={"last"}
|
||||
enableRowActions={props.enableRowActions}
|
||||
renderRowActions={({row}) => <props.TableRowAction fetchUrl={fetchUrl} mutate={mutate} row={row}/>}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default DataTable;
|
||||
58
src/core/components/GlobalHead.jsx
Normal file
58
src/core/components/GlobalHead.jsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import Head from "next/head";
|
||||
|
||||
const GlobalHead = () => {
|
||||
return (
|
||||
<Head>
|
||||
<meta
|
||||
name="application-name"
|
||||
content={process.env.NEXT_PUBLIC_API_NAME}
|
||||
/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||||
<meta
|
||||
name="apple-mobile-web-app-status-bar-style"
|
||||
content="black-translucent"
|
||||
/>
|
||||
<meta
|
||||
name="apple-mobile-web-app-title"
|
||||
content={process.env.NEXT_PUBLIC_API_NAME}
|
||||
/>
|
||||
<meta name="description" content="Marhaba does it for you"/>
|
||||
<meta name="format-detection" content="telephone=no"/>
|
||||
<meta name="format-detection" content="date=no"/>
|
||||
<meta name="format-detection" content="address=no"/>
|
||||
<meta name="format-detection" content="email=no"/>
|
||||
<meta name="mobile-web-app-capable" content="yes"/>
|
||||
<link rel="apple-touch-icon" href="/icons/maskable_icon_x512.png"/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="120x120"
|
||||
href="/icons/maskable_icon_x128.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/icons/maskable_icon_x192.png"
|
||||
/>
|
||||
<meta name="google" content="notranslate"/>
|
||||
<meta name="robots" content="noindex"/>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/svg"
|
||||
sizes="32x32"
|
||||
href="/icons/favicon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/svg"
|
||||
sizes="16x16"
|
||||
href="/icons/favicon.png"
|
||||
/>
|
||||
</Head>
|
||||
)
|
||||
}
|
||||
|
||||
export default GlobalHead
|
||||
22
src/core/components/ImageConvertor.jsx
Normal file
22
src/core/components/ImageConvertor.jsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import ImageResize from "image-resize";
|
||||
|
||||
const ImageResizer = async (image) => {
|
||||
const imageResize = new ImageResize({
|
||||
quality: 1,
|
||||
format: "jpg",
|
||||
outputType: "base64",
|
||||
width: 400,
|
||||
});
|
||||
|
||||
const get = await imageResize.get(image);
|
||||
const resize = await imageResize.resize(get).then();
|
||||
const output = await imageResize.output(resize).then();
|
||||
|
||||
const avatar = await (await import("image-to-file-converter"))
|
||||
.base64ToFile(output)
|
||||
.then();
|
||||
|
||||
return avatar;
|
||||
};
|
||||
|
||||
export default ImageResizer;
|
||||
116
src/core/components/LinkRouting.jsx
Normal file
116
src/core/components/LinkRouting.jsx
Normal file
@@ -0,0 +1,116 @@
|
||||
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;
|
||||
42
src/core/components/LoadingHardPage.jsx
Normal file
42
src/core/components/LoadingHardPage.jsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import {Backdrop, Box, 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}
|
||||
>
|
||||
<LoadingImage
|
||||
width={100}
|
||||
height={100}
|
||||
>
|
||||
<SvgLoading width={100}
|
||||
height={100}/>
|
||||
</LoadingImage>
|
||||
</Backdrop>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoadingHardPage;
|
||||
18
src/core/components/Messages.jsx
Normal file
18
src/core/components/Messages.jsx
Normal file
@@ -0,0 +1,18 @@
|
||||
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;
|
||||
61
src/core/components/MuiDatePicker.jsx
Normal file
61
src/core/components/MuiDatePicker.jsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import {LocalizationProvider, MobileDateTimePicker} from "@mui/x-date-pickers";
|
||||
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
||||
import moment from "jalali-moment";
|
||||
import {faIR} from "@mui/x-date-pickers/locales";
|
||||
import {Box, IconButton} from "@mui/material";
|
||||
import ClearIcon from "@mui/icons-material/Clear";
|
||||
import {useTranslations} from "next-intl";
|
||||
|
||||
export default function MuiDatePicker({column}) {
|
||||
const t = useTranslations();
|
||||
const filterFnValue = column.columnDef._filterFn;
|
||||
|
||||
return (
|
||||
<Box sx={{display: "flex", alignItems: "start"}}>
|
||||
<LocalizationProvider
|
||||
dateAdapter={AdapterDateFnsJalali}
|
||||
localeText={
|
||||
faIR.components.MuiLocalizationProvider.defaultProps
|
||||
.localeText
|
||||
}
|
||||
>
|
||||
<MobileDateTimePicker
|
||||
ampm={false}
|
||||
onChange={(newValue) => {
|
||||
const date = new Date(newValue);
|
||||
const formattedDate = moment(date)
|
||||
.locale("en")
|
||||
.format("YYYY-MM-DD HH:mm");
|
||||
column.setFilterValue(formattedDate);
|
||||
}}
|
||||
slotProps={{
|
||||
textField: {
|
||||
placeholder: "تاریخ خود را وارد کنید",
|
||||
helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
|
||||
sx: {minWidth: "120px"},
|
||||
variant: "standard",
|
||||
},
|
||||
}}
|
||||
value={
|
||||
column.getFilterValue()
|
||||
? new Date(column.getFilterValue())
|
||||
: null
|
||||
}
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => {
|
||||
column.setFilterValue(null);
|
||||
}}
|
||||
sx={{
|
||||
color: column.getFilterValue()
|
||||
? "rgba(0, 0, 0, 0.54)"
|
||||
: "#bfbfbf",
|
||||
}}
|
||||
>
|
||||
<ClearIcon/>
|
||||
</IconButton>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
34
src/core/components/NetworkComponent.jsx
Normal file
34
src/core/components/NetworkComponent.jsx
Normal file
@@ -0,0 +1,34 @@
|
||||
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
|
||||
8
src/core/components/NoSsrHandler.jsx
Normal file
8
src/core/components/NoSsrHandler.jsx
Normal file
@@ -0,0 +1,8 @@
|
||||
import {NoSsr} from "@mui/material";
|
||||
|
||||
const NoSsrHandler = ({isBot, children}) => {
|
||||
if (isBot) return children;
|
||||
return <NoSsr>{children}</NoSsr>;
|
||||
};
|
||||
|
||||
export default NoSsrHandler;
|
||||
33
src/core/components/PasswordField.jsx
Normal file
33
src/core/components/PasswordField.jsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import {useState} from "react";
|
||||
import {IconButton, InputAdornment, TextField} from "@mui/material";
|
||||
import {Visibility, VisibilityOff} from "@mui/icons-material";
|
||||
import {Field} from "formik";
|
||||
|
||||
const PasswordField = (props) => {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
|
||||
const handleClickShowPassword = () => {
|
||||
setShowPassword(!showPassword);
|
||||
};
|
||||
|
||||
return (
|
||||
<Field
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
as={TextField}
|
||||
{...props}
|
||||
type={showPassword ? "text" : "password"}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton onClick={handleClickShowPassword}>
|
||||
{showPassword ? <Visibility/> : <VisibilityOff/>}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default PasswordField;
|
||||
23
src/core/components/PriceField.jsx
Normal file
23
src/core/components/PriceField.jsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import {InputAdornment, TextField, Typography} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
|
||||
const PriceField = (props) => {
|
||||
const t = useTranslations();
|
||||
return (
|
||||
<TextField
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<Typography
|
||||
sx={{margin: 1}}
|
||||
component="span">{((props.value) / 10).toLocaleString()}</Typography>
|
||||
<Typography component="span"
|
||||
variant="caption">{t("ConfirmDialog.toman")}</Typography>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
export default PriceField
|
||||
6
src/core/components/StyledForm.jsx
Normal file
6
src/core/components/StyledForm.jsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import {styled} from "@mui/material";
|
||||
import {Form} from "formik";
|
||||
|
||||
const StyledForm = styled(Form)``;
|
||||
|
||||
export default StyledForm;
|
||||
6
src/core/components/StyledImage.jsx
Normal file
6
src/core/components/StyledImage.jsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import {styled} from "@mui/material";
|
||||
import Image from "next/image";
|
||||
|
||||
const StyledImage = styled(Image)``;
|
||||
|
||||
export default StyledImage;
|
||||
15
src/core/components/TitlePage.jsx
Normal file
15
src/core/components/TitlePage.jsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import {useTranslations} from "next-intl";
|
||||
import Head from "next/head";
|
||||
|
||||
const TitlePage = ({text}) => {
|
||||
const t = useTranslations();
|
||||
return (
|
||||
<Head>
|
||||
<title>
|
||||
{text ? `${t("app_short_name")} | ${t(text)}` : t("app_short_name")}
|
||||
</title>
|
||||
</Head>
|
||||
);
|
||||
};
|
||||
|
||||
export default TitlePage;
|
||||
175
src/core/components/UploadSystem.jsx
Normal file
175
src/core/components/UploadSystem.jsx
Normal file
@@ -0,0 +1,175 @@
|
||||
import {Box, Button, Paper, Typography} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import DeleteForeverIcon from "@mui/icons-material/DeleteForever";
|
||||
import {useRef} from "react";
|
||||
|
||||
const UploadSystem = ({
|
||||
selectedImage,
|
||||
setselectedImage,
|
||||
handleUploadChange,
|
||||
fieldname,
|
||||
setFieldValue,
|
||||
imageAlt,
|
||||
imageSize,
|
||||
fileType,
|
||||
fileName,
|
||||
setShowAddIcon,
|
||||
showAddIcon,
|
||||
}) => {
|
||||
const t = useTranslations();
|
||||
const fileInputRef = useRef(null);
|
||||
|
||||
const handleClick = () => {
|
||||
fileInputRef.current.click();
|
||||
};
|
||||
|
||||
const handleDeleteImage = () => {
|
||||
setselectedImage(null);
|
||||
setFieldValue(fieldname, null);
|
||||
setShowAddIcon(true);
|
||||
if (fileInputRef.current) {
|
||||
fileInputRef.current.value = "";
|
||||
}
|
||||
};
|
||||
|
||||
const isDocumentFormat = (fileType) => {
|
||||
const documentFormats = [
|
||||
"application/pdf",
|
||||
"application/msword",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
"application/vnd.ms-excel",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
];
|
||||
return documentFormats.includes(fileType);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{width: "100%", my: 1}}>
|
||||
{showAddIcon ? (
|
||||
// Show the add icon and "Upload File" text when no image is selected
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
border: "1px solid #b3b3b3",
|
||||
borderRadius: "10px",
|
||||
cursor: "pointer",
|
||||
padding: "5px",
|
||||
|
||||
height: imageSize[1],
|
||||
}}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<AddIcon sx={{fontSize: "2rem", color: "#a19d9d"}}/>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
fontSize: "1rem",
|
||||
color: "#a19d9d",
|
||||
mt: 1,
|
||||
}}
|
||||
textAlign="center"
|
||||
>
|
||||
{t("UploadSystem.upload_file")}
|
||||
</Typography>
|
||||
</Box>
|
||||
</>
|
||||
) : (
|
||||
// Show the uploaded content along with the delete button when an image or document is selected
|
||||
<>
|
||||
{fileType && fileType.startsWith("image/") ? (
|
||||
<Box
|
||||
width="100%"
|
||||
height={imageSize[1]}
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
cursor: "pointer",
|
||||
objectFit: "contain",
|
||||
border: "1px solid #b3b3b3",
|
||||
borderTopRightRadius: "10px",
|
||||
borderTopLeftRadius: "10px",
|
||||
borderBottom: "unset",
|
||||
padding: "5px",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<Paper
|
||||
elevation={0}
|
||||
sx={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
backgroundSize: "contain",
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundPosition: "center",
|
||||
backgroundImage: `url(${selectedImage})`,
|
||||
}}
|
||||
></Paper>
|
||||
</Box>
|
||||
) : (
|
||||
fileType &&
|
||||
isDocumentFormat(fileType) && (
|
||||
<Box
|
||||
sx={{
|
||||
height: imageSize[1],
|
||||
display: "flex",
|
||||
border: "1px solid #b3b3b3",
|
||||
borderTopRightRadius: "10px",
|
||||
borderTopLeftRadius: "10px",
|
||||
borderBottom: "unset",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<Typography
|
||||
margin={2}
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
fontSize: "1rem",
|
||||
color: "#a19d9d",
|
||||
}}
|
||||
textAlign="center"
|
||||
>
|
||||
{fileName}
|
||||
</Typography>
|
||||
</Box>
|
||||
)
|
||||
)}
|
||||
<Button
|
||||
sx={{
|
||||
width: "100%",
|
||||
}}
|
||||
color="error"
|
||||
endIcon={<DeleteForeverIcon/>}
|
||||
variant="contained"
|
||||
onClick={handleDeleteImage}
|
||||
>
|
||||
{t("UploadSystem.delete")}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*, .pdf, .doc, .docx, .xls, .xlsx"
|
||||
style={{display: "none"}}
|
||||
onChange={handleUploadChange}
|
||||
ref={fileInputRef}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default UploadSystem;
|
||||
39
src/core/components/notifications/ErrorNotification.jsx
Normal file
39
src/core/components/notifications/ErrorNotification.jsx
Normal file
@@ -0,0 +1,39 @@
|
||||
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;
|
||||
12
src/core/components/notifications/PendingNotification.jsx
Normal file
12
src/core/components/notifications/PendingNotification.jsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const PendingNotification = (t) => {
|
||||
toast(t("notifications.pending"), {
|
||||
autoClose: false,
|
||||
closeButton: false,
|
||||
closeOnClick: false,
|
||||
draggable: false,
|
||||
});
|
||||
};
|
||||
|
||||
export default PendingNotification;
|
||||
42
src/core/components/notifications/SuccessNotification.jsx
Normal file
42
src/core/components/notifications/SuccessNotification.jsx
Normal file
@@ -0,0 +1,42 @@
|
||||
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;
|
||||
38
src/core/components/notifications/UploadFileNotification.jsx
Normal file
38
src/core/components/notifications/UploadFileNotification.jsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import DangerousIcon from "@mui/icons-material/Dangerous";
|
||||
import {Box, Typography} from "@mui/material";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const UploadFileNotification = (t) => {
|
||||
toast(
|
||||
({closeToast}) => (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "start",
|
||||
justifyContent: "start",
|
||||
}}
|
||||
>
|
||||
<Box sx={{display: "flex", alignItems: "center"}}>
|
||||
<DangerousIcon color="error" sx={{mr: 1.6}}/>
|
||||
<Box sx={{display: "flex", flexDirection: "column"}}>
|
||||
<Typography color="error" variant="button">
|
||||
{t("UploadSystem.uploadfile_error")}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
),
|
||||
{
|
||||
autoClose: 3000,
|
||||
hideProgressBar: true,
|
||||
pauseOnHover: true,
|
||||
closeOnClick: false,
|
||||
draggable: true,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default UploadFileNotification;
|
||||
40
src/core/components/notifications/WarningNotification.jsx
Normal file
40
src/core/components/notifications/WarningNotification.jsx
Normal file
@@ -0,0 +1,40 @@
|
||||
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;
|
||||
54
src/core/components/notifications/index.jsx
Normal file
54
src/core/components/notifications/index.jsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import {toast} from "react-toastify";
|
||||
import ErrorNotification from "./ErrorNotification";
|
||||
import WarningNotification from "./WarningNotification";
|
||||
import SuccessNotification from "./SuccessNotification";
|
||||
|
||||
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("notifications.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
|
||||
*/
|
||||
131
src/core/components/svgs/Svg403.jsx
Normal file
131
src/core/components/svgs/Svg403.jsx
Normal file
@@ -0,0 +1,131 @@
|
||||
import {useTheme} from "@mui/material";
|
||||
|
||||
const Svg403 = ({width, height}) => {
|
||||
const theme = useTheme()
|
||||
const fillColor = theme.palette.primary.main
|
||||
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width={width} height={height}
|
||||
viewBox="0 0 742.41705 712.57302">
|
||||
<path id="aa38b2e7-2ea9-4025-adcf-83f87c0cfc4a-338" data-name="Path 968"
|
||||
d="M853.60644,262.60547h-3.9v-106.977a61.915,61.915,0,0,0-61.915-61.915h-226.65a61.915,61.915,0,0,0-61.916,61.914v586.884a61.915,61.915,0,0,0,61.915,61.915h226.648a61.915,61.915,0,0,0,61.915-61.915v-403.758h3.9Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#3f3d56"/>
|
||||
<path id="f27259c2-0089-4137-bfd8-cb22dff914f1-339" data-name="Path 969"
|
||||
d="M837.00647,151.48149v595.175a46.959,46.959,0,0,1-46.942,46.952h-231.3a46.966,46.966,0,0,1-46.973-46.952v-595.175a46.965,46.965,0,0,1,46.971-46.951h28.058a22.329,22.329,0,0,0,20.656,30.74h131.868a22.329,22.329,0,0,0,20.656-30.74h30.055a46.959,46.959,0,0,1,46.951,46.942Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#fff"/>
|
||||
<circle id="fc31cc31-f989-45cc-bd1e-521a0ee1871b" data-name="Ellipse 18" cx="445.56497" cy="200.129"
|
||||
r="96.565" fill="#084070"/>
|
||||
<path id="a573942c-3bf3-4c43-b474-689725a927f7-340" data-name="Path 39"
|
||||
d="M779.67245,494.30947h-205.537a3.81,3.81,0,0,1-3.806-3.806V439.51949a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985a3.811,3.811,0,0,1-3.806,3.806Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="fb5feb1e-1fe2-48fa-806d-0a2b51d12b49-341" data-name="Path 40"
|
||||
d="M637.69945,454.07448a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00221-.11713-.0019h-125.692Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="bcb9932f-0864-4b7e-b0ed-f7254bb9b8bf-342" data-name="Path 41"
|
||||
d="M637.69945,470.05846a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00219-.11713-.00189h-125.692Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="f88e2a8b-becc-4da9-bd36-af011daaaaf2-343" data-name="Path 42"
|
||||
d="M779.67245,579.28947h-205.537a3.81,3.81,0,0,1-3.806-3.806V524.49949a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985A3.811,3.811,0,0,1,779.67245,579.28947Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="e192d34f-2ccc-4f79-b47a-46430e4d87f6-344" data-name="Path 43"
|
||||
d="M637.69945,539.33047a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.087-5.328h-125.692Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="b230677c-48cc-4ee6-87d6-a753204ffe47-345" data-name="Path 44"
|
||||
d="M637.69945,555.3185a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.087-5.328h-125.692Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="b88a2a79-0ae3-4fd9-9894-02e0db9a2271-346" data-name="Path 39-2"
|
||||
d="M779.67245,664.54748h-205.537a3.81,3.81,0,0,1-3.806-3.806V609.7575a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985a3.811,3.811,0,0,1-3.806,3.806Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="aa2394a9-8b56-4a12-a2cd-a583e6ea12eb-347" data-name="Path 40-2"
|
||||
d="M637.69945,624.59148a2.66449,2.66449,0,1,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00219-.11713-.00189h-125.692Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="bc352cb2-8959-4b51-bd18-df6817a9a47e-348" data-name="Path 41-2"
|
||||
d="M637.69945,640.57846a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.0022-.11713-.00189h-125.692Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="b30ee82f-5b3a-4aa4-9db7-ead828191937-349" data-name="Path 970"
|
||||
d="M969.27042,806.28651h-738.541c-1.071,0-1.938-.468-1.938-1.045s.868-1.045,1.938-1.045H969.27054c1.06994,0,1.938.468,1.938,1.045S970.34146,806.28651,969.27042,806.28651Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<g id="f24cf2fd-107c-4150-a0f1-6f6b12d88bf3" data-name="Group 58">
|
||||
<path id="a2b576eb-bb95-4480-aa60-cd8aa023fe61-350" data-name="Path 438"
|
||||
d="M937.99248,765.52151a19.4741,19.4741,0,0,1-18.806-3.313c-6.587-5.528-8.652-14.636-10.332-23.07l-4.97-24.945,10.405,7.165c7.483,5.152,15.134,10.47,20.316,17.933s7.443,17.651,3.28,25.726"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="fe1c5433-44e0-47a6-8430-329cbd7c4dea-351" data-name="Path 439"
|
||||
d="M936.38547,797.45852c1.31-9.542,2.657-19.206,1.738-28.849-.816-8.565-3.429-16.93-8.749-23.789a39.57365,39.57365,0,0,0-10.153-9.2c-1.015-.641-1.95.968-.939,1.606a37.62192,37.62192,0,0,1,14.881,17.956c3.24,8.241,3.76,17.224,3.2,25.977-.338,5.294-1.053,10.553-1.774,15.805a.964.964,0,0,0,.65,1.144.936.936,0,0,0,1.144-.65Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#f2f2f2"/>
|
||||
<path id="f0043cfc-c9b9-4981-8afd-8c13c1b6f93f-352" data-name="Path 442"
|
||||
d="M926.95847,782.14846a14.336,14.336,0,0,1-12.491,6.447c-6.323-.3-11.595-4.713-16.34-8.9l-14.035-12.395,9.289-.444c6.68-.32,13.533-.618,19.9,1.442s12.231,7.018,13.394,13.6"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="b883c521-5e9e-4a38-b47c-4f8b0cd8c6cd-353" data-name="Path 443"
|
||||
d="M940.08649,802.94344c-6.3-11.156-13.618-23.555-26.685-27.518a29.77874,29.77874,0,0,0-11.224-1.159c-1.192.1-.894,1.94.3,1.837a27.6648,27.6648,0,0,1,17.912,4.739c5.051,3.438,8.983,8.217,12.311,13.286,2.039,3.1,3.865,6.341,5.691,9.573C938.97147,804.73348,940.67746,803.98843,940.08649,802.94344Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#f2f2f2"/>
|
||||
</g>
|
||||
<g id="b241f6a5-c54d-499c-8ecd-4235a19d143f" data-name="Group 59">
|
||||
<circle id="bfaee8a8-2192-45bf-83cb-a2f223d41a02" data-name="Ellipse 5" cx="370.98597" cy="370.985"
|
||||
r="15.986" fill="#084070"/>
|
||||
<path id="ae47602b-fb54-4e88-955d-49b260f35f7f-354" data-name="Path 40-3"
|
||||
d="M592.12445,461.71247c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.94291,5.94291,0,0,0-.328-2.708h-15.73Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
</g>
|
||||
<g id="a1e1e52b-75f8-4aa9-8279-faf451e6aae1" data-name="Group 60">
|
||||
<circle id="fa3a3ce2-c232-40ee-81b4-25b83d5b931c" data-name="Ellipse 5-2" cx="370.98597" cy="456.278"
|
||||
r="15.986" fill="#084070"/>
|
||||
<path id="aaaffa69-7c16-47ec-b12d-87139789d2df-355" data-name="Path 40-4"
|
||||
d="M592.12445,547.00547c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.94291,5.94291,0,0,0-.328-2.708h-15.73Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
</g>
|
||||
<g id="fd2b54c2-3dec-4fb6-9f72-e6c667a136b8" data-name="Group 61">
|
||||
<circle id="abc19202-5605-459b-9c25-b430addb8839" data-name="Ellipse 5-3" cx="370.98597" cy="541.53599"
|
||||
r="15.986" fill="#084070"/>
|
||||
<path id="f69fbb38-8754-494b-94fa-96f6df4fd0e7-356" data-name="Path 40-5"
|
||||
d="M592.12445,632.26346c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.943,5.943,0,0,0-.328-2.708h-15.73Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
</g>
|
||||
<rect x="670.35645" y="260.34249" width="8" height="67"
|
||||
transform="translate(-239.05506 469.193) rotate(-45)" fill="#fff"/>
|
||||
<rect x="670.35645" y="260.34249" width="8" height="67"
|
||||
transform="translate(176.50097 -484.49103) rotate(45)" fill="#fff"/>
|
||||
<path
|
||||
d="M319.05083,549.84841a10.05579,10.05579,0,0,0,5.38778-14.44741l23.56521-26.86373-18.39547-2.53779-19.5577,25.89933a10.11027,10.11027,0,0,0,9.00018,17.9496Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#9f616a"/>
|
||||
<polygon points="118.679 694.215 102.244 694.214 94.425 630.82 118.682 630.821 118.679 694.215"
|
||||
fill="#9f616a"/>
|
||||
<path
|
||||
d="M351.66209,803.8602l-52.99477-.002v-.6703a20.62815,20.62815,0,0,1,20.627-20.62671h.00131l32.3674.00131Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#2f2e41"/>
|
||||
<polygon points="204.713 680.461 189.017 685.334 162.751 627.11 185.917 619.918 204.713 680.461"
|
||||
fill="#9f616a"/>
|
||||
<path
|
||||
d="M442.23214,788.14677,391.62055,803.8602l-.19877-.64014a20.62813,20.62813,0,0,1,13.58247-25.81574l.00126-.00039,30.91186-9.59713Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#2f2e41"/>
|
||||
<path id="ae9bdfa9-f7e0-4b2f-8168-ca8868d01318-357" data-name="Path 973"
|
||||
d="M334.88445,495.65649l-24.34114,27.8773,19.05613,1.71471Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="b88343d2-9c47-4183-8a8a-427a73d8d9be-358" data-name="Path 975"
|
||||
d="M325.37344,531.58948s-8.455,4.227-9.512,23.251,3.171,68.7,3.171,68.7-4.227,22.194,0,42.274-4.227,93,1.057,93,32.762,3.171,33.819,0,2.114-50.729,2.114-50.729,8.455-24.308,0-39.1c0,0,29.52086,51.54832,48.615,90.889,4.17891,8.61,35.933-1.057,30.649-10.569s-17.966-52.843-17.966-52.843-9.512-31.706-26.421-45.445l8.455-67.639s17.967-45.445,7.4-51.786S325.37344,531.58948,325.37344,531.58948Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#2f2e41"/>
|
||||
<circle id="fdc24b21-a9e1-47f2-b2e4-7458730b7c21" data-name="Ellipse 182" cx="128.28696" cy="238.129"
|
||||
r="27.478" fill="#a0616a"/>
|
||||
<path id="ac268c91-41f4-49c7-bce6-773e5eb69fa2-359" data-name="Path 976"
|
||||
d="M387.72745,361.43447l-34.16,20.08s-13.08,7.366-17.966,20.08c-5.208,13.55-2.181,32.628,0,36.99,4.227,8.455-1.773,29.592-1.773,29.592l-5.284,48.615s-19.023,17.966-4.227,20.08,41.217-1.057,57.07,0,33.819,3.171,28.535-7.4-11.625-17.967-5.284-39.1c4.962-16.54,4.747-78.383,4.419-104.5a21.025,21.025,0,0,0-10.211-17.767Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e5e5e5"/>
|
||||
<path id="aebed2c8-94ca-417e-8b11-27e17cbf3024-360" data-name="Path 980"
|
||||
d="M372.40744,394.72649l3.17,64.468-30.726,62.223-5.211-1.983,31.706-58.127Z"
|
||||
transform="translate(-228.79147 -93.71349)" opacity="0.1" style="isolation:isolate"/>
|
||||
<path id="e13ea0c4-bc86-4025-9528-1665a42d3372-361" data-name="Path 982"
|
||||
d="M407.27945,472.93247v-7.4l-35.929,59.186Z" transform="translate(-228.79147 -93.71349)"
|
||||
opacity="0.1" style="isolation:isolate"/>
|
||||
<path id="eb3190ba-6b3f-4b2b-91d1-1543e580b413-362" data-name="Path 983"
|
||||
d="M337.57645,306.38749l-4.539-1.816s9.5-10.457,22.713-9.548l-3.717-4.092s9.085-3.637,17.345,5.91c4.342,5.019,9.365,10.919,12.5,17.564h4.865l-2.03,4.471,7.106,4.471-7.294-.8a24.73921,24.73921,0,0,1-.69,11.579l.2,3.534s-8.459-13.089-8.459-14.905v4.547s-4.543-4.092-4.543-6.82l-2.478,3.183-1.239-5-15.28,5,2.476-4.094-9.5,1.364,3.717-5s-10.737,5.91-11.15,10.912-5.781,11.366-5.781,11.366l-2.478-4.547S325.60443,313.20747,337.57645,306.38749Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#2f2e41"/>
|
||||
<path
|
||||
d="M355.35408,552.83885a10.05581,10.05581,0,0,0,2.73778-15.17434l18.42263-30.62-18.55382.76775-14.64995,28.95959a10.11028,10.11028,0,0,0,12.04336,16.067Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#9f616a"/>
|
||||
<path id="a62f6567-f472-4931-86f9-ff652851a370-363" data-name="Path 981"
|
||||
d="M397.24046,375.17548l7.926-1.585s23.779,17.438,16.381,52.314-40.16,87.719-40.16,87.719-7.4,9.512-9.512,11.625-6.341,0-4.227,3.171-3.171,5.284-3.171,5.284-23.251,0-21.137-8.455,38.047-68.7,38.047-68.7l-5.284-56.013S371.87446,373.0615,397.24046,375.17548Z"
|
||||
transform="translate(-228.79147 -93.71349)" fill="#e5e5e5"/>
|
||||
</svg>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default Svg403
|
||||
101
src/core/components/svgs/Svg404.jsx
Normal file
101
src/core/components/svgs/Svg404.jsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import {useTheme} from "@mui/material";
|
||||
|
||||
const Svg404 = ({width, height}) => {
|
||||
const theme = useTheme()
|
||||
const fillColor = theme.palette.primary.main
|
||||
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width={width} height={height}
|
||||
viewBox="0 0 860.13137 571.14799">
|
||||
<path
|
||||
d="M605.66974,324.95306c-7.66934-12.68446-16.7572-26.22768-30.98954-30.36953-16.482-4.7965-33.4132,4.73193-47.77473,14.13453a1392.15692,1392.15692,0,0,0-123.89338,91.28311l.04331.49238q46.22556-3.1878,92.451-6.37554c22.26532-1.53546,45.29557-3.2827,64.97195-13.8156,7.46652-3.99683,14.74475-9.33579,23.20555-9.70782,10.51175-.46217,19.67733,6.87923,26.8802,14.54931,42.60731,45.371,54.937,114.75409,102.73817,154.61591A1516.99453,1516.99453,0,0,0,605.66974,324.95306Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#f2f2f2"/>
|
||||
<path
|
||||
d="M867.57068,709.78146c-4.71167-5.94958-6.6369-7.343-11.28457-13.34761q-56.7644-73.41638-106.70791-151.79237-33.92354-53.23-64.48275-108.50439-14.54864-26.2781-28.29961-52.96872-10.67044-20.6952-20.8646-41.63793c-1.94358-3.98782-3.8321-7.99393-5.71122-12.00922-4.42788-9.44232-8.77341-18.93047-13.43943-28.24449-5.31686-10.61572-11.789-21.74485-21.55259-28.877a29.40493,29.40493,0,0,0-15.31855-5.89458c-7.948-.51336-15.28184,2.76855-22.17568,6.35295-50.43859,26.301-97.65922,59.27589-140.3696,96.79771A730.77816,730.77816,0,0,0,303.32241,496.24719c-1.008,1.43927-3.39164.06417-2.37419-1.38422q6.00933-8.49818,12.25681-16.81288A734.817,734.817,0,0,1,500.80465,303.06436q18.24824-11.82581,37.18269-22.54245c6.36206-3.60275,12.75188-7.15967,19.25136-10.49653,6.37146-3.27274,13.13683-6.21547,20.41563-6.32547,24.7701-.385,37.59539,27.66695,46.40506,46.54248q4.15283,8.9106,8.40636,17.76626,16.0748,33.62106,33.38729,66.628,10.68453,20.379,21.83683,40.51955,34.7071,62.71816,73.77854,122.897c34.5059,53.1429,68.73651,100.08874,108.04585,149.78472C870.59617,709.21309,868.662,711.17491,867.57068,709.78146Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#e4e4e4"/>
|
||||
<path
|
||||
d="M414.91613,355.804c-1.43911-1.60428-2.86927-3.20856-4.31777-4.81284-11.42244-12.63259-23.6788-25.11847-39.3644-32.36067a57.11025,57.11025,0,0,0-23.92679-5.54622c-8.56213.02753-16.93178,2.27348-24.84306,5.41792-3.74034,1.49427-7.39831,3.1902-11.00078,4.99614-4.11634,2.07182-8.15927,4.28118-12.1834,6.50883q-11.33112,6.27044-22.36816,13.09089-21.9606,13.57221-42.54566,29.21623-10.67111,8.11311-20.90174,16.75788-9.51557,8.03054-18.64618,16.492c-1.30169,1.20091-3.24527-.74255-1.94358-1.94347,1.60428-1.49428,3.22691-2.97938,4.84955-4.44613q6.87547-6.21546,13.9712-12.19257,12.93921-10.91827,26.54851-20.99312,21.16293-15.67614,43.78288-29.22541,11.30361-6.76545,22.91829-12.96259c2.33794-1.24675,4.70318-2.466,7.09572-3.6211a113.11578,113.11578,0,0,1,16.86777-6.86632,60.0063,60.0063,0,0,1,25.476-2.50265,66.32706,66.32706,0,0,1,23.50512,8.1314c15.40091,8.60812,27.34573,21.919,38.97,34.90915C418.03337,355.17141,416.09875,357.12405,414.91613,355.804Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#e4e4e4"/>
|
||||
<path
|
||||
d="M730.47659,486.71092l36.90462-13.498,18.32327-6.70183c5.96758-2.18267,11.92082-4.66747,18.08988-6.23036a28.53871,28.53871,0,0,1,16.37356.20862,37.73753,37.73753,0,0,1,12.771,7.91666,103.63965,103.63965,0,0,1,10.47487,11.18643c3.98932,4.79426,7.91971,9.63877,11.86772,14.46706q24.44136,29.89094,48.56307,60.04134,24.12117,30.14991,47.91981,60.556,23.85681,30.48041,47.38548,61.21573,2.88229,3.76518,5.75966,7.53415c1.0598,1.38809,3.44949.01962,2.37472-1.38808Q983.582,650.9742,959.54931,620.184q-24.09177-30.86383-48.51647-61.46586-24.42421-30.60141-49.17853-60.93743-6.16706-7.55761-12.35445-15.09858c-3.47953-4.24073-6.91983-8.52718-10.73628-12.47427-7.00539-7.24516-15.75772-13.64794-26.23437-13.82166-6.15972-.10214-12.121,1.85248-17.844,3.92287-6.16968,2.232-12.32455,4.50571-18.48633,6.75941l-37.16269,13.59243-9.29067,3.3981c-1.64875.603-.93651,3.2619.73111,2.652Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#e4e4e4"/>
|
||||
<path
|
||||
d="M366.37741,334.52609c-18.75411-9.63866-42.77137-7.75087-60.00508,4.29119a855.84708,855.84708,0,0,1,97.37056,22.72581C390.4603,353.75916,380.07013,341.5635,366.37741,334.52609Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#f2f2f2"/>
|
||||
<path
|
||||
d="M306.18775,338.7841l-3.61042,2.93462c1.22123-1.02713,2.4908-1.99013,3.795-2.90144C306.31073,338.80665,306.24935,338.79473,306.18775,338.7841Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#f2f2f2"/>
|
||||
<path
|
||||
d="M831.54929,486.84576c-3.6328-4.42207-7.56046-9.05222-12.99421-10.84836l-5.07308.20008A575.436,575.436,0,0,0,966.74929,651.418Q899.14929,569.13192,831.54929,486.84576Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#f2f2f2"/>
|
||||
<path
|
||||
d="M516.08388,450.36652A37.4811,37.4811,0,0,0,531.015,471.32518c2.82017,1.92011,6.15681,3.76209,7.12158,7.03463a8.37858,8.37858,0,0,1-.87362,6.1499,24.88351,24.88351,0,0,1-3.86126,5.04137l-.13667.512c-6.99843-4.14731-13.65641-9.3934-17.52227-16.55115s-4.40553-16.53895.34116-23.14544"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#f2f2f2"/>
|
||||
<path
|
||||
d="M749.08388,653.36652A37.4811,37.4811,0,0,0,764.015,674.32518c2.82017,1.92011,6.15681,3.76209,7.12158,7.03463a8.37858,8.37858,0,0,1-.87362,6.1499,24.88351,24.88351,0,0,1-3.86126,5.04137l-.13667.512c-6.99843-4.14731-13.65641-9.3934-17.52227-16.55115s-4.40553-16.53895.34116-23.14544"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#f2f2f2"/>
|
||||
<path
|
||||
d="M284.08388,639.36652A37.4811,37.4811,0,0,0,299.015,660.32518c2.82017,1.92011,6.15681,3.76209,7.12158,7.03463a8.37858,8.37858,0,0,1-.87362,6.1499,24.88351,24.88351,0,0,1-3.86126,5.04137l-.13667.512c-6.99843-4.14731-13.65641-9.3934-17.52227-16.55115s-4.40553-16.53895.34116-23.14544"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#f2f2f2"/>
|
||||
<circle cx="649.24878" cy="51" r="51" fill={fillColor}/>
|
||||
<path
|
||||
d="M911.21851,176.29639c-24.7168-3.34094-52.93512,10.01868-59.34131,34.12353a21.59653,21.59653,0,0,0-41.09351,2.10871l2.82972,2.02667a372.27461,372.27461,0,0,0,160.65881-.72638C957.07935,195.76,935.93537,179.63727,911.21851,176.29639Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#f0f0f0"/>
|
||||
<path
|
||||
d="M805.21851,244.29639c-24.7168-3.34094-52.93512,10.01868-59.34131,34.12353a21.59653,21.59653,0,0,0-41.09351,2.10871l2.82972,2.02667a372.27461,372.27461,0,0,0,160.65881-.72638C851.07935,263.76,829.93537,247.63727,805.21851,244.29639Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#f0f0f0"/>
|
||||
<path
|
||||
d="M1020.94552,257.15423a.98189.98189,0,0,1-.30176-.04688C756.237,173.48919,523.19942,184.42376,374.26388,208.32122c-20.26856,3.251-40.59131,7.00586-60.40381,11.16113-5.05811,1.05957-10.30567,2.19532-15.59668,3.37793-6.31885,1.40723-12.55371,2.85645-18.53223,4.30567q-3.873.917-7.59472,1.84863c-3.75831.92773-7.57178,1.89453-11.65967,2.957-4.56787,1.17774-9.209,2.41309-13.79737,3.67188a.44239.44239,0,0,1-.05127.01465l.00049.001c-5.18261,1.415-10.33789,2.8711-15.32324,4.3252-2.69824.77929-5.30371,1.54785-7.79932,2.30664-.2788.07715-.52587.15136-.77636.22754l-.53614.16308c-.31054.09473-.61718.1875-.92382.27539l-.01953.00586.00048.001-.81152.252c-.96777.293-1.91211.5791-2.84082.86426-24.54492,7.56641-38.03809,12.94922-38.17139,13.00195a1,1,0,1,1-.74414-1.85644c.13428-.05274,13.69336-5.46289,38.32764-13.05762.93213-.28613,1.87891-.57226,2.84961-.86621l.7539-.23438c.02588-.00976.05176-.01757.07813-.02539.30518-.08691.60986-.17968.91943-.27343l.53711-.16309c.26758-.08105.53125-.16113.80127-.23535,2.47852-.75391,5.09278-1.52441,7.79785-2.30664,4.98731-1.45508,10.14746-2.91113,15.334-4.32813.01611-.00586.03271-.00976.04883-.01464v-.001c4.60449-1.2627,9.26269-2.50293,13.84521-3.68457,4.09424-1.06348,7.915-2.03223,11.67969-2.96192q3.73755-.93017,7.60937-1.85253c5.98536-1.45118,12.23291-2.90235,18.563-4.3125,5.29932-1.1836,10.55567-2.32227,15.62207-3.38282,19.84326-4.16211,40.19776-7.92285,60.49707-11.17871C523.09591,182.415,756.46749,171.46282,1021.2463,255.2011a.99974.99974,0,0,1-.30078,1.95313Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#ccc"/>
|
||||
<path
|
||||
d="M432.92309,584.266a6.72948,6.72948,0,0,0-1.7-2.67,6.42983,6.42983,0,0,0-.92-.71c-2.61-1.74-6.51-2.13-8.99,0a5.81012,5.81012,0,0,0-.69.71q-1.11,1.365-2.28,2.67c-1.28,1.46-2.59,2.87-3.96,4.24-.39.38-.78.77-1.18,1.15-.23.23-.46.45-.69.67-.88.84-1.78,1.65-2.69,2.45-.48.43-.96.85-1.45,1.26-.73.61-1.46,1.22-2.2,1.81-.07.05-.14.1-.21.16-.02.01-.03.03-.05.04-.01,0-.02,0-.03.02a.17861.17861,0,0,0-.07.05c-.22.15-.37.25-.48.34.04-.01995.08-.05.12-.07-.18.14-.37.28-.55.42-1.75,1.29-3.54,2.53-5.37,3.69a99.21022,99.21022,0,0,1-14.22,7.55c-.33.13-.67.27-1.01.4a85.96993,85.96993,0,0,1-40.85,6.02q-2.13008-.165-4.26-.45c-1.64-.24-3.27-.53-4.89-.86a97.93186,97.93186,0,0,1-18.02-5.44,118.65185,118.65185,0,0,1-20.66-12.12c-1-.71-2.01-1.42-3.02-2.11,1.15-2.82,2.28-5.64,3.38-8.48.55-1.37,1.08-2.74,1.6-4.12,4.09-10.63,7.93-21.36,11.61-32.13q5.58-16.365,10.53-32.92.51-1.68.99-3.36,2.595-8.745,4.98-17.53c.15-.56994.31-1.12994.45-1.7q.68994-2.52,1.35-5.04c1-3.79-1.26-8.32-5.24-9.23a7.63441,7.63441,0,0,0-9.22,5.24c-.43,1.62-.86,3.23-1.3,4.85q-3.165,11.74494-6.66,23.41-.51,1.68-1.02,3.36-7.71,25.41-16.93,50.31-1.11,3.015-2.25,6.01c-.37.98-.74,1.96-1.12,2.94-.73,1.93-1.48,3.86-2.23,5.79-.43006,1.13-.87006,2.26-1.31,3.38-.29.71-.57,1.42-.85,2.12a41.80941,41.80941,0,0,0-8.81-2.12l-.48-.06a27.397,27.397,0,0,0-7.01.06,23.91419,23.91419,0,0,0-17.24,10.66c-4.77,7.51-4.71,18.25,1.98,24.63,6.89,6.57,17.32,6.52,25.43,2.41a28.35124,28.35124,0,0,0,10.52-9.86,50.56939,50.56939,0,0,0,2.74-4.65c.21.14.42.28.63.43.8.56,1.6,1.13,2.39,1.69a111.73777,111.73777,0,0,0,14.51,8.91,108.35887,108.35887,0,0,0,34.62,10.47c.27.03.53.07.8.1,1.33.17,2.67.3,4.01.41a103.78229,103.78229,0,0,0,55.58-11.36q2.175-1.125,4.31-2.36,3.315-1.92,6.48-4.08c1.15-.78,2.27-1.57,3.38-2.4a101.04244,101.04244,0,0,0,13.51-11.95q2.35491-2.475,4.51-5.11005a8.0612,8.0612,0,0,0,2.2-5.3A7.5644,7.5644,0,0,0,432.92309,584.266Zm-165.59,23.82c.21-.15.42-.31.62-.47C267.89312,607.766,267.60308,607.936,267.33312,608.086Zm3.21-3.23c-.23.26-.44.52-.67.78a23.36609,23.36609,0,0,1-2.25,2.2c-.11.1-.23.2-.35.29a.00976.00976,0,0,0-.01.01,3.80417,3.80417,0,0,0-.42005.22q-.645.39-1.31994.72a17.00459,17.00459,0,0,1-2.71.75,16.79925,16.79925,0,0,1-2.13.02h-.02a14.82252,14.82252,0,0,1-1.45-.4c-.24-.12-.47-.25994-.7-.4-.09-.08-.17005-.16-.22-.21a2.44015,2.44015,0,0,1-.26995-.29.0098.0098,0,0,0-.01-.01c-.11005-.2-.23005-.4-.34-.6a.031.031,0,0,1-.01-.02c-.08-.25-.15-.51-.21-.77a12.51066,12.51066,0,0,1,.01-1.37,13.4675,13.4675,0,0,1,.54-1.88,11.06776,11.06776,0,0,1,.69-1.26c.02-.04.12-.2.23-.38.01-.01.01-.01.01-.02.15-.17.3-.35.46-.51.27-.3.56-.56.85-.83a18.02212,18.02212,0,0,1,1.75-1.01,19.48061,19.48061,0,0,1,2.93-.79,24.98945,24.98945,0,0,1,4.41.04,30.30134,30.30134,0,0,1,4.1,1.01,36.94452,36.94452,0,0,1-2.77,4.54C270.6231,604.746,270.58312,604.806,270.54308,604.856Zm-11.12-3.29a2.18029,2.18029,0,0,1-.31.38995A1.40868,1.40868,0,0,1,259.42309,601.566Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M402.86309,482.136q-.13494,4.71-.27,9.42-.285,10.455-.59,20.92-.315,11.775-.66,23.54-.165,6.07507-.34,12.15-.465,16.365-.92,32.72c-.03,1.13-.07,2.25-.1,3.38q-.225,8.11506-.45,16.23-.255,8.805-.5,17.61-.18,6.59994-.37,13.21-1.34994,47.895-2.7,95.79a7.64844,7.64844,0,0,1-7.5,7.5,7.56114,7.56114,0,0,1-7.5-7.5q.75-26.94,1.52-53.88.675-24.36,1.37-48.72.225-8.025.45-16.06.345-12.09.68-24.18c.03-1.13.07-2.25.1-3.38.02-.99.05-1.97.08-2.96q.66-23.475,1.32-46.96.27-9.24.52-18.49.3-10.545.6-21.08c.09-3.09.17005-6.17.26-9.26a7.64844,7.64844,0,0,1,7.5-7.5A7.56116,7.56116,0,0,1,402.86309,482.136Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M814.29118,484.2172a893.23753,893.23753,0,0,1-28.16112,87.94127c-3.007,7.94641-6.08319,15.877-9.3715,23.71185l.75606-1.7916a54.58274,54.58274,0,0,1-5.58953,10.61184q-.22935.32119-.46685.63642,1.16559-1.49043.4428-.589c-.25405.30065-.5049.60219-.7676.89546a23.66436,23.66436,0,0,1-2.2489,2.20318q-.30139.25767-.61188.5043l.93783-.729c-.10884.25668-.87275.59747-1.11067.74287a18.25362,18.25362,0,0,1-2.40479,1.21853l1.7916-.75606a19.0859,19.0859,0,0,1-4.23122,1.16069l1.9938-.26791a17.02055,17.02055,0,0,1-4.29785.046l1.99379.2679a14.0022,14.0022,0,0,1-3.40493-.917l1.79159.75606a12.01175,12.01175,0,0,1-1.67882-.89614c-.27135-.17688-1.10526-.80852-.01487.02461,1.13336.86595.14562.07434-.08763-.15584-.19427-.19171-.36962-.4-.55974-.595-.88208-.90454.99637,1.55662.39689.49858a18.18179,18.18179,0,0,1-.87827-1.63672l.75606,1.7916a11.92493,11.92493,0,0,1-.728-2.65143l.26791,1.9938a13.65147,13.65147,0,0,1-.00316-3.40491l-.2679,1.9938a15.96371,15.96371,0,0,1,.99486-3.68011l-.75606,1.7916a16.72914,16.72914,0,0,1,1.17794-2.29848,6.72934,6.72934,0,0,1,.72851-1.0714c.04915.01594-1.26865,1.51278-.56937.757.1829-.19767.354-.40592.539-.602.29617-.31382.61354-.60082.92561-.89791,1.04458-.99442-1.46188.966-.25652.17907a19.0489,19.0489,0,0,1,2.74925-1.49923l-1.79159.75606a20.31136,20.31136,0,0,1,4.99523-1.33984l-1.9938.2679a25.62828,25.62828,0,0,1,6.46062.07647l-1.9938-.2679a33.21056,33.21056,0,0,1,7.89178,2.2199l-1.7916-.75606c5.38965,2.31383,10.16308,5.74926,14.928,9.118a111.94962,111.94962,0,0,0,14.50615,8.9065,108.38849,108.38849,0,0,0,34.62226,10.47371,103.93268,103.93268,0,0,0,92.58557-36.75192,8.07773,8.07773,0,0,0,2.1967-5.3033,7.63232,7.63232,0,0,0-2.1967-5.3033c-2.75154-2.52586-7.94926-3.239-10.6066,0a95.63575,95.63575,0,0,1-8.10664,8.72692q-2.01736,1.914-4.14232,3.70983-1.21364,1.02588-2.46086,2.01121c-.3934.31081-1.61863,1.13807.26309-.19744-.43135.30614-.845.64036-1.27058.95478a99.26881,99.26881,0,0,1-20.33215,11.56478l1.79159-.75606a96.8364,96.8364,0,0,1-24.17119,6.62249l1.99379-.2679a97.64308,97.64308,0,0,1-25.75362-.03807l1.99379.2679a99.79982,99.79982,0,0,1-24.857-6.77027l1.7916.75607a116.02515,116.02515,0,0,1-21.7364-12.59112,86.87725,86.87725,0,0,0-11.113-6.99417,42.8238,42.8238,0,0,0-14.43784-4.38851c-9.43884-1.11076-19.0571,2.56562-24.24624,10.72035-4.77557,7.50482-4.71394,18.24362,1.97369,24.62519,6.8877,6.5725,17.31846,6.51693,25.43556,2.40567,7.81741-3.95946,12.51288-12.18539,15.815-19.94186,7.43109-17.45514,14.01023-35.31364,20.1399-53.263q9.09651-26.63712,16.49855-53.81332.91661-3.36581,1.80683-6.73869c1.001-3.78869-1.26094-8.32-5.23829-9.22589a7.63317,7.63317,0,0,0-9.22589,5.23829Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M889.12382,482.13557l-2.69954,95.79311-2.68548,95.29418-1.5185,53.88362a7.56465,7.56465,0,0,0,7.5,7.5,7.64923,7.64923,0,0,0,7.5-7.5l2.69955-95.79311,2.68548-95.29418,1.51849-53.88362a7.56465,7.56465,0,0,0-7.5-7.5,7.64923,7.64923,0,0,0-7.5,7.5Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M629.52566,700.36106h2.32885V594.31942h54.32863v-2.32291H631.85451V547.25214H673.8102q-.92256-1.17339-1.89893-2.31694H631.85451V515.38231c-.7703-.32846-1.54659-.64493-2.32885-.9435V544.9352h-45.652V507.07c-.78227.03583-1.55258.08959-2.3289.15527v37.71h-36.4201V516.68409c-.78227.34636-1.55258.71061-2.31694,1.0928V544.9352h-30.6158v2.31694h30.6158v44.74437h-30.6158v2.32291h30.6158V700.36106h2.31694V594.31942a36.41283,36.41283,0,0,1,36.4201,36.42007v69.62157h2.3289V594.31942h45.652Zm-84.401-108.36455V547.25214h36.4201v44.74437Zm38.749,0V547.25214h.91362a44.74135,44.74135,0,0,1,44.73842,44.74437Z"
|
||||
transform="translate(-169.93432 -164.42601)" opacity="0.2"/>
|
||||
<path
|
||||
d="M615.30309,668.566a63.05854,63.05854,0,0,1-20.05,33.7c-.74.64-1.48,1.26-2.25,1.87q-2.805.25506-5.57.52c-1.53.14-3.04.29-4.54.43l-.27.03-.19-1.64-.76-6.64a37.623,37.623,0,0,1-3.3-32.44c2.64-7.12,7.42-13.41,12.12-19.65,6.49-8.62,12.8-17.14,13.03-27.65a60.54415,60.54415,0,0,1,7.9,13.33,16.432,16.432,0,0,0-5.12,3.76995c-.41.45-.82,1.08-.54,1.62006.24.46.84.57,1.36.62994,1.25.13,2.51.26,3.76.39,1,.11,2,.21,3,.32a63.99025,63.99025,0,0,1,2.45,12.18A61.18851,61.18851,0,0,1,615.30309,668.566Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M648.50311,642.356c-5.9,4.29-9.35,10.46-12.03,17.26a16.62776,16.62776,0,0,0-7.17,4.58c-.41.45-.82,1.08-.54,1.62006.24.46.84.57,1.36.62994,1.25.13,2.51.26,3.76.39-2.68,8.04-5.14,16.36-9.88,23.15a36.98942,36.98942,0,0,1-12.03,10.91,38.49166,38.49166,0,0,1-4.02,1.99q-7.62.585-14.95,1.25-2.805.25506-5.57.52c-1.53.14-3.04.29-4.54.43q-.015-.825,0-1.65a63.30382,63.30382,0,0,1,15.25-39.86c.45-.52.91-1.03,1.38-1.54a61.7925,61.7925,0,0,1,16.81-12.7A62.65425,62.65425,0,0,1,648.50311,642.356Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill={fillColor}/>
|
||||
<path
|
||||
d="M589.16308,699.526l-1.15,3.4-.58,1.73c-1.53.14-3.04.29-4.54.43l-.27.03c-1.66.17-3.31.34-4.96.51-.43-.5-.86-1.01-1.28-1.53a62.03045,62.03045,0,0,1,8.07-87.11c-1.32,6.91.22,13.53,2.75,20.1-.27.11-.53.22-.78.34a16.432,16.432,0,0,0-5.12,3.76995c-.41.45-.82,1.08-.54,1.62006.24.46.84.57,1.36.62994,1.25.13,2.51.26,3.76.39,1,.11,2,.21,3,.32q.705.075,1.41.15c.07.15.13.29.2.44,2.85,6.18,5.92,12.39,7.65,18.83a43.66591,43.66591,0,0,1,1.02,4.91A37.604,37.604,0,0,1,589.16308,699.526Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill={fillColor}/>
|
||||
<path
|
||||
d="M689.82123,554.48655c-8.60876-16.79219-21.94605-30.92088-37.63219-41.30357a114.2374,114.2374,0,0,0-52.5626-18.37992q-3.69043-.33535-7.399-.39281c-2.92141-.04371-46.866,12.63176-61.58712,22.98214a114.29462,114.29462,0,0,0-35.333,39.527,102.49972,102.49972,0,0,0-12.12557,51.6334,113.56387,113.56387,0,0,0,14.70268,51.47577,110.47507,110.47507,0,0,0,36.44425,38.74592C549.66655,708.561,565.07375,734.51,583.1831,735.426c18.24576.923,39.05418-23.55495,55.6951-30.98707a104.42533,104.42533,0,0,0,41.72554-34.005,110.24964,110.24964,0,0,0,19.599-48.94777c2.57368-18.08313,1.37415-36.73271-4.80123-54.01627a111.85969,111.85969,0,0,0-5.58024-12.9833c-1.77961-3.50519-6.996-4.7959-10.26142-2.69063a7.67979,7.67979,0,0,0-2.69064,10.26142q1.56766,3.08773,2.91536,6.27758l-.75606-1.7916a101.15088,101.15088,0,0,1,6.87641,25.53816l-.26791-1.99379a109.2286,109.2286,0,0,1-.06613,28.68252l.26791-1.9938a109.73379,109.73379,0,0,1-7.55462,27.67419l.75606-1.79159a104.212,104.212,0,0,1-6.67151,13.09835q-1.92308,3.18563-4.08062,6.22159c-.63172.8881-1.28287,1.761-1.939,2.63114-.85625,1.13555,1.16691-1.48321.28228-.36941-.15068.18972-.30049.3801-.45182.5693q-.68121.85165-1.3818,1.68765a93.61337,93.61337,0,0,1-10.17647,10.38359q-1.36615,1.19232-2.77786,2.33115c-.46871.37832-.932.77269-1.42079,1.12472.01861-.0134,1.57956-1.19945.65556-.511-.2905.21644-.57851.43619-.86961.65184q-2.90994,2.1558-5.97433,4.092a103.48509,103.48509,0,0,1-14.75565,7.7131l1.7916-.75606a109.21493,109.21493,0,0,1-27.59663,7.55154l1.9938-.26791a108.15361,108.15361,0,0,1-28.58907.0506l1.99379.2679a99.835,99.835,0,0,1-25.09531-6.78448l1.79159.75607a93.64314,93.64314,0,0,1-13.41605-6.99094q-3.17437-2-6.18358-4.24743c-.2862-.21359-.56992-.43038-.855-.64549-.9155-.69088.65765.50965.67021.51787a19.16864,19.16864,0,0,1-1.535-1.22469q-1.45353-1.18358-2.86136-2.4218a101.98931,101.98931,0,0,1-10.49319-10.70945q-1.21308-1.43379-2.37407-2.91054c-.33524-.4263-.9465-1.29026.40424.5289-.17775-.23939-.36206-.47414-.54159-.71223q-.64657-.85751-1.27568-1.72793-2.203-3.048-4.18787-6.24586a109.29037,109.29037,0,0,1-7.8054-15.10831l.75606,1.7916a106.58753,106.58753,0,0,1-7.34039-26.837l.26791,1.9938a97.86589,97.86589,0,0,1-.04843-25.63587l-.2679,1.9938A94.673,94.673,0,0,1,505.27587,570.55l-.75606,1.7916a101.55725,101.55725,0,0,1,7.19519-13.85624q2.0655-3.32328,4.37767-6.4847.52528-.71832,1.06244-1.42786c.324-.4279,1.215-1.49333-.30537.38842.14906-.18449.29252-.37428.43942-.56041q1.26882-1.60756,2.59959-3.1649A107.40164,107.40164,0,0,1,530.772,536.21508q1.47408-1.29171,2.99464-2.52906.6909-.56218,1.39108-1.11284c.18664-.14673.37574-.29073.56152-.43858-1.99743,1.58953-.555.43261-.10157.09288q3.13393-2.34833,6.43534-4.46134a103.64393,103.64393,0,0,1,15.38655-8.10791l-1.7916.75606c7.76008-3.25839,42.14086-10.9492,48.394-10.10973l-1.99379-.26791A106.22471,106.22471,0,0,1,628.768,517.419l-1.7916-.75606a110.31334,110.31334,0,0,1,12.6002,6.32922q3.04344,1.78405,5.96742,3.76252,1.38351.93658,2.73809,1.915.677.48917,1.34626.98885c.24789.185.49386.37253.74135.558,1.03924.779-1.43148-1.1281-.34209-.26655a110.84261,110.84261,0,0,1,10.36783,9.2532q2.401,2.445,4.63686,5.04515,1.14659,1.33419,2.24643,2.70757c.36436.45495,1.60506,2.101.08448.08457.37165.49285.74744.98239,1.11436,1.47884a97.97718,97.97718,0,0,1,8.39161,13.53807c1.79317,3.49775,6.98675,4.80186,10.26142,2.69064A7.67666,7.67666,0,0,0,689.82123,554.48655Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M602.43116,676.88167a3.77983,3.77983,0,0,1-2.73939-6.55137c.09531-.37882.16368-.65085.259-1.02968q-.05115-.12366-.1029-.24717c-3.47987-8.29769-25.685,14.83336-26.645,22.63179a30.029,30.029,0,0,0,.52714,10.32752A120.39223,120.39223,0,0,1,562.77838,652.01a116.20247,116.20247,0,0,1,.72078-12.96332q.59712-5.293,1.65679-10.51055a121.78667,121.78667,0,0,1,24.1515-51.61646c6.87378.38364,12.898-.66348,13.47967-13.98532.10346-2.36972,1.86113-4.42156,2.24841-6.756-.65621.08607-1.32321.13985-1.97941.18285-.20444.0107-.41958.02149-.624.03228l-.07709.00346a3.745,3.745,0,0,1-3.07566-6.10115q.425-.52305.85054-1.04557c.43036-.53793.87143-1.06507,1.30171-1.60292a1.865,1.865,0,0,0,.13986-.16144c.49494-.61322.98971-1.21564,1.48465-1.82885a10.82911,10.82911,0,0,0-3.55014-3.43169c-4.95941-2.90463-11.80146-.89293-15.38389,3.59313-3.59313,4.486-4.27083,10.77947-3.023,16.3843a43.39764,43.39764,0,0,0,6.003,13.3828c-.269.34429-.54872.67779-.81765,1.02209a122.57366,122.57366,0,0,0-12.79359,20.2681c1.0163-7.93863-11.41159-36.60795-16.21776-42.68052-5.773-7.29409-17.61108-4.11077-18.62815,5.13562q-.01476.13428-.02884.26849,1.07082.60411,2.0964,1.28237a5.12707,5.12707,0,0,1-2.06713,9.33031l-.10452.01613c-9.55573,13.64367,21.07745,49.1547,28.74518,41.18139a125.11045,125.11045,0,0,0-6.73449,31.69282,118.66429,118.66429,0,0,0,.08607,19.15986l-.03231-.22593C558.90163,648.154,529.674,627.51374,521.139,629.233c-4.91675.99041-9.75952.76525-9.01293,5.72484q.01788.11874.03635.2375a34.4418,34.4418,0,0,1,3.862,1.86105q1.07082.60423,2.09639,1.28237a5.12712,5.12712,0,0,1-2.06712,9.33039l-.10464.01606c-.07528.01079-.13987.02157-.21507.03237-4.34967,14.96631,27.90735,39.12,47.5177,31.43461h.01081a125.07484,125.07484,0,0,0,8.402,24.52806H601.679c.10765-.3335.20443-.67779.3013-1.01129a34.102,34.102,0,0,1-8.30521-.49477c2.22693-2.73257,4.45377-5.48664,6.6807-8.21913a1.86122,1.86122,0,0,0,.13986-.16135c1.12956-1.39849,2.26992-2.78627,3.39948-4.18476l.00061-.00173a49.95232,49.95232,0,0,0-1.46367-12.72495Zm-34.37066-67.613.0158-.02133-.0158.04282Zm-6.64832,59.93237-.25822-.58084c.01079-.41957.01079-.83914,0-1.26942,0-.11845-.0215-.23672-.0215-.35508.09678.74228.18285,1.48464.29042,2.22692Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#3f3d56"/>
|
||||
<circle cx="95.24878" cy="439" r="11" fill="#3f3d56"/>
|
||||
<circle cx="227.24878" cy="559" r="11" fill="#3f3d56"/>
|
||||
<circle cx="728.24878" cy="559" r="11" fill="#3f3d56"/>
|
||||
<circle cx="755.24878" cy="419" r="11" fill="#3f3d56"/>
|
||||
<circle cx="723.24878" cy="317" r="11" fill="#3f3d56"/>
|
||||
<path d="M434.1831,583.426a10.949,10.949,0,1,1-.21-2.16A10.9921,10.9921,0,0,1,434.1831,583.426Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#3f3d56"/>
|
||||
<circle cx="484.24878" cy="349" r="11" fill="#3f3d56"/>
|
||||
<path d="M545.1831,513.426a10.949,10.949,0,1,1-.21-2.16A10.9921,10.9921,0,0,1,545.1831,513.426Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#3f3d56"/>
|
||||
<path d="M403.1831,481.426a10.949,10.949,0,1,1-.21-2.16A10.9921,10.9921,0,0,1,403.1831,481.426Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#3f3d56"/>
|
||||
<circle cx="599.24878" cy="443" r="11" fill="#3f3d56"/>
|
||||
<circle cx="426.24878" cy="338" r="16" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M1028.875,735.26666l-857.75.30733a1.19068,1.19068,0,1,1,0-2.38136l857.75-.30734a1.19069,1.19069,0,0,1,0,2.38137Z"
|
||||
transform="translate(-169.93432 -164.42601)" fill="#cacaca"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default Svg404
|
||||
77
src/core/components/svgs/SvgChangePassword.jsx
Normal file
77
src/core/components/svgs/SvgChangePassword.jsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import {useTheme} from "@mui/material";
|
||||
|
||||
const SvgChangePassword = ({width, height}) => {
|
||||
const theme = useTheme()
|
||||
const fillColor = theme.palette.primary.main
|
||||
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width={width} height={height}
|
||||
viewBox="0 0 951.23547 632.16225">
|
||||
<path
|
||||
d="M465.59076,496.88433c32.59906-57.34523,94.78224-101.37694,160.60838-97.13517a303.91886,303.91886,0,0,0-79.93135,192.74415c-1.08086,27.64353.5953,58.50234-17.75918,79.20149-11.42033,12.87974-28.87664,19.11743-46.04,20.426-17.16419,1.30818-34.32439-1.79287-51.25919-4.88078l-4.108,1.261C425.53748,622.55617,432.9917,554.22955,465.59076,496.88433Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#f0f0f0"/>
|
||||
<path
|
||||
d="M626.29714,401.1298C577.6195,424.56328,536.113,463.69962,510.63332,511.42944c-5.50863,10.31908-10.19864,21.26636-12.24449,32.84118-2.04677,11.58-.61712,22.60314,3.3381,33.60164,3.61588,10.05484,8.47891,19.92112,9.58764,30.67984,1.16866,11.34025-3.00384,21.94364-10.51467,30.359-9.18971,10.29644-21.531,16.67682-33.81667,22.49689-13.64084,6.46206-27.9118,12.958-37.57338,25.01857-1.17064,1.46131-3.36964-.44057-2.20077-1.89967,16.8095-20.9833,45.58314-24.92774,65.53614-41.8308,9.31043-7.88728,16.30035-18.62816,15.85922-31.21353-.38575-11.00537-5.39185-21.18385-9.141-31.33295-3.93666-10.65673-5.89983-21.37183-4.48809-32.73356,1.44413-11.62241,5.716-22.77612,10.93669-33.19077,11.77384-23.48755,27.88681-45.05091,46.345-63.69115a264.37529,264.37529,0,0,1,73.0986-52.15542c1.68149-.80947,2.612,1.94689.9415,2.75108Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#fff"/>
|
||||
<path
|
||||
d="M518.09691,495.47812a38.97361,38.97361,0,0,1-11.76083-49.07724c.85125-1.66563,3.47954-.42109,2.62716,1.24676a36.0887,36.0887,0,0,0,11.03334,45.62971c1.51533,1.097-.393,3.29149-1.89967,2.20077Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#fff"/>
|
||||
<path
|
||||
d="M499.22208,573.01552A75.11847,75.11847,0,0,0,546.7827,545.9063c1.17577-1.45711,3.37512.44432,2.20077,1.89967A78.13447,78.13447,0,0,1,499.435,575.915c-1.85547.26565-2.05831-2.63524-.21291-2.89944Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#fff"/>
|
||||
<path
|
||||
d="M574.90706,432.68514a22.06094,22.06094,0,0,0,19.71762,7.02965c1.85119-.289,2.05205,2.6123.21291,2.89945a24.7211,24.7211,0,0,1-21.8302-7.72833,1.50247,1.50247,0,0,1-.15055-2.05022,1.461,1.461,0,0,1,2.05022-.15055Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#fff"/>
|
||||
<path
|
||||
d="M757.17329,580.65231c-1.15078.21336-2.30157.42671-3.46287.66229a290.53033,290.53033,0,0,0-45.42472,12.55654c-1.14909.4-2.30759.82272-3.44279,1.25493a306.28393,306.28393,0,0,0-96.32923,58.62179,297.4401,297.4401,0,0,0-31.20006,32.695c-13.1961,16.12271-26.22121,34.65379-43.46521,45.16611a51.02756,51.02756,0,0,1-5.552,3.00981l-99.33786-41.204c-.17876-.20694-.368-.39178-.54786-.59918l-4.04148-1.46379c.45079-.63649.932-1.28694,1.38279-1.92343.26-.3703.542-.73142.802-1.10173.18032-.244.36179-.48759.51056-.718.05971-.08143.12054-.16239.1709-.22127.14877-.23046.31142-.42872.45078-.63649q4.01975-5.46492,8.13029-10.89234c.00941-.02268.00941-.02268.041-.03619,20.95061-27.51625,44.38244-53.52519,71.017-75.1508.80155-.65037,1.61141-1.32388,2.45834-1.95543a283.82353,283.82353,0,0,1,38.36428-25.95136,250.912,250.912,0,0,1,22.75777-11.25342A208.65167,208.65167,0,0,1,633.669,545.38918c43.43148-4.033,87.66932,5.869,120.97979,33.15354C755.50038,579.24131,756.33106,579.931,757.17329,580.65231Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#f0f0f0"/>
|
||||
<path
|
||||
d="M756.427,581.82048c-52.975-10.597-109.67838-4.3386-158.75909,18.43049-10.61113,4.92262-20.94686,10.83971-29.5492,18.84981-8.60619,8.01369-14.10139,17.67579-17.56522,28.83879-3.16664,10.20524-5.224,21.0108-10.81619,30.26856-5.89451,9.75817-15.61,15.71225-26.6736,17.90941-13.53663,2.6883-27.23193.35234-40.5454-2.39747-14.78206-3.05312-30.08763-6.45857-45.06315-2.64583-1.81449.462-2.42521-2.38053-.61346-2.8418,26.05484-6.63351,51.40382,7.5408,77.512,6.05773,12.18255-.692,24.23036-5.0596,31.45541-15.37391,6.318-9.01942,8.449-20.16039,11.566-30.52112,3.27289-10.87894,8.15663-20.61632,16.12437-28.838,8.15056-8.41037,18.27673-14.744,28.71548-19.91633,23.54187-11.66483,49.38981-19.18084,75.35035-22.95093a264.37547,264.37547,0,0,1,89.76631,2.36722c1.82993.36606.91338,3.1271-.9046,2.76343Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#fff"/>
|
||||
<path
|
||||
d="M613.231,592.00833a38.97358,38.97358,0,0,1,20.15752-46.26626c1.68249-.81741,3.03174,1.75871,1.347,2.5772a36.0887,36.0887,0,0,0-18.66273,43.0756c.54944,1.78822-2.2955,2.39145-2.84179.61346Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#fff"/>
|
||||
<path
|
||||
d="M551.4776,642.55365a75.11849,75.11849,0,0,0,54.29611,6.98958c1.81607-.45552,2.42734,2.38682.61346,2.8418a78.13454,78.13454,0,0,1-56.48524-7.38815c-1.64143-.905-.05685-3.34334,1.57567-2.44323Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#fff"/>
|
||||
<path
|
||||
d="M696.3964,576.07528a22.06092,22.06092,0,0,0,11.51107,17.48415c1.65209.88377.06567,3.32125-1.57567,2.44324a24.7211,24.7211,0,0,1-12.7772-19.31393,1.50248,1.50248,0,0,1,1.11417-1.72763,1.461,1.461,0,0,1,1.72763,1.11417Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#fff"/>
|
||||
<path
|
||||
d="M567.94141,648.63076c-13.912-67.2669-31.302-89.69385-31.302-89.69385l-6.64343-5.15185-7.98926-6.20581.03858-.79785-1.8949-.64411-.44513-.34576-.72943-.56006-.11731.126-.24768.25647-36.15234-12.2887-45.86536-15.57934L415.35455,490.14a36.7343,36.7343,0,0,0-29.38672-14.33386l-67.82916.50189a36.73449,36.73449,0,0,0-24.70972,9.80127l-44.58306,41.35412-69.469,33.17786-.11725-.11725-.72949.52106-10.73358,5.13232.44293,2.30561-6.64343,4.79376s-17.39,20.868-31.30206,83.459c-3.53907,15.926-5.28113,50.08979-5.90992,92.1883a16.06908,16.06908,0,0,0,16.06244,16.30737H511.49408v-.00006H557.8056a16.0717,16.0717,0,0,0,16.06262-16.29071C573.25409,703.131,571.51269,665.902,567.94141,648.63076Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M615.54847,191.73153a54.43073,54.43073,0,1,0,0,108.86146H1021.187a54.43073,54.43073,0,0,0,0-108.86146Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#e5e5e5"/>
|
||||
<path d="M615.54847,202.74727a43.415,43.415,0,1,0,0,86.83H1021.187a43.415,43.415,0,0,0,0-86.83Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#fff"/>
|
||||
<circle id="e096411a-cdc3-4e6d-bbd4-4630e1fee17e" data-name="ab6171fa-7d69-4734-b81c-8dff60f9761b"
|
||||
cx="238.3229"
|
||||
cy="228.39206" r="88.86282" fill="#9e616a"/>
|
||||
<path d="M339.97228,445.973q-.56945-1.25376-1.13574-2.51618c.14551.00466.28954.02559.435.0294Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#2f2e41"/>
|
||||
<path
|
||||
d="M271.37112,276.63954c4.49445-3.5853,9.74736-6.88419,15.49373-6.69877,5.74613.18519,11.57324,5.37507,10.38275,10.99974a91.31784,91.31784,0,0,1,109.89524-41.20778c14.28183,5.03874,28.28737,15.1192,31.56809,29.90415.8422,3.79533,1.023,7.95689,3.39274,11.03885,2.98786,3.88573,8.70455,4.76475,13.41179,3.3978q.07062-.0205.141-.04154a4.1986,4.1986,0,0,1,5.07324,5.92695l-4.041,7.5365a32.38317,32.38317,0,0,0,15.428-.3281,4.195,4.195,0,0,1,4.45469,6.52819c-13.32473,18.29415-35.58607,30.10755-58.30327,29.96873-16.14591-.09846-32.45814-5.66309-48.17179-1.95012a41.84383,41.84383,0,0,0-28.14382,58.74019c-4.82733-5.28005-14.159-4.03-19.097,1.147-4.93774,5.177-6.21612,12.90385-5.71853,20.04085.76077,10.91577,5.03759,21.20144,9.5463,31.21221-37.80123-1.19-73.555-27.707-85.58977-63.57189C229.00827,343.26738,241.674,300.32986,271.37112,276.63954Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill="#2f2e41"/>
|
||||
<polygon points="87.464 495.253 112.388 630.86 127.343 632.162 87.464 495.253" opacity="0.2"/>
|
||||
<polygon points="362.007 485.026 337.083 630.762 322.128 632.162 362.007 485.026" opacity="0.2"/>
|
||||
<path
|
||||
d="M292.62933,231.00135c-4.77882,1.99547-9.76532-.19144-11.85656-5.19961-2.12322-5.08476-.14017-10.24648,4.71525-12.27393,4.85588-2.02764,9.75359.1646,11.911,5.33137C299.52417,223.94845,297.5627,228.94135,292.62933,231.00135Zm-9.15419-27.482-3.79972,1.58663a4.09911,4.09911,0,0,1-5.20612-1.90948l-.1879-.36761c-4.08846-7.37337-4.5566-16.33467-1.384-26.62094,2.939-9.22731,4.1597-15.71683,1.70477-21.596-2.83836-6.79741-8.8993-8.92671-16.62838-5.84218-2.99769,1.25173-3.95159,1.23179-6.31064,3.572a5.4161,5.4161,0,0,1-3.92122,1.59344,5.2354,5.2354,0,0,1-3.74713-1.643,5.34757,5.34757,0,0,1-.03684-7.29733,41.53525,41.53525,0,0,1,14.04574-9.64413c16.60647-6.93429,24.96626,3.3032,28.79182,12.46479,3.74183,8.96108,1.637,17.27546-1.745,28.04341-2.83416,8.94752-2.66908,15.57751.55033,22.16977a4.08088,4.08088,0,0,1-2.12565,5.49059Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill={fillColor}/>
|
||||
<path d="M705.14883,272.122h-80.707a1.944,1.944,0,1,1,0-3.88791h80.707a1.944,1.944,0,0,1,0,3.88791Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill={fillColor}/>
|
||||
<path d="M807.53044,272.76994h-80.707a1.944,1.944,0,1,1,0-3.88791h80.707a1.944,1.944,0,1,1,0,3.88791Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill={fillColor}/>
|
||||
<path d="M909.91205,273.41793H829.205a1.944,1.944,0,0,1,0-3.88791h80.707a1.944,1.944,0,1,1,0,3.88791Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill={fillColor}/>
|
||||
<path d="M1012.29367,274.06591h-80.707a1.944,1.944,0,0,1,0-3.88791h80.707a1.944,1.944,0,0,1,0,3.88791Z"
|
||||
transform="translate(-124.38226 -133.06928)" fill={fillColor}/>
|
||||
<circle cx="540.23547" cy="106.16225" r="15" fill={fillColor}/>
|
||||
<circle cx="643.23547" cy="106.16225" r="15" fill={fillColor}/>
|
||||
<circle cx="746.23547" cy="106.16225" r="15" fill={fillColor}/>
|
||||
<circle cx="849.23547" cy="106.16225" r="15" fill={fillColor}/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default SvgChangePassword
|
||||
117
src/core/components/svgs/SvgDashboard.jsx
Normal file
117
src/core/components/svgs/SvgDashboard.jsx
Normal file
@@ -0,0 +1,117 @@
|
||||
import {useTheme} from "@mui/material";
|
||||
|
||||
const SvgDashboard = ({width, height}) => {
|
||||
const theme = useTheme()
|
||||
const fillColor = theme.palette.primary.main
|
||||
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width={width} height={height}
|
||||
viewBox="0 0 1029.56255 548.69495">
|
||||
<path
|
||||
d="M133.37467,722.76736l.21351-1.12612c.04736-.24754,4.90753-24.90966,23.12635-39.22042,18.21964-14.3114,43.33085-13.19135,43.58186-13.17828l1.145.05909-.21358,1.12564c-.04737.24754-4.90763,24.90918-23.12636,39.22042-18.21964,14.3114-43.33084,13.19135-43.58186,13.17828ZM157.95,683.994c-15.40414,12.09937-20.95072,31.88327-22.13763,36.85812,5.11571.02181,25.6644-.68921,41.0536-12.77757,15.38743-12.08706,20.94624-31.88051,22.13762-36.85812C193.88493,671.19461,173.33832,671.90627,157.95,683.994Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#f1f1f1"/>
|
||||
<path
|
||||
d="M165.19537,689.48163c-8.34609,21.49794-30.31721,33.0224-30.31721,33.0224s-8.43942-23.33063-.09333-44.82857S165.102,644.65305,165.102,644.65305,173.54146,667.98369,165.19537,689.48163Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#f1f1f1"/>
|
||||
<path
|
||||
d="M1084.55991,722.826c-.251.01307-25.36223,1.13312-43.58186-13.17828-18.21874-14.31124-23.079-38.97288-23.12636-39.22042l-.21359-1.12564,1.145-.05909c.251-.01307,25.36223-1.13312,43.58186,13.17828,18.21882,14.31076,23.079,38.97288,23.12636,39.22042l.2135,1.12612Zm-64.484-51.60955c1.19139,4.97761,6.75019,24.77106,22.13763,36.85812,15.38919,12.08836,35.93789,12.79938,41.05359,12.77757-1.1869-4.97485-6.73348-24.75875-22.13762-36.85812C1045.74117,671.90627,1025.19457,671.19461,1020.076,671.21642Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#f1f1f1"/>
|
||||
<path
|
||||
d="M1053.88412,689.48163c8.34609,21.49794,30.31722,33.0224,30.31722,33.0224s8.43942-23.33063.09333-44.82857-30.31722-33.02241-30.31722-33.02241S1045.538,667.98369,1053.88412,689.48163Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#f1f1f1"/>
|
||||
<path
|
||||
d="M675.31479,717.62706l-14.5923-6.1443-10.01026-73.15138H517.40762L506.55725,711.1839l-13.05512,6.52746a3.10016,3.10016,0,0,0,1.38657,5.873H674.11213A3.1,3.1,0,0,0,675.31479,717.62706Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#e6e6e6"/>
|
||||
<path
|
||||
d="M912.20621,648.06385H257.377a12.97344,12.97344,0,0,1-12.9443-12.97332V542.751h680.7178v92.33952A12.97356,12.97356,0,0,1,912.20621,648.06385Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#ccc"/>
|
||||
<path
|
||||
d="M925.835,586.39288h-682V191.29161a15.6572,15.6572,0,0,1,15.63964-15.63909H910.1952A15.65735,15.65735,0,0,1,925.835,191.29161Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M885.10186,557.71639H284.56818a12.07023,12.07023,0,0,1-12.057-12.05667v-329.274a12.07087,12.07087,0,0,1,12.057-12.05741H885.10186a12.07088,12.07088,0,0,1,12.057,12.05741v329.274A12.07024,12.07024,0,0,1,885.10186,557.71639Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#fff"/>
|
||||
<path
|
||||
d="M1113.255,724.34746l-1026.44821,0a1.56682,1.56682,0,0,1-1.53909-1.13363,1.52912,1.52912,0,0,1,1.47725-1.91893l1026.385,0a1.61535,1.61535,0,0,1,1.61617,1.19368A1.52819,1.52819,0,0,1,1113.255,724.34746Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#ccc"/>
|
||||
<rect x="219.58182" y="153.2027" width="98.80647" height="9.27916" fill="#e5e5e5"/>
|
||||
<rect x="219.58182" y="175.70578" width="98.80647" height="9.27916" fill="#e5e5e5"/>
|
||||
<rect x="219.58182" y="198.70578" width="98.80647" height="9.27916" fill="#e5e5e5"/>
|
||||
<rect x="219.58182" y="221.70578" width="98.80647" height="9.27916" fill="#e5e5e5"/>
|
||||
<rect x="242.98506" y="250.93227" width="52" height="8.05267" fill={fillColor}/>
|
||||
<rect x="471.19198" y="210.75367" width="0.94479" height="2.83436" fill="#e5e5e5"/>
|
||||
<path
|
||||
d="M557.35549,449.63117h-.94478V443.592h.94478Zm0-12.07807h-.94478v-6.03916h.94478Zm0-12.07831h-.94478v-6.03893h.94478Zm0-12.07808h-.94478v-6.03916h.94478Zm0-12.07808h-.94478v-6.03916h.94478Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#e5e5e5"/>
|
||||
<rect x="471.19198" y="280.01781" width="0.94479" height="2.83436" fill="#e5e5e5"/>
|
||||
<rect x="574.64601" y="210.75367" width="0.94479" height="2.83436" fill="#e5e5e5"/>
|
||||
<path
|
||||
d="M660.80952,449.63117h-.94479V443.592h.94479Zm0-12.07807h-.94479v-6.03916h.94479Zm0-12.07831h-.94479v-6.03893h.94479Zm0-12.07808h-.94479v-6.03916h.94479Zm0-12.07808h-.94479v-6.03916h.94479Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#e5e5e5"/>
|
||||
<rect x="574.64601" y="280.01781" width="0.94479" height="2.83436" fill="#e5e5e5"/>
|
||||
<rect x="626.83111" y="155.3061" width="0.94479" height="2.83436" fill="#e5e5e5"/>
|
||||
<path
|
||||
d="M712.99462,449.86668h-.94478V444.063h.94478Zm0-11.6073h-.94478V432.4555h.94478Zm0-11.60753h-.94478V420.8482h.94478Zm0-11.6073h-.94478V409.2409h.94478Zm0-11.6073h-.94478v-5.80388h.94478Zm0-11.60753h-.94478v-5.80365h.94478Zm0-11.60731h-.94478v-5.80365h.94478Zm0-11.6073h-.94478v-5.80365h.94478Zm0-11.60753h-.94478v-5.80365h.94478Zm0-11.6073h-.94478v-5.80365h.94478Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#e5e5e5"/>
|
||||
<rect x="626.83111" y="280.01781" width="0.94479" height="2.83436" fill="#e5e5e5"/>
|
||||
<rect x="678.49585" y="132.63125" width="0.94479" height="2.83436" fill="#e5e5e5"/>
|
||||
<path
|
||||
d="M764.65936,449.88836h-.94479v-5.7822h.94479Zm0-11.56417h-.94479V432.542h.94479Zm0-11.56416h-.94479v-5.7822h.94479Zm0-11.56417h-.94479v-5.7822h.94479Zm0-11.56417h-.94479v-5.7822h.94479Zm0-11.56416h-.94479v-5.7822h.94479Zm0-11.56417h-.94479v-5.7822h.94479Zm0-11.56417h-.94479V363.157h.94479Zm0-11.56416h-.94479v-5.7822h.94479Zm0-11.56417h-.94479v-5.7822h.94479Zm0-11.56417h-.94479v-5.7822h.94479Zm0-11.56417h-.94479v-5.78219h.94479Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#e5e5e5"/>
|
||||
<rect x="678.49585" y="280.01781" width="0.94479" height="2.83436" fill="#e5e5e5"/>
|
||||
<rect x="523.15519" y="172.78464" width="0.94479" height="2.83436" fill="#e5e5e5"/>
|
||||
<path
|
||||
d="M609.3187,450.17576h-.94478V444.6812h.94478Zm0-10.98936h-.94478v-5.49456h.94478Zm0-10.98936h-.94478v-5.49456h.94478Zm0-10.98936h-.94478v-5.49456h.94478Zm0-10.98936h-.94478v-5.49456h.94478Zm0-10.98936h-.94478v-5.49457h.94478Zm0-10.98936h-.94478V378.745h.94478Zm0-10.98936h-.94478v-5.49457h.94478Zm0-10.98936h-.94478v-5.49457h.94478Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#e5e5e5"/>
|
||||
<rect x="523.15519" y="280.01781" width="0.94479" height="2.83436" fill="#e5e5e5"/>
|
||||
<path
|
||||
d="M817.06089,459.82073H504.27977a.97891.97891,0,0,1-.97886-.97886v-149.916a.97886.97886,0,0,1,1.95772,0V457.863H817.06089a.97886.97886,0,1,1,0,1.95772Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#3f3d56"/>
|
||||
<polygon
|
||||
points="575.548 212.069 523.544 173.118 472.251 211.537 471.077 209.97 523.544 170.672 575.3 209.438 626.731 153.155 626.938 153.071 678.817 132.168 679.549 133.985 627.876 154.804 575.548 212.069"
|
||||
fill="#3f3d56"/>
|
||||
<circle cx="471.66442" cy="210.75355" r="5.87317" fill={fillColor}/>
|
||||
<circle cx="523.54411" cy="172.57792" r="5.87317" fill={fillColor}/>
|
||||
<circle cx="575.42381" cy="210.75355" r="5.87317" fill={fillColor}/>
|
||||
<circle cx="627.3035" cy="153.97954" r="5.87317" fill={fillColor}/>
|
||||
<circle cx="679.1832" cy="132.44458" r="5.87317" fill={fillColor}/>
|
||||
<rect x="347.26975" y="28.67555" width="2" height="353.38818" fill="#e5e5e5"/>
|
||||
<path
|
||||
d="M905.98772,554.09977a7.34552,7.34552,0,0,0-1.961-11.09143l4.882-25.64286-12.52095,5.218L893.6713,546.1344a7.38532,7.38532,0,0,0,12.31642,7.96537Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#ffb7b7"/>
|
||||
<polygon points="883.2 535.797 872.598 535.797 867.554 494.903 883.202 494.904 883.2 535.797"
|
||||
fill="#ffb7b7"/>
|
||||
<path
|
||||
d="M971.1222,721.727l-34.18529-.00126v-.43239a13.30659,13.30659,0,0,1,13.30587-13.30566h.00084l20.87921.00085Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#2f2e41"/>
|
||||
<polygon points="825.26 535.797 814.658 535.797 809.614 494.903 825.262 494.904 825.26 535.797"
|
||||
fill="#ffb7b7"/>
|
||||
<path
|
||||
d="M910.58783,721.727l-34.18529-.00126v-.43239a13.30659,13.30659,0,0,1,13.30587-13.30566h.00084l20.87921.00085Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#2f2e41"/>
|
||||
<polygon
|
||||
points="824.391 363.083 814.014 386.99 805.453 524.403 827.073 523.538 832.978 458.033 851.192 399.689 861.664 464.733 865.988 521.808 883.877 522.583 891.005 363.083 824.391 363.083"
|
||||
fill="#2f2e41"/>
|
||||
<path
|
||||
d="M961.48266,420.76584l-30.07691.75236-17.65821,9.065-.96906,66.87968-11.0131,46.17488s68.811,4.73581,78.32355-2.1824L968.84683,488.704,983.925,431.69483Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill={fillColor}/>
|
||||
<path
|
||||
d="M916.96023,431.62873l-3.21269-1.04552s-10.19135,6.54059-9.22166,22.35367c0,0-.382,8.1827-.01724,13.62852.41834,6.24634-12.10688,68.31736-12.10688,68.31736h18.16032l7.783-56.21048Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill={fillColor}/>
|
||||
<path
|
||||
d="M983.45379,554.96455a7.34552,7.34552,0,0,1,1.961-11.09143l-4.882-25.64286,12.52095,5.218,2.71649,23.55092a7.38532,7.38532,0,0,1-12.31642,7.96537Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#ffb7b7"/>
|
||||
<path
|
||||
d="M979.39949,432.4935l3.2127-1.04551s10.19134,6.54059,9.22166,22.35367c0,0,.382,8.1827.01724,13.62852-.41834,6.24634,5.18866,68.31736,5.18866,68.31736H978.87944l-7.783-56.21049Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill={fillColor}/>
|
||||
<path
|
||||
d="M968.86587,392.707a20.84977,20.84977,0,1,1-20.84978-20.84975h0a20.79787,20.79787,0,0,1,20.84975,20.74588Q968.866,392.655,968.86587,392.707Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#ffb7b7"/>
|
||||
<path
|
||||
d="M927.23562,364.702c2.44244-5.25207,7.169-4.21369,11.30278-2.43339,5.23475-1.16114,10.21334-4.63745,15.85348-2.58158,5.55578,8.08056,24.209,5.70314,20.24058,18.85835-.00519,3.15227,5.93159,1.31744,4.89514,6.48014,3.14494,9.93555-11.35179,28.752-19.674,24.78956,2.05822-3.77215,6.76-12.34-.37128-13.18978-15.34037,14.27367-1.58274-27.18028-20.85755-15.1248C932.24272,387.341,923.50556,370.544,927.23562,364.702Z"
|
||||
transform="translate(-85.21873 -175.65252)" fill="#2f2e41"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default SvgDashboard
|
||||
136
src/core/components/svgs/SvgLoading.jsx
Normal file
136
src/core/components/svgs/SvgLoading.jsx
Normal file
@@ -0,0 +1,136 @@
|
||||
import {useTheme} from "@mui/material";
|
||||
|
||||
const SvgLoading = ({width, height}) => {
|
||||
const theme = useTheme()
|
||||
const fillColor = theme.palette.primary.main
|
||||
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width={width} height={height}
|
||||
viewBox="0 0 693.97296 712.57302">
|
||||
<path id="a7e0d23c-0c47-41f1-93b9-87dfccd4c0f5-182" data-name="Path 968"
|
||||
d="M752.75753,262.60547h-3.9v-106.977a61.915,61.915,0,0,0-61.915-61.915h-226.65a61.915,61.915,0,0,0-61.916,61.914v586.884a61.915,61.915,0,0,0,61.915,61.915h226.648a61.915,61.915,0,0,0,61.915-61.915v-403.758h3.9Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#3f3d56"/>
|
||||
<path id="a1ad11fc-8226-4675-bbe0-e36020d9de96-183" data-name="Path 969"
|
||||
d="M736.15756,151.48149v595.175a46.959,46.959,0,0,1-46.942,46.952h-231.3a46.966,46.966,0,0,1-46.973-46.952v-595.175a46.965,46.965,0,0,1,46.971-46.951h28.058a22.329,22.329,0,0,0,20.656,30.74h131.868a22.329,22.329,0,0,0,20.656-30.74h30.055a46.959,46.959,0,0,1,46.951,46.942Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#fff"/>
|
||||
<path id="a71e44ec-7616-4081-86af-b6db32cd39f3-184" data-name="Path 39"
|
||||
d="M678.82353,494.30947h-205.537a3.81,3.81,0,0,1-3.806-3.806V439.51949a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985a3.811,3.811,0,0,1-3.806,3.806Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="a3f57aef-fb20-4553-8f82-b751eb5ec42c-185" data-name="Path 40"
|
||||
d="M536.85153,454.07448a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00221-.11712-.0019h-125.692Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="a617e1da-1a45-4bf0-a146-8b20186fa5b6-186" data-name="Path 41"
|
||||
d="M536.85153,470.05846a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00219-.11712-.00189h-125.692Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="f83fafa3-5270-49ac-8952-eedc3d6c92ed-187" data-name="Path 42"
|
||||
d="M678.82353,579.28947h-205.537a3.81,3.81,0,0,1-3.806-3.806V524.49949a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985A3.811,3.811,0,0,1,678.82353,579.28947Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="b1e095e5-1d51-47f4-b1e9-85a21efab4ec-188" data-name="Path 43"
|
||||
d="M536.85153,539.33047a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.087-5.328h-125.692Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="e7ccabbb-2f45-40c9-adc9-a92013dc0f4d-189" data-name="Path 44"
|
||||
d="M536.85153,555.3185a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.087-5.328h-125.692Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="ec532991-8ec8-4eba-a86f-87c70c278f41-190" data-name="Path 39-2"
|
||||
d="M678.82353,664.54748h-205.537a3.81,3.81,0,0,1-3.806-3.806V609.7575a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985a3.811,3.811,0,0,1-3.806,3.806Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="a788f10e-f95b-4590-bad9-be702445c232-191" data-name="Path 40-2"
|
||||
d="M536.85153,624.59148a2.66449,2.66449,0,1,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00219-.11712-.00189h-125.692Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="f15a5014-9b42-4c0b-a546-80766b911601-192" data-name="Path 41-2"
|
||||
d="M536.85153,640.57846a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.0022-.11712-.00189h-125.692Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="b97f850c-7352-4ff9-8496-0f681ff3b244-193" data-name="Path 970"
|
||||
d="M945.17252,806.28651h-690.347c-1,0-1.812-.468-1.812-1.045s.812-1.04505,1.812-1.04505H945.17447c1,0,1.812.468,1.812,1.045S946.17252,806.28651,945.17252,806.28651Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<g id="ac055b4e-9afd-48c4-86db-12c8e2993e8d" data-name="Group 58">
|
||||
<path id="b77ebe88-e0c7-4a9a-a2fb-b51dce897c46-194" data-name="Path 438"
|
||||
d="M282.08554,765.52248a19.47406,19.47406,0,0,0,18.806-3.313c6.587-5.528,8.652-14.637,10.332-23.07l4.97-24.945-10.405,7.165c-7.483,5.152-15.134,10.47-20.316,17.933s-7.443,17.651-3.28,25.727"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="a8a7bc76-ff28-4167-bc9c-ebff63445848-195" data-name="Path 439"
|
||||
d="M283.69254,797.45852c-1.31-9.542-2.657-19.206-1.738-28.85.816-8.565,3.429-16.93,8.749-23.789a39.57353,39.57353,0,0,1,10.153-9.2c1.015-.641,1.95.968.939,1.606a37.622,37.622,0,0,0-14.885,17.955c-3.24,8.241-3.76,17.224-3.2,25.978.338,5.294,1.053,10.553,1.774,15.806a.964.964,0,0,1-.65,1.144.936.936,0,0,1-1.144-.65Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#f2f2f2"/>
|
||||
<path id="abfc2b94-a38f-4778-bd11-bd0282c86570-196" data-name="Path 442"
|
||||
d="M293.11954,782.1495a14.336,14.336,0,0,0,12.491,6.447c6.323-.3,11.595-4.713,16.34-8.9l14.036-12.392-9.289-.444c-6.68-.32-13.533-.618-19.9,1.442s-12.231,7.018-13.394,13.6"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="ba99c695-899d-4604-b38e-601ed41861fa-197" data-name="Path 443"
|
||||
d="M279.99051,802.94448c6.3-11.156,13.618-23.555,26.685-27.518a29.77893,29.77893,0,0,1,11.224-1.159c1.192.1.894,1.94-.3,1.837a27.66479,27.66479,0,0,0-17.912,4.739c-5.051,3.438-8.983,8.217-12.311,13.286-2.039,3.1-3.865,6.341-5.691,9.573C281.10352,804.73452,279.4035,803.98946,279.99051,802.94448Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#f2f2f2"/>
|
||||
</g>
|
||||
<g id="bf60e786-3805-43a5-8cdd-bbea060079bf" data-name="Group 59">
|
||||
<circle id="a323e3dd-8f2c-40f7-a0c1-7a235f78e8b7" data-name="Ellipse 5" cx="245.91502" cy="370.985"
|
||||
r="15.986"
|
||||
fill={fillColor}/>
|
||||
<path id="b21d221e-9b86-4bff-9dca-a61a27263db1-198" data-name="Path 40-3"
|
||||
d="M491.27554,461.71247c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.94306,5.94306,0,0,0-.328-2.708h-15.73Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
</g>
|
||||
<g id="b51141dd-8175-4f5a-b697-41b89601b37f" data-name="Group 60">
|
||||
<circle id="e363222e-d569-47a6-8bf5-edbaac636a07" data-name="Ellipse 5-2" cx="245.91502" cy="456.278"
|
||||
r="15.986"
|
||||
fill={fillColor}/>
|
||||
<path id="bf4b9d9b-b2cd-48cd-bc0b-2e6b007ef33d-199" data-name="Path 40-4"
|
||||
d="M491.27554,547.00547c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.94306,5.94306,0,0,0-.328-2.708h-15.73Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
</g>
|
||||
<g id="b35aa588-fd9e-4429-8570-fee6b5da93cc" data-name="Group 61">
|
||||
<circle id="b896a996-d737-41ee-9642-d5eaf8a9fd6b" data-name="Ellipse 5-3" cx="245.91502" cy="541.53599"
|
||||
r="15.986" fill={fillColor}/>
|
||||
<path id="f0c90521-3626-484d-9767-39f7327e6a31-200" data-name="Path 40-5"
|
||||
d="M491.27554,632.26346c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.9431,5.9431,0,0,0-.328-2.708h-15.73Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
</g>
|
||||
<path
|
||||
d="M625.19989,350.38193a4.48656,4.48656,0,0,1-4.01245-2.4497,52.87438,52.87438,0,0,0-31.37232-26.41114,59.99908,59.99908,0,0,0-8.408-1.9038l-.57959-.08789L610.74725,225.983l.50586.01758c58.12769,15.79492,91.385,62.38134,100.19336,76.2832a4.49382,4.49382,0,0,1-1.79663,6.42334L627.21918,349.9044A4.50685,4.50685,0,0,1,625.19989,350.38193Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e6e6e6"/>
|
||||
<path id="e0f3bbc9-2b9f-408e-80ac-e1d5d48fdbc4-201" data-name="Path 2881"
|
||||
d="M804.63654,549.70647a9.27592,9.27592,0,0,1,12.711-6.383l22.283-24.293,4.164,16.616-21.8,20.521a9.326,9.326,0,0,1-17.359-6.462Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#feb8b8"/>
|
||||
<path id="b7278a0b-1b02-42c5-a26a-5568eba21726-202" data-name="Path 2882"
|
||||
d="M852.49454,792.04449h-13.613l-6.478-52.517h20.1Z" transform="translate(-253.01352 -93.71349)"
|
||||
fill="#feb8b8"/>
|
||||
<path id="ae5e3f59-c07c-4936-a848-b4ed4a22f493-203" data-name="Path 2883"
|
||||
d="M855.96756,787.5985h-26.815a17.089,17.089,0,0,0-17.088,17.087v.556h43.9Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#2f2e41"/>
|
||||
<path id="e2dcac65-80ca-45a3-9c58-68329f82aa19-204" data-name="Path 2884"
|
||||
d="M930.68353,778.55646l-12.729,4.832-24.693-46.8,18.787-7.13Z"
|
||||
transform="translate(-253.01352 -93.71349)"
|
||||
fill="#feb8b8"/>
|
||||
<path id="e33efd2e-5dad-4e18-8ce5-ea4b13e613d2-205" data-name="Path 2885"
|
||||
d="M932.35455,773.16747l-25.069,9.515h0a17.089,17.089,0,0,0-9.911,22.039l.2.519,41.045-15.578Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#2f2e41"/>
|
||||
<path id="aea1be6b-88fd-4404-a4b2-fdb70dea932e-206" data-name="Path 2886"
|
||||
d="M885.86453,617.36046l11.283,60.71405s30.625,85.428,28.476,87.577-31.7,9.671-30.088,4.836-35.461-77.369-35.461-77.369Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#2f2e41"/>
|
||||
<path id="a45d4c0e-5c31-49a4-b00c-14ea50dd8cbe-207" data-name="Path 2887"
|
||||
d="M840.10855,507.03047s-22.777,29.774-19.792,31.4,14.547,10.236,14.547,10.236l11.764-32.284Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e4e4e4"/>
|
||||
<path id="ababf4ae-7dbc-4717-bb50-ecd0b5fac405-208" data-name="Path 2888"
|
||||
d="M833.74753,537.0825s-3.761,27.939-2.149,33.849.537,173.543-.537,176.229-4.3,11.82-2.686,16.118,23.64,15.044,26.864,11.283,26.866-140.768,26.866-140.768,33.312-82.742,25.79-90.8S833.74753,537.0825,833.74753,537.0825Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#2f2e41"/>
|
||||
<circle id="a4a0a325-f198-46ef-8204-e1264a7da486" data-name="Ellipse 542" cx="629.07161" cy="237.48247"
|
||||
r="26.32701"
|
||||
fill="#feb8b8"/>
|
||||
<path id="f1bcc5ff-8c37-42ba-ac71-fb7b653723a6-209" data-name="Path 2890"
|
||||
d="M854.57553,390.69649a18.66405,18.66405,0,0,1,6-11.04l4.8-14.675h28.209l7.861,12.335c8.5,3.661,14.8,9.467,15.039,16.311,1.3,4.545-4.3,148.828-5.91,154.2-.473,1.564-6.9,2.4-15.936,2.772-8.285.338-18.756.29-28.809.059-16.645-.387-32.162-1.279-34.773-1.757C825.15152,547.82848,853.99054,394.08647,854.57553,390.69649Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e4e4e4"/>
|
||||
<path id="f2ae932d-f3ee-421e-b804-f39bdd3d1485-210" data-name="Path 2891"
|
||||
d="M879.51553,582.02647a9.276,9.276,0,0,0,1.826-14.106l15.569-29.056-17.059,1.558-12.168,27.352a9.326,9.326,0,0,0,11.833,14.251Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#feb8b8"/>
|
||||
<path id="a13bc27c-3d22-450d-9b6a-4857ac9e22b6-211" data-name="Path 2893"
|
||||
d="M882.10355,374.82347s-24.715,10.208-15.581,36,19.342,56.415,19.342,56.415-12.895,69.31-12.895,72-8.059,17.193-4.836,19.88,24.715,8.059,25.252,5.373a181.71945,181.71945,0,0,1,5.91-18.268c1.075-2.149,26.327-69.31,23.1-75.22-2.372-4.349-4.454-44.2-5.388-64.939a34.107,34.107,0,0,0-17.781-28.715C894.22256,374.68749,888.39056,373.25148,882.10355,374.82347Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#e4e4e4"/>
|
||||
<path id="a3aad1c3-1778-4515-92de-8de9e018032c-212" data-name="Path 2800"
|
||||
d="M892.21851,342.96248c-2-.922-4.317-1.113-6.479-1.686-7.734-2.052-12.916-9.689-11.261-16.6a7.47905,7.47905,0,0,0,.406-2.736c-.289-2.047-2.687-3.368-4.986-3.837s-4.746-.4-6.943-1.155a9.39,9.39,0,0,1-6.136-7.366,13.67394,13.67394,0,0,1,2.327-9.171l.831,2.088a7.77124,7.77124,0,0,0,2.714-3.545,5.5,5.5,0,0,1,4.26,2.992c1.333.687,1.525-2.133,3-2.549a2.945,2.945,0,0,1,1.838.4c2.967,1.209,6.414.175,9.6-.495a41.22185,41.22185,0,0,1,16.771-.017c3.663.763,7.29,2.093,9.912,4.455a20.35,20.35,0,0,1,4.636,6.96c2.812,6.182,4.669,12.871,3.741,19.473a26.05108,26.05108,0,0,1-7.436,14.6c-2.123,2.137-9.05,9.591-12.848,8.321C891.38751,351.49449,897.84155,345.5595,892.21851,342.96248Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#2f2e41"/>
|
||||
<circle cx="321.97861" cy="266.45946" r="8" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M521.30463,350.26524a4.492,4.492,0,0,1-2.1001-.52442l-81.95288-43.23437a4.5,4.5,0,0,1-1.74121-6.32471,181.66635,181.66635,0,0,1,40.991-45.9751c28.30152-22.43066,60.4939-33.68408,95.678-33.49512a151.88378,151.88378,0,0,1,39.064,5.28858l.50464.13672-29.927,93.541-.42114-.06347a66.68158,66.68158,0,0,0-8.13867-.72168c-30.45068-.85938-43.64649,19.876-47.90772,28.82959a4.41453,4.41453,0,0,1-2.62011,2.31005A4.52734,4.52734,0,0,1,521.30463,350.26524Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill={fillColor}/>
|
||||
<path d="M611.122,226.483l-21.15967,94.56a60.38421,60.38421,0,0,0-8.48-1.92l29.62988-92.64Z"
|
||||
transform="translate(-253.01352 -93.71349)" fill="#3f3d56"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default SvgLoading
|
||||
75
src/core/components/svgs/SvgLogin.jsx
Normal file
75
src/core/components/svgs/SvgLogin.jsx
Normal file
@@ -0,0 +1,75 @@
|
||||
import {useTheme} from "@mui/material";
|
||||
|
||||
const SvgLogin = ({width, height}) => {
|
||||
const theme = useTheme()
|
||||
const fillColor = theme.palette.primary.main
|
||||
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width={width} height={height}
|
||||
viewBox="0 0 869.99994 520.13854">
|
||||
<path
|
||||
d="M831.09242,704.18737c-11.13833-9.4118-17.90393-24.27967-16.12965-38.75366s12.76358-27.78,27.01831-30.85364,30.50415,5.43465,34.83378,19.3594c2.3828-26.84637,5.12854-54.81757,19.40179-77.67976,12.92407-20.70115,35.3088-35.51364,59.5688-38.16357s49.80265,7.35859,64.93272,26.50671,18.83461,46.98549,8.2379,68.96911c-7.80623,16.19456-22.188,28.24676-37.2566,38.05184a240.45181,240.45181,0,0,1-164.45376,35.97709Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#f2f2f2"/>
|
||||
<path
|
||||
d="M996.72788,546.00953a393.41394,393.41394,0,0,0-54.82622,54.44229,394.561,394.561,0,0,0-61.752,103.194c-1.112,2.72484,3.31272,3.911,4.4123,1.21642A392.34209,392.34209,0,0,1,999.96343,549.24507c2.28437-1.86015-.97-5.08035-3.23555-3.23554Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#fff"/>
|
||||
<path
|
||||
d="M445.06712,701.63014c15.2985-12.92712,24.591-33.34815,22.15408-53.22817s-17.53079-38.15588-37.10966-42.37749-41.89745,7.46449-47.8442,26.59014c-3.27278-36.87349-7.04406-75.29195-26.64837-106.69317-17.75122-28.433-48.49666-48.778-81.81777-52.41768s-68.40395,10.107-89.18511,36.407-25.86934,64.53459-11.31476,94.72909c10.72185,22.24324,30.47528,38.79693,51.17195,52.26422,66.02954,42.9653,147.93912,60.88443,225.8773,49.41454"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#f2f2f2"/>
|
||||
<path
|
||||
d="M217.56676,484.37281a540.35491,540.35491,0,0,1,75.30383,74.77651A548.0761,548.0761,0,0,1,352.25665,647.04a545.835,545.835,0,0,1,25.43041,53.8463c1.52726,3.74257-4.55,5.37169-6.06031,1.67075a536.35952,536.35952,0,0,0-49.009-92.727A539.73411,539.73411,0,0,0,256.889,528.63168a538.44066,538.44066,0,0,0-43.76626-39.81484c-3.13759-2.55492,1.33232-6.97788,4.444-4.444Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#fff"/>
|
||||
<path
|
||||
d="M789.5,708.93073h-365v-374.5c0-79.67773,64.82227-144.5,144.49976-144.5h76.00049c79.67749,0,144.49975,64.82227,144.49975,144.5Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#f2f2f2"/>
|
||||
<path
|
||||
d="M713.5,708.93073h-289v-374.5a143.38177,143.38177,0,0,1,27.59571-84.94434c.66381-.90478,1.32592-1.79785,2.00878-2.68115a144.46633,144.46633,0,0,1,30.75415-29.85058c.65967-.48,1.322-.95166,1.99415-1.42334a144.15958,144.15958,0,0,1,31.47216-16.459c.66089-.25049,1.33374-.50146,2.00659-.74219a144.01979,144.01979,0,0,1,31.1084-7.33593c.65772-.08985,1.333-.16016,2.0083-.23047a146.28769,146.28769,0,0,1,31.10547,0c.67334.07031,1.34864.14062,2.01416.23144a143.995,143.995,0,0,1,31.10034,7.335c.6731.24073,1.346.4917,2.00879.74268a143.79947,143.79947,0,0,1,31.10645,16.21582c.67163.46143,1.344.93311,2.00635,1.40478a145.987,145.987,0,0,1,18.38354,15.564,144.305,144.305,0,0,1,12.72437,14.55078c.68066.88037,1.34277,1.77344,2.00537,2.67676A143.38227,143.38227,0,0,1,713.5,334.43073Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#ccc"/>
|
||||
<circle cx="524.99994" cy="335.5" r="16" fill={fillColor}/>
|
||||
<polygon points="594.599 507.783 582.339 507.783 576.506 460.495 594.601 460.496 594.599 507.783"
|
||||
fill="#ffb8b8"/>
|
||||
<path
|
||||
d="M573.58165,504.27982h23.64384a0,0,0,0,1,0,0v14.88687a0,0,0,0,1,0,0H558.69478a0,0,0,0,1,0,0v0a14.88688,14.88688,0,0,1,14.88688-14.88688Z"
|
||||
fill="#2f2e41"/>
|
||||
<polygon points="655.599 507.783 643.339 507.783 637.506 460.495 655.601 460.496 655.599 507.783"
|
||||
fill="#ffb8b8"/>
|
||||
<path
|
||||
d="M634.58165,504.27982h23.64384a0,0,0,0,1,0,0v14.88687a0,0,0,0,1,0,0H619.69478a0,0,0,0,1,0,0v0a14.88688,14.88688,0,0,1,14.88688-14.88688Z"
|
||||
fill="#2f2e41"/>
|
||||
<path
|
||||
d="M698.09758,528.60035a10.74272,10.74272,0,0,1,4.51052-15.84307l41.67577-114.86667L764.791,409.082,717.20624,518.85271a10.80091,10.80091,0,0,1-19.10866,9.74764Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#ffb8b8"/>
|
||||
<path
|
||||
d="M814.33644,550.1843a10.74269,10.74269,0,0,1-2.89305-16.21659L798.53263,412.4583l23.33776,1.06622L827.23606,533.045a10.80091,10.80091,0,0,1-12.89962,17.13934Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#ffb8b8"/>
|
||||
<circle cx="612.1058" cy="162.12254" r="24.56103" fill="#ffb8b8"/>
|
||||
<path
|
||||
d="M814.17958,522.54937H740.13271l.08911-.57617c.13306-.86133,13.19678-86.439,3.56177-114.436a11.813,11.813,0,0,1,6.06933-14.5835h.00025c13.77173-6.48535,40.20752-14.47119,62.52,4.90918a28.23448,28.23448,0,0,1,9.45947,23.396Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill={fillColor}/>
|
||||
<path d="M754.35439,448.1812,721.01772,441.418l15.62622-37.02978a13.99723,13.99723,0,0,1,27.10571,6.99755Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill={fillColor}/>
|
||||
<path
|
||||
d="M797.05043,460.73882l-2.00415-45.94141c-1.51977-8.63623,3.42408-16.80029,11.02735-18.13476,7.60547-1.32959,15.03174,4.66016,16.55835,13.35986l7.533,42.92774Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill={fillColor}/>
|
||||
<path
|
||||
d="M811.71606,517.04933c11.91455,45.37671,13.21436,103.0694,10,166l-16-2-29-120-16,122-18-1c-5.37744-66.02972-10.61328-122.71527-2-160Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#2f2e41"/>
|
||||
<path
|
||||
d="M793.2891,371.03474c-4.582,4.88079-13.09131,2.26067-13.68835-4.40717a8.05467,8.05467,0,0,1,.01014-1.55569c.30826-2.95357,2.01461-5.63506,1.60587-8.7536a4.59046,4.59046,0,0,0-.84011-2.14892c-3.65124-4.88933-12.22227,2.18687-15.6682-2.23929-2.113-2.714.3708-6.98713-1.25065-10.02051-2.14006-4.00358-8.47881-2.0286-12.45388-4.22116-4.42275-2.43948-4.15822-9.22524-1.24686-13.35269,3.55052-5.03359,9.77572-7.71951,15.92336-8.10661s12.25292,1.27475,17.99229,3.51145c6.52109,2.54134,12.98768,6.05351,17.00067,11.78753,4.88021,6.97317,5.34986,16.34793,2.90917,24.50174C802.09785,360.98987,797.03077,367.04906,793.2891,371.03474Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#2f2e41"/>
|
||||
<path
|
||||
d="M1004.98163,709.57417h-738.294a1.19069,1.19069,0,0,1,0-2.38137h738.294a1.19069,1.19069,0,0,1,0,2.38137Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#3f3d56"/>
|
||||
<path
|
||||
d="M634,600.43073H504a6.46539,6.46539,0,0,1-6.5-6.41531V303.846a6.46539,6.46539,0,0,1,6.5-6.41531H634a6.46539,6.46539,0,0,1,6.5,6.41531V594.01542A6.46539,6.46539,0,0,1,634,600.43073Z"
|
||||
transform="translate(-165.00003 -189.93073)" fill="#fff"/>
|
||||
<rect x="332.49994" y="201.38965" width="143" height="2" fill="#ccc"/>
|
||||
<rect x="332.99994" y="315.5" width="143" height="2" fill="#ccc"/>
|
||||
<rect x="377.49994" y="107.5" width="2" height="304" fill="#ccc"/>
|
||||
<rect x="427.49994" y="107.5" width="2" height="304" fill="#ccc"/>
|
||||
</svg>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default SvgLogin
|
||||
13
src/core/data/apiRoutes.js
Normal file
13
src/core/data/apiRoutes.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL;
|
||||
|
||||
//login
|
||||
export const GET_USER_TOKEN = BASE_URL + "/dashboard/login";
|
||||
//end login
|
||||
|
||||
//change password
|
||||
export const SET_USER_PASSWORD = BASE_URL + "/dashboard/profile/change_password";
|
||||
//end change password
|
||||
|
||||
//user data
|
||||
export const GET_USER_ROUTE = BASE_URL + "/dashboard/profile/info";
|
||||
//user data
|
||||
19
src/core/data/headerProfileItems.jsx
Normal file
19
src/core/data/headerProfileItems.jsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import BorderColorIcon from "@mui/icons-material/BorderColor";
|
||||
import PasswordIcon from "@mui/icons-material/Password";
|
||||
|
||||
const headerProfileItems = [
|
||||
{
|
||||
key: 0,
|
||||
name: "header.edit_profile",
|
||||
route: "/dashboard/edit-profile",
|
||||
icon: <BorderColorIcon/>,
|
||||
},
|
||||
{
|
||||
key: 1,
|
||||
name: "header.change_password",
|
||||
route: "/dashboard/change-password",
|
||||
icon: <PasswordIcon/>,
|
||||
},
|
||||
];
|
||||
|
||||
export default headerProfileItems;
|
||||
16
src/core/data/sidebarMenu.jsx
Normal file
16
src/core/data/sidebarMenu.jsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import SpaceDashboardIcon from "@mui/icons-material/SpaceDashboard";
|
||||
|
||||
const sidebarMenu = [
|
||||
[
|
||||
{
|
||||
key: "sidebar.dashboard",
|
||||
type: "page",
|
||||
route: "/dashboard",
|
||||
icon: <SpaceDashboardIcon />,
|
||||
selected: false,
|
||||
permission: "all",
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
export default sidebarMenu;
|
||||
38
src/core/utils/createEmotionCache.jsx
Normal file
38
src/core/utils/createEmotionCache.jsx
Normal file
@@ -0,0 +1,38 @@
|
||||
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,
|
||||
});
|
||||
};
|
||||
62
src/core/utils/errorHandler.js
Normal file
62
src/core/utils/errorHandler.js
Normal file
@@ -0,0 +1,62 @@
|
||||
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)
|
||||
}
|
||||
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]);
|
||||
})
|
||||
}
|
||||
}
|
||||
9
src/core/utils/succesHandler.js
Normal file
9
src/core/utils/succesHandler.js
Normal file
@@ -0,0 +1,9 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
14
src/core/utils/theme-rtl.jsx
Normal file
14
src/core/utils/theme-rtl.jsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import {createTheme} from "@mui/material/styles";
|
||||
import theme from "./theme";
|
||||
import {faIR} from "@mui/x-date-pickers/locales";
|
||||
|
||||
const themeRtl = createTheme({
|
||||
direction: "rtl",
|
||||
typography: {
|
||||
fontFamily: `IRANSansFaNum, sans-serif`,
|
||||
},
|
||||
faIR,
|
||||
...theme,
|
||||
});
|
||||
|
||||
export default themeRtl;
|
||||
29
src/core/utils/theme.jsx
Normal file
29
src/core/utils/theme.jsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import {colord} from "colord";
|
||||
|
||||
const theme = {
|
||||
palette: {
|
||||
primary: {
|
||||
main: process.env.NEXT_PUBLIC_PRIMARY_MAIN,
|
||||
contrastText: "#FFFFFF",
|
||||
light: colord(process.env.NEXT_PUBLIC_PRIMARY_MAIN).lighten(0.1).toHex(),
|
||||
dark: colord(process.env.NEXT_PUBLIC_PRIMARY_MAIN).darken(0.1).toHex(),
|
||||
},
|
||||
secondary: {
|
||||
main: process.env.NEXT_PUBLIC_SECONDARY_MAIN,
|
||||
contrastText: "#FFFFFF",
|
||||
light: colord(process.env.NEXT_PUBLIC_SECONDARY_MAIN).lighten(0.1).toHex(),
|
||||
dark: colord(process.env.NEXT_PUBLIC_SECONDARY_MAIN).darken(0.1).toHex(),
|
||||
},
|
||||
},
|
||||
components: {
|
||||
MuiBackdrop: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: colord(process.env.NEXT_PUBLIC_PRIMARY_MAIN).darken(0.2).alpha(0.7).toHex(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default theme;
|
||||
56
src/layouts/AppLayout.jsx
Normal file
56
src/layouts/AppLayout.jsx
Normal file
@@ -0,0 +1,56 @@
|
||||
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;
|
||||
18
src/layouts/CenterLayout.jsx
Normal file
18
src/layouts/CenterLayout.jsx
Normal file
@@ -0,0 +1,18 @@
|
||||
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;
|
||||
21
src/layouts/FullPageLayout.jsx
Normal file
21
src/layouts/FullPageLayout.jsx
Normal file
@@ -0,0 +1,21 @@
|
||||
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;
|
||||
73
src/layouts/MuiLayout.jsx
Normal file
73
src/layouts/MuiLayout.jsx
Normal file
@@ -0,0 +1,73 @@
|
||||
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;
|
||||
25
src/layouts/ScrollableLayout.jsx
Normal file
25
src/layouts/ScrollableLayout.jsx
Normal file
@@ -0,0 +1,25 @@
|
||||
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;
|
||||
19
src/layouts/dashboardLayouts/breadcrumbs/BreadcrumbItem.jsx
Normal file
19
src/layouts/dashboardLayouts/breadcrumbs/BreadcrumbItem.jsx
Normal file
@@ -0,0 +1,19 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
49
src/layouts/dashboardLayouts/breadcrumbs/index.jsx
Normal file
49
src/layouts/dashboardLayouts/breadcrumbs/index.jsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import {useRouter} from "next/router";
|
||||
import {Box, Breadcrumbs} from "@mui/material";
|
||||
import {useTheme} from "@mui/material/styles";
|
||||
import {NavigateBefore, NavigateNext} from "@mui/icons-material";
|
||||
import BreadcrumbItem from "./BreadcrumbItem";
|
||||
|
||||
const BreadCrumbs = (props) => {
|
||||
const {isVisible} = props;
|
||||
const theme = useTheme();
|
||||
const router = useRouter();
|
||||
|
||||
if (!isVisible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {pathname} = router;
|
||||
const RouterArray = pathname.split("/").filter((segment) => segment !== "");
|
||||
|
||||
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;
|
||||
18
src/layouts/dashboardLayouts/header/ProfileData.jsx
Normal file
18
src/layouts/dashboardLayouts/header/ProfileData.jsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import {Avatar, Stack, Typography} 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.avatar}
|
||||
/>
|
||||
<Typography sx={{fontSize: 15, fontWeight: 600}} textAlign="center">
|
||||
{user.username}
|
||||
</Typography>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
62
src/layouts/dashboardLayouts/header/ProfileMenu.jsx
Normal file
62
src/layouts/dashboardLayouts/header/ProfileMenu.jsx
Normal file
@@ -0,0 +1,62 @@
|
||||
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.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;
|
||||
49
src/layouts/dashboardLayouts/header/ProfileOptionLogOut.jsx
Normal file
49
src/layouts/dashboardLayouts/header/ProfileOptionLogOut.jsx
Normal file
@@ -0,0 +1,49 @@
|
||||
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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
49
src/layouts/dashboardLayouts/header/ProfileOptions.jsx
Normal file
49
src/layouts/dashboardLayouts/header/ProfileOptions.jsx
Normal file
@@ -0,0 +1,49 @@
|
||||
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}/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
72
src/layouts/dashboardLayouts/header/index.jsx
Normal file
72
src/layouts/dashboardLayouts/header/index.jsx
Normal file
@@ -0,0 +1,72 @@
|
||||
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;
|
||||
45
src/layouts/dashboardLayouts/index.jsx
Normal file
45
src/layouts/dashboardLayouts/index.jsx
Normal file
@@ -0,0 +1,45 @@
|
||||
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";
|
||||
|
||||
const drawerWidth = 240;
|
||||
|
||||
const DashboardLayouts = (props) => {
|
||||
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;
|
||||
27
src/layouts/dashboardLayouts/sidebar/SidebarDrawer.jsx
Normal file
27
src/layouts/dashboardLayouts/sidebar/SidebarDrawer.jsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import {Divider, Stack, Toolbar, Typography} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import SidebarList from "./SidebarList";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
|
||||
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.name} | {user.position}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Toolbar>
|
||||
<Divider/>
|
||||
<SidebarList handleDrawerToggle={handleDrawerToggle}/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SidebarDrawer;
|
||||
72
src/layouts/dashboardLayouts/sidebar/SidebarList.jsx
Normal file
72
src/layouts/dashboardLayouts/sidebar/SidebarList.jsx
Normal file
@@ -0,0 +1,72 @@
|
||||
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) => {
|
||||
console.log(item)
|
||||
if (item.type === "page") {
|
||||
if (action.route === item.route)
|
||||
return {...item, selected: true}
|
||||
else
|
||||
return {...item, selected: false}
|
||||
}
|
||||
return {...item}
|
||||
// item.subItem.map((subitem) => {
|
||||
// if (action.route === subitem.route)
|
||||
// return {...item, showSubItem: true, subItem: {...subitem, selected: true}}
|
||||
// else
|
||||
// return {...item, showSubItem: false, subItem: {...subitem, selected: false}}
|
||||
// })
|
||||
}
|
||||
)
|
||||
);
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
export default function SidebarList({handleDrawerToggle}) {
|
||||
const [itemMenu, dispatch] = useReducer(reducer, sidebarMenu);
|
||||
const {user} = useUser();
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({type: "SELECTED", route: router.pathname});
|
||||
}, [router.pathname]);
|
||||
|
||||
return (
|
||||
<List>
|
||||
{itemMenu.map((itemArr, index) => (
|
||||
<Fragment key={index}>
|
||||
{itemArr.map((item) =>
|
||||
<Fragment key={item.key}>
|
||||
{(user.permissions.includes(item.permission) || item.permission === "all") &&
|
||||
<SidebarListItem
|
||||
item={item}
|
||||
dispatch={dispatch}
|
||||
handleDrawerToggle={handleDrawerToggle}
|
||||
/>}
|
||||
</Fragment>
|
||||
)}
|
||||
<Divider/>
|
||||
</Fragment>
|
||||
))}
|
||||
</List>
|
||||
|
||||
);
|
||||
}
|
||||
84
src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx
Normal file
84
src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import ExpandLess from "@mui/icons-material/ExpandLess";
|
||||
import ExpandMore from "@mui/icons-material/ExpandMore";
|
||||
import {Badge, IconButton, ListItem, ListItemButton, ListItemIcon, ListItemText, Typography,} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {Fragment} from "react";
|
||||
import SidebarListSubItem from "./SidebarListSubItem";
|
||||
import useNotification from "@/lib/app/hooks/useNotification";
|
||||
|
||||
const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
|
||||
const t = useTranslations();
|
||||
const {notification_count} = useNotification()
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListItem disablePadding secondaryAction={
|
||||
<IconButton>
|
||||
<Badge
|
||||
badgeContent={notification_count ? notification_count[item.name] : 0}
|
||||
color="error"
|
||||
variant="standard"
|
||||
anchorOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
}>
|
||||
<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)}
|
||||
secondary={
|
||||
item.secondary !== undefined ? (
|
||||
<Typography variant="caption" color="textSecondary">
|
||||
{t(item.secondary)}
|
||||
</Typography>
|
||||
) : null
|
||||
}
|
||||
/>
|
||||
|
||||
|
||||
{item.type == "menu" &&
|
||||
(item.showSubItem ? <ExpandLess/> : <ExpandMore/>)}
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
{item.subItem && (
|
||||
<SidebarListSubItem
|
||||
item={item}
|
||||
handleDrawerToggle={handleDrawerToggle}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SidebarListItem;
|
||||
71
src/layouts/dashboardLayouts/sidebar/SidebarListSubItem.jsx
Normal file
71
src/layouts/dashboardLayouts/sidebar/SidebarListSubItem.jsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import {
|
||||
Badge,
|
||||
Collapse,
|
||||
IconButton,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import useNotification from "@/lib/app/hooks/useNotification";
|
||||
|
||||
const SidebarListSubItem = ({item, handleDrawerToggle}) => {
|
||||
const t = useTranslations();
|
||||
const {notification_count} = useNotification()
|
||||
|
||||
return (
|
||||
<Collapse in={item.showSubItem} timeout="auto" mountOnEnter={true} unmountOnExit={true}>
|
||||
<List component="div" disablePadding sx={{bgcolor: "#f6f6f6", pr: 1}}>
|
||||
{item.subItem.map((subitem, index) => (
|
||||
<ListItem key={subitem.key} disablePadding secondaryAction={
|
||||
<IconButton>
|
||||
<Badge
|
||||
badgeContent={notification_count ? notification_count[subitem.name] : 0}
|
||||
color="error"
|
||||
variant="standard"
|
||||
anchorOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
}>
|
||||
<ListItemButton
|
||||
selected={subitem.selected}
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: subitem.route,
|
||||
}}
|
||||
sx={{
|
||||
minHeight: 48,
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
justifyContent: "center",
|
||||
pr: 2,
|
||||
}}
|
||||
>
|
||||
{subitem.icon}
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={t(subitem.key)} secondary={
|
||||
subitem.secondary !== undefined ? (
|
||||
<Typography variant="caption" color="textSecondary">
|
||||
{t(subitem.secondary)}
|
||||
</Typography>
|
||||
) : null
|
||||
}/>
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
</Collapse>
|
||||
);
|
||||
};
|
||||
|
||||
export default SidebarListSubItem;
|
||||
46
src/layouts/dashboardLayouts/sidebar/index.jsx
Normal file
46
src/layouts/dashboardLayouts/sidebar/index.jsx
Normal file
@@ -0,0 +1,46 @@
|
||||
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;
|
||||
99
src/lib/app/contexts/language.jsx
Normal file
99
src/lib/app/contexts/language.jsx
Normal file
@@ -0,0 +1,99 @@
|
||||
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>
|
||||
);
|
||||
};
|
||||
14
src/lib/app/contexts/loading.jsx
Normal file
14
src/lib/app/contexts/loading.jsx
Normal file
@@ -0,0 +1,14 @@
|
||||
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>
|
||||
);
|
||||
};
|
||||
132
src/lib/app/contexts/user.jsx
Normal file
132
src/lib/app/contexts/user.jsx
Normal file
@@ -0,0 +1,132 @@
|
||||
import {GET_USER_ROUTE} 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(/* use in 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(GET_USER_ROUTE, {
|
||||
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>
|
||||
);
|
||||
};
|
||||
10
src/lib/app/hooks/useDirection.jsx
Normal file
10
src/lib/app/hooks/useDirection.jsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import {useContext} from "react";
|
||||
import {LanguageContext} from "../contexts/language";
|
||||
|
||||
const useDirection = () => {
|
||||
const {directionApp} = useContext(LanguageContext);
|
||||
|
||||
return {directionApp};
|
||||
};
|
||||
|
||||
export default useDirection;
|
||||
28
src/lib/app/hooks/useLanguage.jsx
Normal file
28
src/lib/app/hooks/useLanguage.jsx
Normal file
@@ -0,0 +1,28 @@
|
||||
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;
|
||||
10
src/lib/app/hooks/useLoading.jsx
Normal file
10
src/lib/app/hooks/useLoading.jsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import {useContext} from "react";
|
||||
import {LoadingContext} from "../contexts/loading";
|
||||
|
||||
const useLoading = () => {
|
||||
const {setLoadingPage} = useContext(LoadingContext);
|
||||
|
||||
return {setLoadingPage};
|
||||
};
|
||||
|
||||
export default useLoading;
|
||||
58
src/lib/app/hooks/useNetwork.jsx
Normal file
58
src/lib/app/hooks/useNetwork.jsx
Normal file
@@ -0,0 +1,58 @@
|
||||
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;
|
||||
23
src/lib/app/hooks/useNotification.jsx
Normal file
23
src/lib/app/hooks/useNotification.jsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import useSWR from 'swr'
|
||||
import {GET_SIDEBAR_NOTIFICATION} from "@/core/data/apiRoutes";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
|
||||
const useNotification = () => {
|
||||
const requestServer = useRequest({auth: true, notification: false})
|
||||
|
||||
//swr config
|
||||
const fetcher = (...args) => {
|
||||
return requestServer(args, 'get').then((response) => {
|
||||
return response.data.data;
|
||||
}).catch(() => {
|
||||
})
|
||||
};
|
||||
|
||||
const {data, mutate} = useSWR(GET_SIDEBAR_NOTIFICATION, fetcher)
|
||||
const notification_count = data
|
||||
//swr config
|
||||
|
||||
// render data
|
||||
return {notification_count, update_notification: mutate}
|
||||
}
|
||||
export default useNotification
|
||||
66
src/lib/app/hooks/useRequest.jsx
Normal file
66
src/lib/app/hooks/useRequest.jsx
Normal file
@@ -0,0 +1,66 @@
|
||||
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
|
||||
34
src/lib/app/hooks/useUser.jsx
Normal file
34
src/lib/app/hooks/useUser.jsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import {useContext} from "react";
|
||||
import {UserContext} from "../contexts/user";
|
||||
|
||||
const useUser = () => {
|
||||
const {
|
||||
isAuth,
|
||||
userChangedLanguage,
|
||||
token,
|
||||
user,
|
||||
getUser,
|
||||
clearUser,
|
||||
changeUser,
|
||||
changeAuthState,
|
||||
changeLanguageState,
|
||||
clearToken,
|
||||
setToken,
|
||||
} = useContext(UserContext);
|
||||
|
||||
return {
|
||||
isAuth,
|
||||
userChangedLanguage,
|
||||
token,
|
||||
user,
|
||||
getUser,
|
||||
clearUser,
|
||||
changeUser,
|
||||
changeAuthState,
|
||||
changeLanguageState,
|
||||
clearToken,
|
||||
setToken,
|
||||
};
|
||||
};
|
||||
|
||||
export default useUser;
|
||||
43
src/middlewares/RolePermission.jsx
Normal file
43
src/middlewares/RolePermission.jsx
Normal file
@@ -0,0 +1,43 @@
|
||||
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 RolePermissionMiddleware = ({children, requiredPermissions}) => {
|
||||
const {user} = useUser();
|
||||
const t = useTranslations();
|
||||
|
||||
const hasPermission = requiredPermissions.some((permission) =>
|
||||
user?.permissions?.includes(permission)
|
||||
);
|
||||
|
||||
if (!hasPermission) {
|
||||
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 RolePermissionMiddleware;
|
||||
42
src/middlewares/WithAuth.jsx
Normal file
42
src/middlewares/WithAuth.jsx
Normal file
@@ -0,0 +1,42 @@
|
||||
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-expert",
|
||||
query: {back_url: encodeURIComponent(router.asPath)},
|
||||
}}
|
||||
>
|
||||
{t("login")}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default WithAuthMiddleware;
|
||||
56
src/middlewares/WithoutAuth.jsx
Normal file
56
src/middlewares/WithoutAuth.jsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import Message from "@/core/components/Messages";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import {Stack, Typography} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {useSearchParams} from "next/navigation";
|
||||
import {useRouter} from "next/router";
|
||||
import {useEffect} from "react";
|
||||
|
||||
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;
|
||||
24
src/pages/403.jsx
Normal file
24
src/pages/403.jsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import {useRouter} from "next/router";
|
||||
import {NextIntlProvider} from "next-intl";
|
||||
import UnAuthorizedComponent from "@/components/errors/403";
|
||||
|
||||
export default function Custom404() {
|
||||
const router = useRouter()
|
||||
const [messages, setMessages] = useState(null)
|
||||
useEffect(() => {
|
||||
const fetch = async () => {
|
||||
const tempMessages = (await import(`&/locales/${router.locale}/app.json`)).default
|
||||
setMessages(tempMessages)
|
||||
}
|
||||
fetch()
|
||||
}, []);
|
||||
|
||||
if (!messages) return
|
||||
|
||||
return (
|
||||
<NextIntlProvider messages={messages}>
|
||||
<UnAuthorizedComponent/>
|
||||
</NextIntlProvider>
|
||||
);
|
||||
}
|
||||
25
src/pages/404.jsx
Normal file
25
src/pages/404.jsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import {useRouter} from "next/router";
|
||||
import {NextIntlProvider} from "next-intl";
|
||||
import NotFoundComponent from "@/components/errors/404";
|
||||
|
||||
export default function Custom404() {
|
||||
const router = useRouter()
|
||||
const [messages, setMessages] = useState(null)
|
||||
useEffect(() => {
|
||||
|
||||
const fetch = async () => {
|
||||
const tempMessages = (await import(`&/locales/${router.locale}/app.json`)).default
|
||||
setMessages(tempMessages)
|
||||
}
|
||||
fetch()
|
||||
}, []);
|
||||
|
||||
if (!messages) return
|
||||
|
||||
return (
|
||||
<NextIntlProvider messages={messages}>
|
||||
<NotFoundComponent/>
|
||||
</NextIntlProvider>
|
||||
);
|
||||
}
|
||||
24
src/pages/500.jsx
Normal file
24
src/pages/500.jsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import {useRouter} from "next/router";
|
||||
import {NextIntlProvider} from "next-intl";
|
||||
import ServerErrorComponent from "@/components/errors/500";
|
||||
|
||||
export default function Custom500() {
|
||||
const router = useRouter()
|
||||
const [messages, setMessages] = useState(null)
|
||||
useEffect(() => {
|
||||
const fetch = async () => {
|
||||
const tempMessages = (await import(`&/locales/${router.locale}/app.json`)).default
|
||||
setMessages(tempMessages)
|
||||
}
|
||||
fetch()
|
||||
}, []);
|
||||
|
||||
if (!messages) return
|
||||
|
||||
return (
|
||||
<NextIntlProvider messages={messages}>
|
||||
<ServerErrorComponent/>
|
||||
</NextIntlProvider>
|
||||
);
|
||||
}
|
||||
33
src/pages/_app.jsx
Normal file
33
src/pages/_app.jsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import "&/fontiran.scss";
|
||||
import AppLayout from "@/layouts/AppLayout";
|
||||
import MuiLayout from "@/layouts/MuiLayout";
|
||||
import {LanguageProvider} from "@/lib/app/contexts/language";
|
||||
import {LoadingProvider} from "@/lib/app/contexts/loading";
|
||||
import {UserProvider} from "@/lib/app/contexts/user";
|
||||
import "moment/locale/fa";
|
||||
import {NextIntlProvider} from "next-intl";
|
||||
import TitlePage from "@/core/components/TitlePage";
|
||||
|
||||
const App = ({Component, pageProps}) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<UserProvider>
|
||||
<LanguageProvider>
|
||||
<NextIntlProvider messages={pageProps.messages || {}}>
|
||||
<MuiLayout isBot={pageProps.isBot}>
|
||||
{pageProps.messages ? <TitlePage text={pageProps.title}/> : ''}
|
||||
<LoadingProvider>
|
||||
<AppLayout isBot={pageProps.isBot}>
|
||||
<Component {...pageProps} />
|
||||
</AppLayout>
|
||||
</LoadingProvider>
|
||||
</MuiLayout>
|
||||
</NextIntlProvider>
|
||||
</LanguageProvider>
|
||||
</UserProvider>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
61
src/pages/_document.jsx
Normal file
61
src/pages/_document.jsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import {createEmotionCacheRtl} from "@/core/utils/createEmotionCache";
|
||||
import theme from "@/core/utils/theme";
|
||||
import createEmotionServer from "@emotion/server/create-instance";
|
||||
import Document, {Head, Html, Main, NextScript} from "next/document";
|
||||
|
||||
export default function MyDocument(props) {
|
||||
const {emotionStyleTags} = props;
|
||||
|
||||
return (
|
||||
<Html>
|
||||
<Head>
|
||||
<meta name="theme-color" content={theme.palette.primary.main}/>
|
||||
<meta name="emotion-insertion-point" content=""/>
|
||||
<link rel="shortcut icon" href="/icons/favicon.png"/>
|
||||
<link rel="manifest" href="/manifest.json"/>
|
||||
{emotionStyleTags}
|
||||
</Head>
|
||||
<body>
|
||||
<Main/>
|
||||
<NextScript/>
|
||||
</body>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
|
||||
MyDocument.getInitialProps = async (ctx) => {
|
||||
const originalRenderPage = ctx.renderPage;
|
||||
let cache;
|
||||
switch (ctx.locale) {
|
||||
case "fa":
|
||||
cache = createEmotionCacheRtl();
|
||||
break;
|
||||
}
|
||||
|
||||
const {extractCriticalToChunks} = createEmotionServer(cache);
|
||||
|
||||
ctx.renderPage = () =>
|
||||
originalRenderPage({
|
||||
enhanceApp: (App) =>
|
||||
function EnhanceApp(props) {
|
||||
return <App emotionCache={cache} {...props} />;
|
||||
},
|
||||
});
|
||||
|
||||
const initialProps = await Document.getInitialProps(ctx);
|
||||
|
||||
const emotionStyles = extractCriticalToChunks(initialProps.html);
|
||||
const emotionStyleTags = emotionStyles.styles.map((style) => (
|
||||
<style
|
||||
data-emotion={`${style.key} ${style.ids.join(" ")}`}
|
||||
key={style.key}
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{__html: style.css}}
|
||||
/>
|
||||
));
|
||||
|
||||
return {
|
||||
...initialProps,
|
||||
emotionStyleTags,
|
||||
};
|
||||
};
|
||||
22
src/pages/dashboard/change-password/index.jsx
Normal file
22
src/pages/dashboard/change-password/index.jsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import DashboardChangePasswordComponent from "@/components/dashboard/change-password";
|
||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
||||
import {parse} from "next-useragent";
|
||||
|
||||
export default function LoanFollowUp() {
|
||||
return (
|
||||
<WithAuthMiddleware>
|
||||
<DashboardChangePasswordComponent/>
|
||||
</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: "Dashboard.change_password",
|
||||
isBot,
|
||||
},
|
||||
};
|
||||
}
|
||||
22
src/pages/dashboard/edit-profile/index.jsx
Normal file
22
src/pages/dashboard/edit-profile/index.jsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import DashboardEditProfile from "@/components/dashboard/edit-profile";
|
||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
||||
import {parse} from "next-useragent";
|
||||
|
||||
export default function LoanFollowUp() {
|
||||
return (
|
||||
<WithAuthMiddleware>
|
||||
<DashboardEditProfile/>
|
||||
</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: "Dashboard.edit_profile",
|
||||
isBot,
|
||||
},
|
||||
};
|
||||
}
|
||||
22
src/pages/dashboard/index.jsx
Normal file
22
src/pages/dashboard/index.jsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import DashboardFirstComponent from "@/components/dashboard/first";
|
||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
||||
import {parse} from "next-useragent";
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<WithAuthMiddleware>
|
||||
<DashboardFirstComponent/>
|
||||
</WithAuthMiddleware>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getServerSideProps({req, locale}) {
|
||||
const {isBot} = parse(req.headers["user-agent"]);
|
||||
return {
|
||||
props: {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Dashboard.dashboard_page",
|
||||
isBot,
|
||||
},
|
||||
};
|
||||
}
|
||||
21
src/pages/index.jsx
Normal file
21
src/pages/index.jsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import FirstComponent from "@/components/first";
|
||||
import {parse} from "next-useragent";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<FirstComponent/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getServerSideProps({req, locale}) {
|
||||
const {isBot} = parse(req.headers["user-agent"]);
|
||||
return {
|
||||
props: {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "first_page",
|
||||
isBot,
|
||||
},
|
||||
};
|
||||
}
|
||||
22
src/pages/login-expert.jsx
Normal file
22
src/pages/login-expert.jsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import LoginComponent from "@/components/login-expert";
|
||||
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
|
||||
import {parse} from "next-useragent";
|
||||
|
||||
export default function Login() {
|
||||
return (
|
||||
<WithoutAuthMiddleware>
|
||||
<LoginComponent/>
|
||||
</WithoutAuthMiddleware>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getServerSideProps({req, locale}) {
|
||||
const {isBot} = parse(req.headers["user-agent"]);
|
||||
return {
|
||||
props: {
|
||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||
title: "Titles.title_login_expert_page",
|
||||
isBot,
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user