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 @@ +server_cluster \ 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("app_name")} + + + {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("app_name")} + + + {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("app_name")} + + + {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("app_name")}/ - - - {t("login_expert")} - - - - - + return ( + + + + + + {(props) => ( + - + {t("app_name")}/ + + {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}