diff --git a/example.env.local b/example.env.local
index bf64ae2..ff1832b 100644
--- a/example.env.local
+++ b/example.env.local
@@ -2,6 +2,18 @@ NEXT_PUBLIC_API_NAME = "Loan Facilities Dashboard"
NEXT_PUBLIC_DEFAULT_LANGUAGE = "fa"
NEXT_PUBLIC_DEFAULT_DIRECTION = "rtl"
+
+NEXT_PUBLIC_PRIMARY_MAIN = "#084070"
+NEXT_PUBLIC_PRIMARY_CONTRAST_TEXT = "#fff"
+NEXT_PUBLIC_PRIMARY_LIGHT = "#2c6291"
+NEXT_PUBLIC_PRIMARY_DARK = "#11293e"
+
+
+NEXT_PUBLIC_SECONDARY_MAIN = "#FF4E00"
+NEXT_PUBLIC_SECONDARY_CONTRAST_TEXT = "#fff"
+NEXT_PUBLIC_SECONDARY_LIGHT = "#ed743e"
+NEXT_PUBLIC_SECONDARY_DARK = "#ad3a07"
+
NEXT_PUBLIC_API_URL = "http://Your IP:3000"
NEXT_PUBLIC_BASE_URL = "https://loan.witel.ir"
diff --git a/next.config.js b/next.config.js
index 409876a..a288e34 100644
--- a/next.config.js
+++ b/next.config.js
@@ -6,7 +6,7 @@ const nextConfig = {
defaultLocale: 'fa',
locales: ['fa'],
localeDetection: false,
- },
+ }
}
module.exports = nextConfig
diff --git a/public/icons/favicon.png b/public/icons/favicon.png
new file mode 100644
index 0000000..c82bf9a
Binary files /dev/null and b/public/icons/favicon.png differ
diff --git a/public/images/403.svg b/public/images/403.svg
new file mode 100644
index 0000000..d5ab3a5
--- /dev/null
+++ b/public/images/403.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/images/404.svg b/public/images/404.svg
new file mode 100644
index 0000000..2383041
--- /dev/null
+++ b/public/images/404.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/images/500.svg b/public/images/500.svg
new file mode 100644
index 0000000..c7629f3
--- /dev/null
+++ b/public/images/500.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json
index 50c92c0..9bca403 100644
--- a/public/locales/fa/app.json
+++ b/public/locales/fa/app.json
@@ -20,7 +20,10 @@
},
"Titles": {
"title_login_page": "صفحه ورود",
- "title_login_expert_page": "ورود کارشناس"
+ "title_login_expert_page": "ورود کارشناس",
+ "title_custom_404": "صفحه یافت نشد",
+ "title_custom_403": "عدم دسترسی",
+ "title_custom_500": "خطای سرور"
},
"sidebar": {
"dashboard": "داشبورد",
@@ -58,6 +61,14 @@
"link_routing_main_page": "صفحه اصلی",
"error_message_required": "اجباری!"
},
+ "ErrorPage": {
+ "custom_404": "صفحه مورد نظر یافت نشد | 404",
+ "custom_500": "دسترسی به سامانه امکانپذیر نمی باشد دقایقی دیگر تلاش نمائید | 500",
+ "custom_403": "شما دسترسی به این بخش را ندارید | 403",
+ "link_routing_back_to": "بازگشت به",
+ "link_routing_previuos_page": "صفحه قبل",
+ "link_routing_main_page": "صفحه اصلی"
+ },
"Dashboard": {
"dashboard_page": "داشبورد",
"passenger_boss_page": "رئیس مسافر",
diff --git a/public/manifest.json b/public/manifest.json
new file mode 100644
index 0000000..6bc19ce
--- /dev/null
+++ b/public/manifest.json
@@ -0,0 +1,57 @@
+{
+ "short_name": "Loan Facilities Dashboard",
+ "name": "Loan Facilities Expert Dashboard",
+ "description": "Loan Facilities",
+ "version": "1.0.0",
+ "version_name": "1.0.0 beta",
+ "start_url": "/dashboard",
+ "orientation": "portrait",
+ "display": "standalone",
+ "theme_color": "#084070",
+ "background_color": "#084070",
+ "icons": [
+ {
+ "src": "/icons/maskable_icon.png",
+ "sizes": "any",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x48.png",
+ "sizes": "48x48",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x72.png",
+ "sizes": "72x72",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x96.png",
+ "sizes": "96x96",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x128.png",
+ "sizes": "128x128",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x384.png",
+ "sizes": "384x384",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "categories": [
+ "government"
+ ]
+}
diff --git a/src/components/dashboard/change-password/index.jsx b/src/components/dashboard/change-password/index.jsx
index 9a9c128..fac3c15 100644
--- a/src/components/dashboard/change-password/index.jsx
+++ b/src/components/dashboard/change-password/index.jsx
@@ -90,7 +90,7 @@ const DashboardChangePasswordComponent = () => {
-
+
{t("ChangePassword.typography_change_password")}
diff --git a/src/components/errors/403.jsx b/src/components/errors/403.jsx
new file mode 100644
index 0000000..cf46e41
--- /dev/null
+++ b/src/components/errors/403.jsx
@@ -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 UnAuthorizedComponent = () => {
+ const t = useTranslations();
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {t("ErrorPage.custom_403")}
+
+
+
+
+
+
+ >
+ );
+};
+
+export default UnAuthorizedComponent;
diff --git a/src/components/errors/404.jsx b/src/components/errors/404.jsx
new file mode 100644
index 0000000..e0888b3
--- /dev/null
+++ b/src/components/errors/404.jsx
@@ -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 NotFoundComponent = () => {
+ const t = useTranslations();
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {t("ErrorPage.custom_404")}
+
+
+
+
+
+
+ >
+ );
+};
+
+export default NotFoundComponent;
diff --git a/src/components/errors/500.jsx b/src/components/errors/500.jsx
new file mode 100644
index 0000000..10e9d12
--- /dev/null
+++ b/src/components/errors/500.jsx
@@ -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 (
+ <>
+
+
+
+
+
+
+
+
+
+ {t("ErrorPage.custom_500")}
+
+
+
+
+
+
+ >
+ );
+};
+
+export default ServerErrorComponent;
diff --git a/src/components/login-expert/index.jsx b/src/components/login-expert/index.jsx
index aa79bac..293f9f9 100644
--- a/src/components/login-expert/index.jsx
+++ b/src/components/login-expert/index.jsx
@@ -27,100 +27,125 @@ const LoginComponent = () => {
//formik properties
const handleSubmit = async (values, props) => {
- Notifications(directionApp, t);
await axios
.post(GET_USER_TOKEN, {
- username: values.username, password: values.password,
+ username: values.username,
+ password: values.password,
})
.then(function (response) {
setToken(response.data.token);
})
.catch(function (error) {
- Notifications(directionApp, t, error.response);
+ Notifications(directionApp, error.response, t);
props.setSubmitting(false);
});
};
const initialValues = {
- username: "", password: "",
+ 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 (
-
-
-
-
- {(props) => (
-
-
-
-
- {t("login_expert")}
-
-
-
-
-
+ return (
+
+
+
+
+
+ {(props) => (
+
-
+
+
+ {t("login_expert")}
+
+
+
+
+
+
+
+
+
+
-
- )}
-
-
-
-
-
-
- {t("LoginPage.link_routing_back_to")}{" "}
- {backUrlDecodedPath ? t("LoginPage.link_routing_previuos_page") : t("LoginPage.link_routing_main_page")}
-
-
- );
+ )}
+
+
+
+
+
+
+ {t("LoginPage.link_routing_back_to")}{" "}
+ {backUrlDecodedPath
+ ? t("LoginPage.link_routing_previuos_page")
+ : t("LoginPage.link_routing_main_page")}
+
+
+
+ );
};
export default LoginComponent;
diff --git a/src/core/utils/theme.jsx b/src/core/utils/theme.jsx
index 1679552..0ded0d2 100644
--- a/src/core/utils/theme.jsx
+++ b/src/core/utils/theme.jsx
@@ -3,16 +3,16 @@ import {faIR} from "@mui/x-date-pickers/locales";
const theme = {
palette: {
primary: {
- main: "#084070",
- contrastText: "#fff",
- light: "#2c6291",
- dark: "#11293e",
+ main: process.env.NEXT_PUBLIC_PRIMARY_MAIN,
+ contrastText: process.env.NEXT_PUBLIC_PRIMARY_CONTRAST_TEXT,
+ light: process.env.NEXT_PUBLIC_PRIMARY_LIGHT,
+ dark: process.env.NEXT_PUBLIC_PRIMARY_DARK,
},
secondary: {
- main: "#FF4E00",
- contrastText: "#fff",
- light: "#ed743e",
- dark: "#ad3a07",
+ main: process.env.NEXT_PUBLIC_SECONDARY_MAIN,
+ contrastText: process.env.NEXT_PUBLIC_SECENDARY_CONTRAST_TEXT,
+ light: process.env.NEXT_PUBLIC_SECENDARY_LIGHT,
+ dark: process.env.NEXT_PUBLIC_SECENDARY_DARK,
},
},
faIR,
diff --git a/src/layouts/AppLayout.jsx b/src/layouts/AppLayout.jsx
index d0f26d7..c86d1f2 100644
--- a/src/layouts/AppLayout.jsx
+++ b/src/layouts/AppLayout.jsx
@@ -83,13 +83,13 @@ function AppLayout({children, isBot}) {
rel="icon"
type="image/svg"
sizes="32x32"
- href="/images/logo.png"
+ href="/icons/favicon.png"
/>
{
+ const {user} = useUser()
const t = useTranslations();
return (
<>
@@ -12,10 +14,7 @@ const SidebarDrawer = ({handleDrawerToggle}) => {
{t("app_short_name")}
- {
- t("expert") /* make if on thease t("user_welfare_services")
- t("user_navy") */
- }
+ {user.name} | {user.position}
diff --git a/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx b/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx
index f14ae1d..616ecb5 100644
--- a/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx
+++ b/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx
@@ -1,7 +1,7 @@
import {NextLinkComposed} from "@/core/components/LinkRouting";
import ExpandLess from "@mui/icons-material/ExpandLess";
import ExpandMore from "@mui/icons-material/ExpandMore";
-import {Badge, ListItem, ListItemButton, ListItemIcon, ListItemText, Typography,} from "@mui/material";
+import {Badge, IconButton, ListItem, ListItemButton, ListItemIcon, ListItemText, Typography,} from "@mui/material";
import {useTranslations} from "next-intl";
import {Fragment} from "react";
import SidebarListSubItem from "./SidebarListSubItem";
@@ -11,7 +11,19 @@ const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
return (
-
+
+
+
+ }>
{
sx={{
minHeight: 48,
}}
+
>
{
}
/>
+
{item.type == "menu" &&
(item.showSubItem ? : )}
-
{item.subItem && (
diff --git a/src/pages/403.jsx b/src/pages/403.jsx
new file mode 100644
index 0000000..15ba915
--- /dev/null
+++ b/src/pages/403.jsx
@@ -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 (
+
+
+
+ );
+}
diff --git a/src/pages/404.jsx b/src/pages/404.jsx
new file mode 100644
index 0000000..26de038
--- /dev/null
+++ b/src/pages/404.jsx
@@ -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 (
+
+
+
+ );
+}
diff --git a/src/pages/500.jsx b/src/pages/500.jsx
new file mode 100644
index 0000000..4b85bc2
--- /dev/null
+++ b/src/pages/500.jsx
@@ -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 (
+
+
+
+ );
+}
diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx
index 85b03cd..29ec464 100644
--- a/src/pages/_app.jsx
+++ b/src/pages/_app.jsx
@@ -9,13 +9,14 @@ import {NextIntlProvider} from "next-intl";
import TitlePage from "@/core/components/TitlePage";
const App = ({Component, pageProps}) => {
+
return (
<>
-
+
-
+ {pageProps.messages ? : ''}
diff --git a/src/pages/_document.jsx b/src/pages/_document.jsx
index c9c28bb..474e29b 100644
--- a/src/pages/_document.jsx
+++ b/src/pages/_document.jsx
@@ -11,7 +11,7 @@ export default function MyDocument(props) {
-
+
{emotionStyleTags}