diff --git a/frontend/src/components/ProfileSideBar.vue b/frontend/src/components/ProfileSideBar.vue new file mode 100644 index 0000000..3fbca75 --- /dev/null +++ b/frontend/src/components/ProfileSideBar.vue @@ -0,0 +1,74 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/components/TheHeader.vue b/frontend/src/components/TheHeader.vue index 27a4ee9..bb1a1af 100644 --- a/frontend/src/components/TheHeader.vue +++ b/frontend/src/components/TheHeader.vue @@ -19,7 +19,7 @@ export default { }, methods: { - openProfile() { + openLogin() { this.showLoginModal = true }, logout() { @@ -47,11 +47,11 @@ export default {
- + + profile + diff --git a/frontend/src/js/router.js b/frontend/src/js/router.js index 3c16e8e..7afeb9b 100644 --- a/frontend/src/js/router.js +++ b/frontend/src/js/router.js @@ -1,6 +1,6 @@ import { createRouter, createWebHistory } from 'vue-router' -import {isUserAdmin} from "@/services/authService.js"; +import {isUserAdmin, isUserAuthenticated} from "@/services/authService.js"; import HomeView from '@/views/HomeView.vue' import AdminOrders from "@/views/admin/AdminOrders.vue"; import AdminEmployees from "@/views/admin/AdminEmployees.vue"; @@ -9,6 +9,10 @@ import AdminReviews from "@/views/admin/AdminReviews.vue"; import AdminStatistics from "@/views/admin/AdminStatistics.vue"; import AdminTools from "@/views/admin/AdminTools.vue"; import AdminCategories from "@/views/admin/AdminCategories.vue"; +import ProfileView from "@/views/profile/ProfileView.vue"; +import MyRents from "@/views/profile/MyRents.vue"; +import EditProfile from "@/views/profile/EditProfile.vue"; +import ChangePassword from "@/views/profile/ChangePassword.vue"; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -74,6 +78,38 @@ const router = createRouter({ requiresAdmin: true, }, }, + { + path: '/profile/dashboard', + name: 'profile-dashboard', + component: ProfileView, + meta: { + requiresLogin: true + } + }, + { + path: '/profile/rents', + name: 'profile-rents', + component: MyRents, + meta: { + requiresLogin: true + } + }, + { + path: '/profile/edit', + name: 'profile-edit', + component: EditProfile, + meta: { + requiresLogin: true + } + }, + { + path: '/profile/change-password', + name: 'profile-change-password', + component: ChangePassword, + meta: { + requiresLogin: true + } + }, ], }) @@ -83,6 +119,11 @@ router.beforeEach((to, from, next) => { } else { next(); } + if (to.meta.requiresLogin && !isUserAuthenticated()){ + next({ name: 'home' }); + } else { + next(); + } }); export default router diff --git a/frontend/src/services/authService.js b/frontend/src/services/authService.js index 16af6ad..eff49b8 100644 --- a/frontend/src/services/authService.js +++ b/frontend/src/services/authService.js @@ -47,8 +47,10 @@ export const storeUserInfo = (token) => { const decodedToken = jwtDecode(token); const isAdmin = (decodedToken.role === "worker") || false; const isAuthenticated = true; + const id = decodedToken.sub localStorage.setItem('isAdmin', isAdmin.toString()); + localStorage.setItem('id', id); localStorage.setItem('isAuthenticated', isAuthenticated.toString()); store.commit('login') } @@ -73,6 +75,10 @@ export const logoutUser = () => { localStorage.removeItem('access_token'); localStorage.removeItem('isAdmin'); localStorage.removeItem('isAuthenticated'); + localStorage.removeItem('id') + store.dispatch('logout').then(() => { + window.location.href = '/' + }) }; export const refreshToken = async () => { diff --git a/frontend/src/services/profileServices.js b/frontend/src/services/profileServices.js new file mode 100644 index 0000000..7a6e170 --- /dev/null +++ b/frontend/src/services/profileServices.js @@ -0,0 +1,56 @@ +import axios from 'axios'; +import { useToast } from 'vue-toastification' + +const toast = useToast() + +const API_URL = 'http://localhost:8000/api/clients'; + + +export const getProfileData = async (userData) => { + try{ + const response = await axios.get(`${API_URL}/${localStorage.getItem('id')}/private`); + return response.data + } catch (error) { + const errorMessage = error.response + ? error.response.data.message // Если есть ответ от сервера + : error.message || 'Ошибка соединения'; + toast.error(errorMessage) + return "ERROR" + } +}; + +export const updateProfileData = async (profileData) => { + try{ + const response = await axios.patch(`${API_URL}/${localStorage.getItem('id')}`, profileData, { + headers: { + 'Content-Type': 'application/json' + } + }); + toast.success("Данные успешно обновлены!") + return "SUCCESS" + } catch (error) { + const errorMessage = error.response + ? error.response.data.message // Если есть ответ от сервера + : error.message || 'Ошибка соединения'; + toast.error(errorMessage) + return "ERROR" + } +} + +export const changePassword = async (formData) => { + try{ + const response = await axios.patch(`${API_URL}/${localStorage.getItem('id')}/password`, formData, { + headers: { + 'Content-Type': 'application/json' + } + }); + toast.success("Пароль успешно обновлен!") + return "SUCCESS" + } catch (error) { + const errorMessage = error.response + ? error.response.data.message // Если есть ответ от сервера + : error.message || 'Ошибка соединения'; + toast.error(errorMessage) + return "ERROR" + } +} \ No newline at end of file diff --git a/frontend/src/views/HomeView.vue b/frontend/src/views/HomeView.vue index 321b540..d15aaae 100644 --- a/frontend/src/views/HomeView.vue +++ b/frontend/src/views/HomeView.vue @@ -14,7 +14,9 @@ export default{ }, beforeMount() { getAllCategories().then((res) => { - if (res === "ERROR") window.location.href = '/' + if (res === "ERROR") { + this.isLoading = false + } else { this.isLoading = false this.categories = res diff --git a/frontend/src/views/profile/ChangePassword.vue b/frontend/src/views/profile/ChangePassword.vue new file mode 100644 index 0000000..5ddb4a5 --- /dev/null +++ b/frontend/src/views/profile/ChangePassword.vue @@ -0,0 +1,138 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/views/profile/EditProfile.vue b/frontend/src/views/profile/EditProfile.vue new file mode 100644 index 0000000..7b7a841 --- /dev/null +++ b/frontend/src/views/profile/EditProfile.vue @@ -0,0 +1,215 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/views/profile/MyRents.vue b/frontend/src/views/profile/MyRents.vue new file mode 100644 index 0000000..8dd090b --- /dev/null +++ b/frontend/src/views/profile/MyRents.vue @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/views/profile/ProfileView.vue b/frontend/src/views/profile/ProfileView.vue new file mode 100644 index 0000000..0ff625e --- /dev/null +++ b/frontend/src/views/profile/ProfileView.vue @@ -0,0 +1,89 @@ + + + + + \ No newline at end of file