diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json
index 60890a7..4450c55 100644
--- a/public/locales/fa/app.json
+++ b/public/locales/fa/app.json
@@ -23,7 +23,8 @@
"passenger-boss": "رئیس مسافر",
"transportation-assistance": "معاونت حمل و نقل",
"manager": "مدیر کل",
- "change-password": "تغییر رمز عبور"
+ "change-password": "تغییر رمز عبور",
+ "edit-profile": "ویرایش پروفایل"
},
"Authorization": {
"typography_your_login_is_valid_and_you_do_not_need_to_login_again": "شما دسترسی لازم به این صفحه را دارید نیاز به ورود مجدد نیست.",
@@ -45,8 +46,13 @@
},
"Dashboard": {
"dashboard_page": "داشبورد",
+<<<<<<< HEAD
"passenger_boss": "رئیس مسافر",
"change_password": "تغییر رمز عبور"
+=======
+ "change_password": "تغییر رمز عبور",
+ "edit_profile": "ویرایش پروفایل"
+>>>>>>> 135f6d1e2f3495abe68e3ca758870023dcd85d76
},
"MuiDatePicker": {
"date_picker_birthday": "تاریخ"
@@ -64,5 +70,27 @@
"SubmitButton": {
"button_while_submit": "در حال ثبت",
"button_submit": "ثبت"
+ },
+ "UpdateProfile": {
+ "error_invalid_email": "ایمیل نامعتبر است",
+ "typography_edit_profile": "ویرایش پروفایل",
+ "text_field_email": "ایمیل",
+ "text_field_enter_your_password": "رمز عبور خود را وارد کنید",
+ "text_field_username": "نام کاربری",
+ "text_field_name": "نام",
+ "text_field_phone_number": "شماره تماس",
+ "text_field_position": "سمت",
+ "text_field_province_name": "نام استان",
+ "error_message_required": "اجباری !"
+ },
+ "notifications": {
+ "code": "کد",
+ "error": "خطا",
+ "warning": "خطر",
+ "success": "موفق",
+ "error_static_text": "عملیات شما با خطا مواجه شد",
+ "warning_static_text": "خطا سرور",
+ "success_static_text": "عملیات شما با موفقیت انجام شد",
+ "pending": "در حال انجام..."
}
}
diff --git a/src/components/dashboard/change-password/index.jsx b/src/components/dashboard/change-password/index.jsx
index 62d6fe3..c2b5fd4 100644
--- a/src/components/dashboard/change-password/index.jsx
+++ b/src/components/dashboard/change-password/index.jsx
@@ -28,7 +28,7 @@ const DashboardChangePasswordComponent = () => {
const handleSubmit = (values, { setSubmitting, resetForm }) => {
toast.dismiss();
- const pendingToast = toast("Pending...", {
+ const pendingToast = toast(t("notifications.pending"), {
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
diff --git a/src/components/dashboard/edit-profile/index.jsx b/src/components/dashboard/edit-profile/index.jsx
new file mode 100644
index 0000000..fa3e2e1
--- /dev/null
+++ b/src/components/dashboard/edit-profile/index.jsx
@@ -0,0 +1,299 @@
+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,
+ Button,
+ 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_PROFILE, 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();
+ console.log(user);
+ const { directionApp } = useDirection();
+
+ const editAvatar = async (avatar) => {
+ 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(directionApp, error.response, t);
+ throw error;
+ }
+ };
+ const handleSubmit = (values, { setSubmitting }) => {
+ // const formData = new FormData();
+ // formData.append("email", values.expert_email);
+ // if (values.change_avatar !== false) {
+ // editAvatar(values.expert_avatar)
+ // .then(() => {
+ // return axios.post(UPDATE_PROFILE, formData, {
+ // headers: {
+ // authorization: `Bearer ${token}`,
+ // "Content-Type": "multipart/form-data",
+ // },
+ // });
+ // })
+ // .then((response) => {
+ // Notifications(directionApp, response, t);
+ // getUser((data) => {
+ // changeUser(data);
+ // });
+ // })
+ // .catch((error) => {
+ // Notifications(directionApp, error.response, t);
+ // })
+ // .finally(() => {
+ // setSubmitting(false);
+ // });
+ // } else {
+ // axios
+ // .post(UPDATE_PROFILE, formData, {
+ // headers: {
+ // authorization: `Bearer ${token}`,
+ // "Content-Type": "multipart/form-data",
+ // },
+ // })
+ // .then((response) => {
+ // Notifications(directionApp, response, t);
+ // getUser((data) => {
+ // changeUser(data);
+ // });
+ // })
+ // .catch((error) => {
+ // Notifications(directionApp, error.response, t);
+ // })
+ // .finally(() => {
+ // setSubmitting(false);
+ // });
+ // }
+ };
+ 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({
+ // username: Yup.string().required(t("UpdateProfile.error_message_required")),
+ // name: Yup.string().required(t("UpdateProfile.error_message_required")),
+ // email: Yup.string()
+ // .email(t("UpdateProfile.error_invalid_email"))
+ // .required(t("UpdateProfile.error_message_required")),
+ // province_name: Yup.string().required(
+ // t("UpdateProfile.error_message_required")
+ // ),
+ // position: Yup.string().required(t("UpdateProfile.error_message_required")),
+ });
+
+ return (
+
+
+
+
+ {(props) => (
+ {
+ e.preventDefault();
+ props.handleSubmit();
+ }}
+ >
+
+
+
+ {t("UpdateProfile.typography_edit_profile")}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* */}
+
+
+
+ )}
+
+
+
+
+ );
+};
+
+export default DashboardEditProfile;
diff --git a/src/components/login-expert/index.jsx b/src/components/login-expert/index.jsx
index 65b1e1c..bcc3b1a 100644
--- a/src/components/login-expert/index.jsx
+++ b/src/components/login-expert/index.jsx
@@ -2,7 +2,7 @@ import LinkRouting from "@/core/components/LinkRouting";
// import Notifications from "@/core/components/notifications";
import PasswordField from "@/core/components/PasswordField";
import StyledForm from "@/core/components/StyledForm";
-// import { GET_USER_TOKEN } from "@/core/data/apiRoutes";
+import { GET_USER_TOKEN } from "@/core/data/apiRoutes";
import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
import useDirection from "@/lib/app/hooks/useDirection";
@@ -17,7 +17,7 @@ import {
TextField,
Typography,
} from "@mui/material";
-// import axios from "axios";
+import axios from "axios";
import { Field, Formik } from "formik";
import { useTranslations } from "next-intl";
import Image from "next/image";
@@ -33,21 +33,23 @@ const LoginComponent = () => {
const searchParams = useSearchParams();
const backUrlDecodedPath = searchParams.get("back_url");
- // formik properties
- // const handleSubmit = async (values, props) => {
- // await axios
- // .post(GET_USER_TOKEN, {
- // username: values.username,
- // password: values.password,
- // })
- // .then(function (response) {
- // setToken(response.data.token);
- // })
- // .catch(function (error) {
- // Notifications(directionApp, error.response, t);
- // props.setSubmitting(false);
- // });
- // };
+ //formik properties
+ const handleSubmit = async (values, props) => {
+ await axios
+ .post(GET_USER_TOKEN, {
+ username: values.username,
+ password: values.password,
+ })
+ .then(function (response) {
+ console.log(response);
+ setToken(response.data.token);
+ })
+ .catch(function (error) {
+ // Notifications(directionApp, error.response, t);
+ console.log(error);
+ props.setSubmitting(false);
+ });
+ };
const initialValues = {
username: "",
password: "",
@@ -64,7 +66,7 @@ const LoginComponent = () => {
{(props) => (
diff --git a/src/core/components/AvatarUpload.jsx b/src/core/components/AvatarUpload.jsx
new file mode 100644
index 0000000..e1ade5c
--- /dev/null
+++ b/src/core/components/AvatarUpload.jsx
@@ -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 (
+
+
+
+
+ {isHovered && (
+
+ {selectedImage ? (
+
+ ) : (
+
+ )}
+
+ )}
+
+
+
+
+ );
+};
+
+export default AvatarUpload;
diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js
index 0877232..1b299cc 100644
--- a/src/core/data/apiRoutes.js
+++ b/src/core/data/apiRoutes.js
@@ -1,6 +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 CHANGE_PASSWORD =
- BASE_URL + "/dashboard/profile/change_password";
-//end change password
\ No newline at end of file
+export const CHANGE_PASSWORD = BASE_URL + "/dashboard/profile/change_password";
+//end change password
+
+//user data
+export const GET_USER_ROUTE = BASE_URL + "/dashboard/profile/info";
+//user data
\ No newline at end of file
diff --git a/src/lib/app/contexts/user.jsx b/src/lib/app/contexts/user.jsx
index 49d55af..30875d9 100644
--- a/src/lib/app/contexts/user.jsx
+++ b/src/lib/app/contexts/user.jsx
@@ -51,27 +51,7 @@ export const UserProvider = ({ children }) => {
dispatch({ type: "CHANGE_USER", user });
}, []);
- const changeUserLanguage = useCallback(
- (language) => {
- dispatch({ type: "CHANGE_USER_LANGUAGE", language });
- axios
- .post(
- SET_LANGUAGE,
- { language: language },
- {
- headers: {
- authorization: `Bearer ${state.token}`,
- },
- }
- )
- .then(() => {
- getUser((data) => {
- changeUser(data);
- });
- });
- },
- [state.token]
- );
+ const changeUserLanguage = useCallback(/* use in multi language app */);
const changeAuthState = useCallback((isAuth) => {
dispatch({ type: "CHANGE_AUTH_STATE", isAuth });
diff --git a/src/lib/app/hooks/useUser.jsx b/src/lib/app/hooks/useUser.jsx
index baa0aaa..56bdf7c 100644
--- a/src/lib/app/hooks/useUser.jsx
+++ b/src/lib/app/hooks/useUser.jsx
@@ -10,7 +10,6 @@ const useUser = () => {
getUser,
clearUser,
changeUser,
- changeUserLanguage,
changeAuthState,
changeLanguageState,
clearToken,
@@ -25,7 +24,6 @@ const useUser = () => {
getUser,
clearUser,
changeUser,
- changeUserLanguage,
changeAuthState,
changeLanguageState,
clearToken,
diff --git a/src/middlewares/WithAuth.jsx b/src/middlewares/WithAuth.jsx
index d158bf3..3fa5f43 100644
--- a/src/middlewares/WithAuth.jsx
+++ b/src/middlewares/WithAuth.jsx
@@ -16,7 +16,7 @@ const WithAuthMiddleware = ({ children }) => {
text={
{t(
- "typography_your_access_to_this_page_has_expired_Please_login_again"
+ "Authorization.typography_your_access_to_this_page_has_expired_Please_login_again"
)}
}
@@ -26,7 +26,7 @@ const WithAuthMiddleware = ({ children }) => {
variant="contained"
component={NextLinkComposed}
to={{
- pathname: "/login",
+ pathname: "/login-expert",
query: { back_url: encodeURIComponent(router.asPath) },
}}
>
diff --git a/src/middlewares/WithoutAuth.jsx b/src/middlewares/WithoutAuth.jsx
index 5fb4f93..cb8e571 100644
--- a/src/middlewares/WithoutAuth.jsx
+++ b/src/middlewares/WithoutAuth.jsx
@@ -37,14 +37,14 @@ const WithoutAuthMiddleware = ({ children }) => {
{t(
- "typography_your_login_is_valid_and_you_do_not_need_to_login_again"
+ "Authorization.typography_your_login_is_valid_and_you_do_not_need_to_login_again"
)}
- {t("typography_redirect_to")}{" "}
+ {t("Authorization.typography_redirect_to")}{" "}
{backUrlDecodedPath
- ? t("typography_routing_previuos_page")
- : t("typography_routing_dashbaord_page")}
+ ? t("Authorization.typography_routing_previuos_page")
+ : t("Authorization.typography_routing_dashbaord_page")}
}
diff --git a/src/pages/dashboard/change-password/index.jsx b/src/pages/dashboard/change-password/index.jsx
index 85660ff..30685f1 100644
--- a/src/pages/dashboard/change-password/index.jsx
+++ b/src/pages/dashboard/change-password/index.jsx
@@ -1,6 +1,6 @@
import DashboardChangePasswordComponent from "@/components/dashboard/change-password";
import TitlePage from "@/core/components/TitlePage";
-import WithAuthMiddleware from "@/middlewares/WithoutAuth";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
import { parse } from "next-useragent";
export default function LoanFollowUp() {
diff --git a/src/pages/dashboard/edit-profile/index.jsx b/src/pages/dashboard/edit-profile/index.jsx
new file mode 100644
index 0000000..0adabf6
--- /dev/null
+++ b/src/pages/dashboard/edit-profile/index.jsx
@@ -0,0 +1,23 @@
+import DashboardEditProfile from "@/components/dashboard/edit-profile";
+import TitlePage from "@/core/components/TitlePage";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import { parse } from "next-useragent";
+
+export default function LoanFollowUp() {
+ return (
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({ req, locale }) {
+ const { isBot } = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/index.jsx b/src/pages/dashboard/index.jsx
index 5ebc479..c3c3933 100644
--- a/src/pages/dashboard/index.jsx
+++ b/src/pages/dashboard/index.jsx
@@ -1,12 +1,12 @@
import DashboardFirstComponent from "@/components/dashboard/first";
import TitlePage from "@/core/components/TitlePage";
-import WithAuthMiddleware from "@/middlewares/WithoutAuth";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
import { parse } from "next-useragent";
export default function Dashboard() {
return (
-
+
);
diff --git a/src/pages/dashboard/loan-follow-up/index.jsx b/src/pages/dashboard/loan-follow-up/index.jsx
index fc299c4..6bab35f 100644
--- a/src/pages/dashboard/loan-follow-up/index.jsx
+++ b/src/pages/dashboard/loan-follow-up/index.jsx
@@ -6,7 +6,7 @@ import { parse } from "next-useragent";
export default function LoanFollowUp() {
return (
-
+
);
diff --git a/src/pages/dashboard/loan-request/index.jsx b/src/pages/dashboard/loan-request/index.jsx
index b76f172..ad64ce8 100644
--- a/src/pages/dashboard/loan-request/index.jsx
+++ b/src/pages/dashboard/loan-request/index.jsx
@@ -6,7 +6,7 @@ import { parse } from "next-useragent";
export default function LoanRequest() {
return (
-
+
);