From 8684a35c6630ba66e6820ed90ea4047ec3927540 Mon Sep 17 00:00:00 2001 From: Diyar Akhgar Date: Sat, 28 Jun 2025 02:26:29 +0330 Subject: [PATCH] add alerts Design in loginsPages , ChangeAvatar , Edit Profile --- xroom-dashboard/src/assets/main.css | 19 + xroom-dashboard/src/main.js | 17 +- xroom-dashboard/src/pages/LoginPage.vue | 104 +++-- xroom-dashboard/src/pages/ResetPassword.vue | 111 +++++- xroom-dashboard/src/pages/SignupPage.vue | 83 +++- xroom-dashboard/src/pages/SmsVerification.vue | 297 ++++++++------ .../src/pages/dashboard/ChangeAvatar.vue | 362 ++++++++++++------ .../src/pages/dashboard/EditProfile.vue | 254 +++++++++--- xroom-dashboard/src/router/index.js | 4 +- 9 files changed, 898 insertions(+), 353 deletions(-) diff --git a/xroom-dashboard/src/assets/main.css b/xroom-dashboard/src/assets/main.css index e6c28a9..42ff861 100644 --- a/xroom-dashboard/src/assets/main.css +++ b/xroom-dashboard/src/assets/main.css @@ -41,4 +41,23 @@ button:focus-visible { a { text-decoration: none; +} + +/* sweet alert */ + +.swal2-popup { + right: 1rem !important; + top: 1rem !important; + display: flex !important; + align-items: center !important; + justify-content: right !important; + width: 95% !important; + padding-right: 0 !important; +} + +.swal2-title { + padding-right: 12px !important; + margin-right: 0 !important; + color: #101010 !important; + text-align: right !important; } \ No newline at end of file diff --git a/xroom-dashboard/src/main.js b/xroom-dashboard/src/main.js index 49aabb8..5f44f82 100644 --- a/xroom-dashboard/src/main.js +++ b/xroom-dashboard/src/main.js @@ -1,8 +1,11 @@ -import { createApp } from 'vue' -import App from './App.vue' -import router from './router' -import '@/assets/main.css' +// src/main.js +import { createApp } from 'vue'; +import App from './App.vue'; +import router from './router'; +import Swal from 'sweetalert2'; +import '@/assets/main.css'; -createApp(App) - .use(router) // Make sure you use the router here - .mount('#app') +const app = createApp(App); +app.use(router); +app.config.globalProperties.$swal = Swal; // Add SweetAlert2 globally +app.mount('#app'); \ No newline at end of file diff --git a/xroom-dashboard/src/pages/LoginPage.vue b/xroom-dashboard/src/pages/LoginPage.vue index 9f24767..bd9ae85 100644 --- a/xroom-dashboard/src/pages/LoginPage.vue +++ b/xroom-dashboard/src/pages/LoginPage.vue @@ -7,10 +7,6 @@

ورود به حساب کاربری

- - - -
@@ -23,10 +19,9 @@
- -
@@ -34,7 +29,7 @@ - + @@ -42,8 +37,8 @@ - diff --git a/xroom-dashboard/src/pages/ResetPassword.vue b/xroom-dashboard/src/pages/ResetPassword.vue index 4a10218..b987ee5 100644 --- a/xroom-dashboard/src/pages/ResetPassword.vue +++ b/xroom-dashboard/src/pages/ResetPassword.vue @@ -7,7 +7,7 @@

فراموشی رمز عبور

- رمز عبور خود را فراموش کرده اید؟ شماره موبایل خود را وارد کنید تا کد تأیید برای شما ارسال شود. + رمز عبور خود را فراموش کرده‌اید؟ شماره موبایل خود را وارد کنید تا کد تأیید برای شما ارسال شود.
@@ -63,7 +63,6 @@ - + + + \ No newline at end of file diff --git a/xroom-dashboard/src/pages/dashboard/EditProfile.vue b/xroom-dashboard/src/pages/dashboard/EditProfile.vue index 7f7241a..c42d1f3 100644 --- a/xroom-dashboard/src/pages/dashboard/EditProfile.vue +++ b/xroom-dashboard/src/pages/dashboard/EditProfile.vue @@ -1,13 +1,7 @@ @@ -152,85 +135,239 @@ export default { return { selectedProfileImage: null, userData: { - user: { first_name: '', last_name: '', email: '', semat: '' } + customer: { semat: '', profile_img: '' }, + user: { first_name: '', last_name: '' }, }, - editForm: { full_name: '', email: '', semat: '' }, // جایگزینی first_name و last_name با full_name + editForm: { first_name: '', last_name: '', email: '', semat: '' }, passwordForm: { current_password: '', new_password: '', confirm_password: '' }, + initialFormState: { first_name: '', last_name: '', semat: '' }, saving: false, userAvatarUrl: 'https://i.imgur.com/QbXfV6C.png', - baseUrl: 'http://194.62.43.230:8000' - } + baseUrl: 'http://194.62.43.230:8000', + }; }, created() { this.fetchUserData(); }, computed: { userProfilePicUrl() { - const customer = JSON.parse(localStorage.getItem('customer') || {}); - if (!customer.profile_img) return this.defaultProfileImage; - return `${customer.profile_img}`; - } + // Prioritize userData from API if available + if (this.userData.customer && this.userData.customer.profile_img) { + return this.userData.customer.profile_img; + } + // Fallback to localStorage + const customer = JSON.parse(localStorage.getItem('customer') || '{}'); + return customer.profile_img || this.userAvatarUrl; + }, }, methods: { async fetchUserData() { + const Toast = this.$swal.mixin({ + toast: true, + position: 'top-end', + showConfirmButton: false, + timer: 3000, + timerProgressBar: true, + didOpen: (toast) => { + toast.onmouseenter = this.$swal.stopTimer; + toast.onmouseleave = this.$swal.resumeTimer; + }, + }); + try { const response = await axios.get('/getInfo'); - this.userData = response.data; + + // Check if response.data and required fields exist + if (!response.data || !response.data.data) { + throw new Error('داده‌های پاسخ از سرور معتبر نیست'); + } + + const userData = response.data.data; // Adjust to match the nested 'data' structure + if (!userData.user || !userData.customer) { + throw new Error('داده‌های کاربر یا مشتری در پاسخ سرور وجود ندارد'); + } + + this.userData = userData; this.editForm = { - full_name: `${response.data.user.first_name} ${response.data.user.last_name}`.trim(), // ترکیب نام و نام خانوادگی - email: response.data.user.email, - semat: response.data.user.semat, - userAvatarUrl: response.data.customer.profile_img + first_name: userData.user.first_name || '', + last_name: userData.user.last_name || '', + email: userData.user.email || '', + semat: userData.customer.semat || '', }; + this.initialFormState = { + first_name: this.editForm.first_name, + last_name: this.editForm.last_name, + semat: this.editForm.semat, + }; + + // Update localStorage to keep it in sync with the API response + localStorage.setItem('customer', JSON.stringify(userData.customer)); } catch (error) { + Toast.fire({ + icon: 'error', + title: 'خطا در بارگذاری اطلاعات کاربر. لطفاً دوباره تلاش کنید', + }); console.error('Error fetching user data:', error); - } + // Initialize with default values to prevent breaking the UI + this.editForm = { + first_name: '', + last_name: '', + email: '', + semat: '', + }; + this.initialFormState = { + first_name: '', + last_name: '', + semat: '', + }; + } }, async saveProfile() { + const Toast = this.$swal.mixin({ + toast: true, + position: 'top-end', + showConfirmButton: false, + timer: 3000, + timerProgressBar: true, + didOpen: (toast) => { + toast.onmouseenter = this.$swal.stopTimer; + toast.onmouseleave = this.$swal.resumeTimer; + }, + }); + this.saving = true; + let isProfileChanged = false; + let isPasswordChanged = false; + let onlyNameChanged = false; + try { const formData = new FormData(); - // تجزیه full_name به first_name و last_name (اگر API نیاز دارد) - const [first_name = '', last_name = ''] = this.editForm.full_name.split(' ').filter(Boolean); - formData.append('first_name', first_name); - formData.append('last_name', last_name); - formData.append('semat', this.editForm.semat); + + if (this.editForm.first_name !== this.initialFormState.first_name || this.editForm.last_name !== this.initialFormState.last_name) { + formData.append('first_name', this.editForm.first_name); + formData.append('last_name', this.editForm.last_name); + isProfileChanged = true; + onlyNameChanged = true; + } + + if (this.editForm.semat !== this.initialFormState.semat) { + formData.append('semat', this.editForm.semat); + isProfileChanged = true; + onlyNameChanged = false; + } if (this.selectedProfileImage) { formData.append('profile_img', this.selectedProfileImage); + isProfileChanged = true; + onlyNameChanged = false; } - await axios.post(`${this.baseUrl}/editProfile/`, formData, { - headers: { - 'Content-Type': 'multipart/form-data' - } - }); + if (isProfileChanged) { + await axios.post(`${this.baseUrl}/editProfile/`, formData, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }); + } - // Handle password change if filled - if (this.passwordForm.new_password && this.passwordForm.current_password) { + if (this.passwordForm.current_password && this.passwordForm.new_password) { if (this.passwordForm.new_password !== this.passwordForm.confirm_password) { - throw new Error('رمز عبور جدید و تکرار آن مطابقت ندارند'); + Toast.fire({ + icon: 'error', + title: 'رمز عبور جدید و تکرار آن مطابقت ندارند', + }); + this.saving = false; + return; } await axios.post(`${this.baseUrl}/resetPassword/`, { old_password: this.passwordForm.current_password, - new_password: this.passwordForm.new_password + new_password: this.passwordForm.new_password, }); + isPasswordChanged = true; + onlyNameChanged = false; + } + + if (!isProfileChanged && !isPasswordChanged) { + Toast.fire({ + icon: 'info', + title: 'هیچ تغییری اعمال نشده است', + }); + this.saving = false; + return; } await this.fetchUserData(); - alert('تغییرات با موفقیت ذخیره شد'); + this.passwordForm = { current_password: '', new_password: '', confirm_password: '' }; + this.editForm.first_name = ''; + this.editForm.last_name = ''; + this.editForm.semat = ''; + this.selectedProfileImage = null; + + Toast.fire({ + icon: 'success', + title: 'تغییرات با موفقیت ذخیره شد', + }); + + if (onlyNameChanged) { + window.location.reload(); + } } catch (error) { - alert(error.response?.data?.detail || error.message || 'خطا در ذخیره تغییرات'); + let errorMessage = 'خطا در ذخیره تغییرات'; + if (error.response) { + if (error.response.status === 400) { + errorMessage = 'اطلاعات ورودی نامعتبر است'; + } else if (error.response.status === 401) { + errorMessage = 'رمز عبور فعلی اشتباه است'; + } else { + errorMessage = error.response.data.detail || errorMessage; + } + } else if (error.request) { + errorMessage = 'مشکل در ارتباط با سرور، لطفاً دوباره تلاش کنید'; + } + + Toast.fire({ + icon: 'error', + title: errorMessage, + }); + console.error('Error saving profile:', error); } finally { this.saving = false; } }, changeAvatar() { - alert('تغییر آواتار کلیک شد'); + const Toast = this.$swal.mixin({ + toast: true, + position: 'top-end', + showConfirmButton: false, + timer: 3000, + timerProgressBar: true, + didOpen: (toast) => { + toast.onmouseenter = this.$swal.stopTimer; + toast.onmouseleave = this.$swal.resumeTimer; + }, + }); + Toast.fire({ + icon: 'info', + title: 'تغییر آواتار کلیک شد', + }); }, regenerateAvatar() { - alert('ساخت مجدد آواتار کلیک شد'); + const Toast = this.$swal.mixin({ + toast: true, + position: 'top-end', + showConfirmButton: false, + timer: 3000, + timerProgressBar: true, + didOpen: (toast) => { + toast.onmouseenter = this.$swal.stopTimer; + toast.onmouseleave = this.$swal.resumeTimer; + }, + }); + Toast.fire({ + icon: 'info', + title: 'ساخت مجدد آواتار کلیک شد', + }); }, uploadProfileImage(event) { const file = event.target.files[0]; @@ -238,11 +375,12 @@ export default { this.selectedProfileImage = file; this.userProfilePicUrl = URL.createObjectURL(file); } - } - } -} + }, + }, +}; +