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 @@
ورود به حساب کاربری
@@ -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);
}
- }
- }
-}
+ },
+ },
+};
+