add sweetAlert2 for all Alerts in pages

This commit is contained in:
Diyar Akhgar 2025-06-29 02:36:05 +03:30
parent e8a4d5b597
commit dfcc5cb94c
21 changed files with 1041 additions and 389 deletions

View File

@ -102,63 +102,79 @@
</template>
<script>
export default {
name: 'AddUserModal',
props: {
isVisible: {
type: Boolean,
default: false,
},
},
data() {
return {
newUser: {
first_name: '',
last_name: '',
mobile_number: '',
password: '',
semat: '',
isAdmin: false,
export default {
name: 'AddUserModal',
props: {
isVisible: {
type: Boolean,
default: false,
},
};
},
watch: {
isVisible(newVal) {
if (newVal) {
// غیرفعال کردن اسکرول هنگام باز شدن پاپآپ
document.body.style.overflow = 'hidden';
} else {
// فعال کردن اسکرول هنگام بسته شدن پاپآپ
document.body.style.overflow = '';
}
},
},
methods: {
beforeDestroy() {
// اطمینان از فعال شدن اسکرول هنگام حذف کامپوننت
document.body.style.overflow = '';
},
close() {
this.newUser = {
first_name: '',
last_name: '',
mobile_number: '',
password: '',
semat: '',
isAdmin: false,
data() {
return {
newUser: {
first_name: '',
last_name: '',
mobile_number: '',
password: '',
semat: '',
isAdmin: false,
},
};
this.$emit('close');
},
handleSubmit() {
if (!this.newUser.first_name || !this.newUser.last_name || !this.newUser.mobile_number || !this.newUser.password || !this.newUser.semat) {
alert('لطفاً تمام فیلدها را پر کنید.');
return;
}
this.$emit('add-user', { ...this.newUser });
this.close();
watch: {
isVisible(newVal) {
if (newVal) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = '';
}
},
},
},
};
methods: {
beforeDestroy() {
document.body.style.overflow = '';
},
close() {
this.newUser = {
first_name: '',
last_name: '',
mobile_number: '',
password: '',
semat: '',
isAdmin: false,
};
this.$emit('close');
},
handleSubmit() {
// Define Toast configuration with SweetAlert2
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;
},
});
if (!this.newUser.first_name || !this.newUser.last_name || !this.newUser.mobile_number || !this.newUser.password || !this.newUser.semat) {
// Show error Toast for incomplete fields
Toast.fire({
icon: 'error',
title: 'لطفاً تمام فیلدها را پر کنید.',
});
return;
}
this.$emit('add-user', { ...this.newUser });
this.close();
},
},
};
</script>
<style scoped>

View File

@ -51,7 +51,7 @@
<span>مبلغ قابل پرداخت:</span>
<span>{{ selectedPlan.total.toLocaleString() }} تومان</span>
</div>
<button class="primary-button" style="width: 100%;" @click="pay">پرداخت</button>
<button class="primary-button" style="width: 100%;max-width: 100%;" @click="pay">پرداخت</button>
</div>
</div>
</template>
@ -66,7 +66,7 @@ export default {
availableMemberOptions: { type: Array, default: () => [5, 10, 20, 100] },
baseUrl: { type: String, required: true },
hasActiveSubscription: { type: Boolean, default: false },
hasExpiredSubscription: { type: Boolean, default: false }, // جدید
hasExpiredSubscription: { type: Boolean, default: false },
},
data() {
return {
@ -92,18 +92,43 @@ export default {
this.selectedPlan = { ...plan, basePrice: base, tax, total: base + tax };
},
async pay() {
// Define Toast configuration with SweetAlert2
const Toast = this.$swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.onmouseenter = this.$swal.stopTimeritarian
toast.onmouseleave = this.$swal.resumeTimer;
},
});
if (this.hasActiveSubscription) {
alert('شما اشتراک فعالی دارید و نمی‌توانید اشتراک دیگری خریداری کنید.');
Toast.fire({
icon: 'warning',
title: 'شما اشتراک فعالی دارید و نمی‌توانید اشتراک دیگری خریداری کنید.',
});
return;
}
if (this.hasExpiredSubscription) {
alert('شما یکبار اشتراک تهیه کردید و نمی‌توانید دوباره اشتراک تهیه کنید.');
Toast.fire({
icon: 'warning',
title: 'شما یکبار اشتراک تهیه کردید و نمی‌توانید دوباره اشتراک تهیه کنید.',
});
return;
}
if (!this.selectedPlan) {
alert('لطفاً یک طرح اشتراک انتخاب کنید.');
Toast.fire({
icon: 'error',
title: 'لطفاً یک طرح اشتراک انتخاب کنید.',
});
return;
}
try {
const startTime = new Date().toISOString();
const endTime = this.calculateEndTime(this.selectedPlan.name);
@ -114,16 +139,50 @@ export default {
endTime,
price: this.selectedPlan.total,
};
const token = localStorage.getItem('token');
if (!token) throw new Error('توکن احراز هویت یافت نشد.');
if (!token) {
Toast.fire({
icon: 'error',
title: 'توکن احراز هویت یافت نشد.',
});
throw new Error('Authentication token not found.');
}
const response = await axios.post(`${this.baseUrl}/add_subscription/`, subscriptionData, {
headers: { Authorization: `Token ${token}`, 'Content-Type': 'application/json' },
});
this.$emit('payment-success', { subscriptionId: response.data.subscription_id });
// Show success Toast
Toast.fire({
icon: 'success',
title: 'اشFinally با موفقیت ثبت شد.',
});
this.selectedPlan = null;
} catch (error) {
let errorMessage = 'خطا در ثبت اشتراک. لطفاً دوباره تلاش کنید.';
if (error.response) {
if (error.response.status === 401) {
errorMessage = 'توکن احراز هویت نامعتبر است.';
} else if (error.response.status === 400) {
errorMessage = 'اطلاعات ورودی نامعتبر است.';
} else {
errorMessage = error.response.data.message || errorMessage;
}
} else if (error.request) {
errorMessage = 'مشکل در ارتباط با سرور. لطفاً دوباره تلاش کنید.';
}
// Show error Toast
Toast.fire({
icon: 'error',
title: errorMessage,
});
console.error('Error registering subscription:', error);
alert('خطا در ثبت اشتراک. لطفاً دوباره تلاش کنید.');
}
},
calculateEndTime(planName) {
@ -140,6 +199,7 @@ export default {
};
</script>
<style scoped>
.buy-subscription-container {
direction: rtl;

View File

@ -433,9 +433,12 @@ export default {
customer() {
return JSON.parse(localStorage.getItem('customer') || '{}');
},
userInfo() {
return JSON.parse(localStorage.getItem('user') || '{}');
},
fullName() {
return this.customer.first_name && this.customer.last_name
? `${this.customer.first_name} ${this.customer.last_name}`
return this.userInfo.first_name && this.userInfo.last_name
? `${this.userInfo.first_name} ${this.userInfo.last_name}`
: 'کاربر مهمان';
},
userPhone() {
@ -448,7 +451,7 @@ export default {
return this.customer.profile_img || this.defaultProfileIcon;
},
userId() {
return this.customer.id || null;
return this.customer.user_id || null;
},
},
watch: {
@ -482,19 +485,47 @@ export default {
},
methods: {
async fetchTeamMembers() {
// Define Toast configuration for SweetAlert2
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 token = localStorage.getItem('token');
if (!token) throw new Error('توکن احراز هویت پیدا نشد');
if (!token) {
throw new Error('توکن احراز هویت پیدا نشد');
}
const response = await axios.get(`${API_BASE_URL}/get_all_team_members`, {
headers: { Authorization: `Token ${token.trim()}` },
});
this.teamMembers = response.data.members.filter(
(member) => member.user?.id && member.user.first_name && member.user.last_name
);
} catch (error) {
if (error.response?.status === 403) {
alert('لطفاً دوباره وارد شوید');
// Show unauthorized error Toast and redirect to login
Toast.fire({
icon: 'error',
title: 'لطفاً دوباره وارد شوید',
});
window.location.href = '/login';
} else {
// Show general error Toast for team members fetch
Toast.fire({
icon: 'error',
title: 'خطا در بارگذاری لیست اعضای تیم',
});
}
this.error = 'خطا در بارگذاری لیست اعضای تیم';
}
@ -528,23 +559,60 @@ export default {
return member ? `${member.user.first_name} ${member.user.last_name}` : '';
},
addParticipant() {
// Define Toast configuration for SweetAlert2
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;
},
});
if (!this.selectedParticipantId) {
// Show error Toast for no participant selected
Toast.fire({
icon: 'error',
title: 'لطفاً یک عضو تیم انتخاب کنید.',
});
this.error = 'لطفاً یک عضو تیم انتخاب کنید.';
return;
}
const selectedMember = this.teamMembers.find((member) => member.user.id === this.selectedParticipantId);
if (!selectedMember) {
// Show error Toast for invalid participant
Toast.fire({
icon: 'error',
title: 'کاربر انتخاب‌شده یافت نشد.',
});
this.error = 'کاربر انتخاب‌شده یافت نشد.';
return;
}
if (this.participants.some((p) => p.id === this.selectedParticipantId)) {
// Show error Toast for duplicate participant
Toast.fire({
icon: 'error',
title: 'این کاربر قبلاً اضافه شده است.',
});
this.error = 'این کاربر قبلاً اضافه شده است.';
return;
}
if (this.selectedParticipantId === this.userId) {
// Show error Toast for adding self
Toast.fire({
icon: 'error',
title: 'نمی‌توانید خودتان را به‌عنوان شرکت‌کننده اضافه کنید.',
});
this.error = 'نمی‌توانید خودتان را به‌عنوان شرکت‌کننده اضافه کنید.';
return;
}
this.participants.push({
id: selectedMember.user.id,
phone: selectedMember.mobile_number,
@ -552,9 +620,11 @@ export default {
role: selectedMember.semat || 'بدون سمت',
profile_img: selectedMember.profile_img || this.defaultProfileIcon,
});
this.selectedParticipantId = '';
this.isDropdownOpen = false;
this.error = null;
},
removeParticipant(id) {
this.participants = this.participants.filter((p) => p.id !== id);
@ -569,7 +639,6 @@ export default {
this.$emit('close');
this.resetForm();
},
resetForm() {
this.form = {
title: '',
@ -598,25 +667,62 @@ export default {
if (this.form[field] > 0) this.form[field]--;
},
async handleSubmit() {
// Define Toast configuration for SweetAlert2
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;
},
});
if (!this.form.title || !this.form.date) {
// Show error Toast for missing title or date
Toast.fire({
icon: 'error',
title: 'لطفاً نام جلسه و تاریخ را وارد کنید.',
});
this.error = 'لطفاً نام جلسه و تاریخ را وارد کنید.';
return;
}
if (!this.form.selectedRoom || this.form.space === null || this.form.asset_bundle === null) {
// Show error Toast for missing room selection
Toast.fire({
icon: 'error',
title: 'لطفاً یک اتاق برای جلسه انتخاب کنید.',
});
this.error = 'لطفاً یک اتاق برای جلسه انتخاب کنید.';
return;
}
const momentDate = moment(this.form.date, 'jYYYY/jMM/jDD');
if (!momentDate.isValid()) {
// Show error Toast for invalid date
Toast.fire({
icon: 'error',
title: 'تاریخ وارد شده معتبر نیست.',
});
this.error = 'تاریخ وارد شده معتبر نیست.';
return;
}
const startTimeInMinutes = this.form.startHour * 60 + this.form.startMinute;
const endTimeInMinutes = this.form.endHour * 60 + this.form.endMinute;
if (endTimeInMinutes <= startTimeInMinutes) {
// Show error Toast for invalid time range
Toast.fire({
icon: 'error',
title: 'زمان پایان باید بعد از زمان شروع باشد.',
});
this.error = 'زمان پایان باید بعد از زمان شروع باشد.';
return;
}
const startDateTime = momentDate
.clone()
.set({ hour: this.form.startHour, minute: this.form.startMinute, second: 0 })
@ -635,7 +741,13 @@ export default {
try {
this.$emit('create-meeting', meetingData);
this.closeModalByButton();
} catch (error) {
// Show error Toast for data preparation failure
Toast.fire({
icon: 'error',
title: `خطا در آماده‌سازی داده‌ها: ${error.message}`,
});
this.error = `خطا در آماده‌سازی داده‌ها: ${error.message}`;
}
},

View File

@ -49,7 +49,10 @@
</div>
</div>
<div v-else class="loading-message">
<div v-if="spaces.length === 0 && !isLoading" class="loading-message">
<p>امکان ساختن فضا برای شما وجود ندارد</p>
</div>
<div v-else-if="spaces.length === 0 && isLoading" class="loading-message">
<p>در حال بارگذاری فضاها...</p>
</div>
</div>
@ -106,34 +109,52 @@ export default {
capacity: '',
description: '',
},
isLoading: false,
};
},
methods: {
beforeDestroy() {
// اطمینان از فعال شدن اسکرول هنگام حذف کامپوننت
document.body.style.overflow = '';
},
beforeDestroy() {
document.body.style.overflow = '';
},
closeModal() {
this.$emit('close');
this.resetForm()
this.resetForm();
},
resetForm() {
this.spaces = [],
this.selectedSpace = null,
this.spaces = [];
this.selectedSpace = null;
this.form = {
name : '',
capacity : '',
description : '',
}
name: '',
capacity: '',
description: '',
};
},
selectSpace(space) {
this.selectedSpace = space;
},
async fetchSpaces() {
// Define Toast configuration with SweetAlert2
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 {
this.isLoading = true;
const token = localStorage.getItem('token');
if (!token) {
console.error('No token found!');
// Show error Toast if no token is found
Toast.fire({
icon: 'error',
title: 'توکن یافت نشد. لطفا دوباره وارد شوید.',
});
return;
}
@ -147,8 +168,6 @@ export default {
}
);
console.log(response.data);
this.spaces = response.data.assetbundle_rooms.map(room => ({
name: room.name,
img: room.img,
@ -158,10 +177,30 @@ export default {
id: room.id,
}));
} catch (error) {
// Show error Toast
Toast.fire({
icon: 'error',
title: 'خطا در بارگذاری فضاها. لطفا دوباره تلاش کنید.',
});
console.error('Error fetching spaces:', error);
} finally {
this.isLoading = false;
}
},
async submitForm() {
// Define Toast configuration with SweetAlert2
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;
},
});
const spaceData = {
assetBundleRoomId: this.selectedSpace.id,
name: this.form.name,
@ -172,7 +211,11 @@ export default {
try {
const token = localStorage.getItem('token');
if (!token) {
console.error('No token found!');
// Show error Toast if no token is found
Toast.fire({
icon: 'error',
title: 'توکن یافت نشد. لطفا دوباره وارد شوید.',
});
return;
}
@ -187,24 +230,45 @@ export default {
}
);
console.log(response.data);
// Show success Toast
Toast.fire({
icon: 'success',
title: 'فضا با موفقیت اضافه شد',
});
this.$emit('submit', response.data);
this.closeModal(); // Close the modal
window.location.reload(); // Refresh the page
this.closeModal();
window.location.reload();
} catch (error) {
let errorMessage = 'خطا در ارسال اطلاعات. لطفا دوباره تلاش کنید.';
if (error.response) {
if (error.response.status === 401) {
errorMessage = 'عدم دسترسی. لطفا دوباره وارد شوید.';
} else if (error.response.status === 400) {
errorMessage = 'اطلاعات ورودی نامعتبر است.';
} else {
errorMessage = error.response.data.message || errorMessage;
}
} else if (error.request) {
errorMessage = 'مشکل در ارتباط با سرور. لطفا دوباره تلاش کنید.';
}
// Show error Toast
Toast.fire({
icon: 'error',
title: errorMessage,
});
console.error('Error submitting form:', error);
alert('خطا در ارسال اطلاعات، لطفا دوباره تلاش کنید');
}
},
},
watch: {
isVisible(newVal) {
if (newVal) {
// غیرفعال کردن اسکرول هنگام باز شدن پاپآپ
document.body.style.overflow = 'hidden';
this.fetchSpaces();
} else {
// فعال کردن اسکرول هنگام بسته شدن پاپآپ
document.body.style.overflow = '';
}
},

View File

@ -137,6 +137,19 @@ export default {
this.$emit('close');
},
async downloadFile() {
// Define Toast configuration with SweetAlert2
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 fetch(this.previewUrl);
const blob = await response.blob();
@ -148,14 +161,38 @@ export default {
a.click();
window.URL.revokeObjectURL(downloadUrl);
document.body.removeChild(a);
// Show success Toast
Toast.fire({
icon: 'success',
title: 'فایل با موفقیت دانلود شد',
});
} catch (error) {
console.error('Error downloading file:', error);
alert('خطا در دانلود فایل');
// Show error Toast
Toast.fire({
icon: 'error',
title: 'خطا در دانلود فایل',
});
}
},
async deleteFile() {
if (this.previewIndex === null || !this.previewType) return;
// Define Toast configuration with SweetAlert2
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 token = localStorage.getItem('token');
const deleteUrl = `${this.baseUrl}/delete${this.previewType.charAt(0).toUpperCase() + this.previewType.slice(1)}/${this.previewIndex}/`;
@ -168,10 +205,33 @@ export default {
this.$emit('delete-success');
this.closePreviewDialog();
alert('فایل با موفقیت حذف شد');
// Show success Toast
Toast.fire({
icon: 'success',
title: 'فایل با موفقیت حذف شد',
});
} catch (error) {
console.error('Error deleting file:', error);
alert('خطا در حذف فایل');
let errorMessage = 'خطا در حذف فایل';
if (error.response) {
if (error.response.status === 401) {
errorMessage = 'عدم دسترسی: لطفا دوباره وارد شوید.';
} else if (error.response.status === 400) {
errorMessage = 'درخواست نامعتبر است.';
} else {
errorMessage = error.response.data.message || errorMessage;
}
} else if (error.request) {
errorMessage = 'مشکل در ارتباط با سرور. لطفا دوباره تلاش کنید.';
}
// Show error Toast
Toast.fire({
icon: 'error',
title: errorMessage,
});
}
},
},

View File

@ -502,7 +502,7 @@ export default {
return this.customer.profile_img || this.defaultProfileIcon;
},
userId() {
return this.customer.id || null;
return this.customer.user_id || null;
},
},
watch: {
@ -524,6 +524,19 @@ export default {
},
methods: {
async fetchTeamMembers() {
// Define Toast configuration with SweetAlert2
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 token = localStorage.getItem('token');
if (!token) throw new Error('توکن احراز هویت پیدا نشد');
@ -535,7 +548,11 @@ export default {
);
} catch (error) {
if (error.response?.status === 403) {
alert('لطفاً دوباره وارد شوید');
// Show error Toast for unauthorized access
Toast.fire({
icon: 'error',
title: 'لطفاً دوباره وارد شوید',
});
window.location.href = '/login';
}
this.error = 'خطا در بارگذاری لیست اعضای تیم';
@ -638,20 +655,53 @@ export default {
return member ? `${member.user.first_name} ${member.user.last_name}` : '';
},
addParticipant() {
// Define Toast configuration for participant errors
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;
},
});
if (!this.selectedParticipantId) {
// Show error Toast for no participant selected
Toast.fire({
icon: 'error',
title: 'لطفاً یک عضو تیم انتخاب کنید.',
});
this.error = 'لطفاً یک عضو تیم انتخاب کنید.';
return;
}
const selectedMember = this.teamMembers.find((member) => member.user.id === this.selectedParticipantId);
if (!selectedMember) {
// Show error Toast for invalid participant
Toast.fire({
icon: 'error',
title: 'کاربر انتخاب‌شده یافت نشد.',
});
this.error = 'کاربر انتخاب‌شده یافت نشد.';
return;
}
if (this.participants.some((p) => p.id === this.selectedParticipantId)) {
// Show error Toast for duplicate participant
Toast.fire({
icon: 'error',
title: 'این کاربر قبلاً اضافه شده است.',
});
this.error = 'این کاربر قبلاً اضافه شده است.';
return;
}
if (this.selectedParticipantId === this.userId) {
// Show error Toast for self-addition
Toast.fire({
icon: 'error',
title: 'نمی‌توانید خودتان را به‌عنوان شرکت‌کننده اضافه کنید.',
});
this.error = 'نمی‌توانید خودتان را به‌عنوان شرکت‌کننده اضافه کنید.';
return;
}
@ -709,22 +759,55 @@ export default {
if (this.form[field] > 0) this.form[field]--;
},
async handleSubmit() {
// Define Toast configuration with SweetAlert2
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;
},
});
if (!this.form.title || !this.form.date) {
// Show error Toast for missing title or date
Toast.fire({
icon: 'error',
title: 'لطفاً نام جلسه و تاریخ را وارد کنید.',
});
this.error = 'لطفاً نام جلسه و تاریخ را وارد کنید.';
return;
}
if (!this.form.selectedRoom || this.form.space === null || this.form.asset_bundle === null) {
// Show error Toast for missing room selection
Toast.fire({
icon: 'error',
title: 'لطفاً یک اتاق برای جلسه انتخاب کنید.',
});
this.error = 'لطفاً یک اتاق برای جلسه انتخاب کنید.';
return;
}
const momentDate = moment(this.form.date, 'jYYYY/jMM/jDD');
if (!momentDate.isValid()) {
// Show error Toast for invalid date
Toast.fire({
icon: 'error',
title: 'تاریخ وارد شده معتبر نیست.',
});
this.error = 'تاریخ وارد شده معتبر نیست.';
return;
}
const startTimeInMinutes = this.form.startHour * 60 + this.form.startMinute;
const endTimeInMinutes = this.form.endHour * 60 + this.form.endMinute;
if (endTimeInMinutes <= startTimeInMinutes) {
// Show error Toast for invalid time range
Toast.fire({
icon: 'error',
title: 'زمان پایان باید بعد از زمان شروع باشد.',
});
this.error = 'زمان پایان باید بعد از زمان شروع باشد.';
return;
}
@ -761,15 +844,26 @@ export default {
maxCapacity: this.form.selectedRoom.capacity || 10,
invited_users: this.participants,
});
// Show success Toast
Toast.fire({
icon: 'success',
title: 'جلسه با موفقیت ویرایش شد!',
});
this.closeModalByButton();
alert('جلسه با موفقیت ویرایش شد!');
} catch (error) {
// Show error Toast for submission failure
Toast.fire({
icon: 'error',
title: `خطا در ویرایش جلسه: ${error.response?.data?.message || error.message}`,
});
this.error = `خطا در ویرایش جلسه: ${error.response?.data?.message || error.message}`;
}
},
},
};
</script>
<style scoped>
.participant-input {
position: relative;

View File

@ -146,7 +146,7 @@ export default {
} else if (/\.(mp4|mov|mkv|wmv|m4v|mpg|webm|ogg)$/i.test(fileName)) {
this.currentUploadType = 'video';
this.dialogTitle = 'آپلود ویدیو';
} else if (/\.(glb|obj|fbx|stl|ply|gltf)|$/i.test(fileName)) {
} else if (/\.(glb|obj|fbx|stl|ply|gltf)$/i.test(fileName)) {
this.currentUploadType = 'glb';
this.dialogTitle = 'آپلود مدل 3D';
} else {
@ -156,8 +156,25 @@ export default {
}
},
async uploadFile() {
// Define Toast configuration with SweetAlert2
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;
},
});
if (!this.selectedFile) {
alert('لطفاً یک فایل انتخاب کنید.');
// Check if a file is selected
Toast.fire({
icon: 'error',
title: 'لطفاً یک فایل انتخاب کنید.',
});
return;
}
@ -171,9 +188,12 @@ export default {
let uploadUrl = `${this.baseUrl}/upload${this.currentUploadType.charAt(0).toUpperCase() + this.currentUploadType.slice(1)}/`;
if (this.currentUploadType === 'other') {
console.log('فایل به دسته "سایر" ارسال می‌شود:', this.selectedFile.name);
alert('فایل به دسته "سایر" ارسال شد (تستی).');
console.log('File sent to "other" category:', this.selectedFile.name);
// Log and show Toast for 'other' file type (test mode)
Toast.fire({
icon: 'success',
title: 'فایل به دسته "سایر" ارسال شد.',
});
this.resetForm();
this.$emit('upload-success');
this.$emit('close');
@ -187,17 +207,40 @@ export default {
},
});
// Show success Toast
Toast.fire({
icon: 'success',
title: 'فایل با موفقیت آپلود شد',
});
this.resetForm();
this.$emit('upload-success');
this.$emit('close');
alert('فایل با موفقیت آپلود شد');
if (this.$route.path !== '/dashboard/files') {
this.$router.push('/dashboard/files');
}
} catch (error) {
let errorMessage = 'خطا در آپلود فایل. لطفا دوباره تلاش کنید.';
if (error.response) {
if (error.response.status === 401) {
errorMessage = 'عدم دسترسی. لطفاً وارد حساب کاربری شوید.';
} else if (error.response.status === 400) {
errorMessage = 'اطلاعات ورودی نامعتبر است.';
} else {
errorMessage = error.response.data.message || errorMessage;
}
} else if (error.request) {
errorMessage = 'مشکل در ارتباط با سرور. لطفا دوباره تلاش کنید.';
}
// Show error Toast
Toast.fire({
icon: 'error',
title: errorMessage,
});
console.error('Error uploading file:', error);
alert('خطا در آپلود فایل');
} finally {
this.uploading = false;
}

View File

@ -430,7 +430,7 @@ export default {
if (selectedRoomDetails.isTemporary) {
roomData = {
...selectedRoomDetails,
space: 18,
space: 29,
asset_bundle: selectedRoomDetails.id,
use_space: false,
image: selectedRoomDetails.image || 'https://via.placeholder.com/150',
@ -455,6 +455,8 @@ export default {
},
};
</script>
<style scoped>
.modal-overlay {
position: fixed;

View File

@ -122,9 +122,30 @@ export default {
},
methods: {
async fetchTeamData() {
// Define Toast configuration with SweetAlert2
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 token = localStorage.getItem('token');
if (!token) throw new Error('توکن احراز هویت یافت نشد.');
if (!token) {
// Show error Toast for missing token
Toast.fire({
icon: 'error',
title: 'توکن احراز هویت یافت نشد.',
});
throw new Error('No authentication token found.');
}
const response = await axios.get(`${this.baseUrl}/get_team`, {
headers: { Authorization: `Token ${token}`, 'Content-Type': 'application/json' },
});
@ -135,10 +156,19 @@ export default {
this.form.teamId = team.id;
this.teamLogo = team.logo ? `${this.baseUrl}${team.logo}` : null;
} else {
alert('هیچ اطلاعاتی برای تیم یافت نشد.');
// Show error Toast for no team data
Toast.fire({
icon: 'error',
title: 'هیچ اطلاعاتی برای تیم یافت نشد.',
});
}
} catch {
alert('خطا در بارگذاری اطلاعات تیم.');
} catch (error) {
// Show error Toast for fetch failure
Toast.fire({
icon: 'error',
title: 'خطا در بارگذاری اطلاعات تیم.',
});
console.error('Fetch team error:', error);
}
},
handleLogoUpload(event) {
@ -148,30 +178,69 @@ export default {
}
},
async submitForm() {
// Define Toast configuration with SweetAlert2
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;
},
});
if (!this.form.teamName && !this.form.activityType && !this.uploadedLogoFile) {
alert('لطفاً حداقل یک فیلد یا لوگو وارد کنید.');
// Show error Toast for empty form
Toast.fire({
icon: 'error',
title: 'لطفاً حداقل یک فیلد یا لوگو وارد کنید.',
});
return;
}
try {
const formData = new FormData();
if (this.form.teamName) formData.append('name', this.form.teamName);
if (this.form.activityType) formData.append('description', this.form.activityType);
if (this.uploadedLogoFile) formData.append('logo', this.uploadedLogoFile);
const token = localStorage.getItem('token');
if (!token) throw new Error('توکن احراز هویت یافت نشد.');
if (!token) {
// Show error Toast for missing token
Toast.fire({
icon: 'error',
title: 'توکن احراز هویت یافت نشد.',
});
throw new Error('No authentication token found.');
}
await axios.patch(`${this.baseUrl}/update_team/${this.form.teamId}/`, formData, {
headers: { Authorization: `Token ${token}`, 'Content-Type': 'multipart/form-data' },
});
this.$emit('update:team-data', {
teamName: this.form.teamName,
activityType: this.form.activityType,
teamLogo: this.uploadedLogoFile,
});
alert('اطلاعات تیم با موفقیت به‌روزرسانی شد.');
// Show success Toast
Toast.fire({
icon: 'success',
title: 'اطلاعات تیم با موفقیت به‌روزرسانی شد.',
});
this.resetForm();
await this.fetchTeamData();
} catch {
alert('خطا در به‌روزرسانی اطلاعات تیم.');
} catch (error) {
// Show error Toast for update failure
Toast.fire({
icon: 'error',
title: 'خطا در به‌روزرسانی اطلاعات تیم.',
});
console.error('Update team error:', error);
}
},
resetForm() {

View File

@ -321,9 +321,26 @@ export default {
},
methods: {
openAddUserModal() {
// Define Toast configuration with SweetAlert2
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;
},
});
if (this.remainingCapacity <= 0) {
this.$emit('change-tab', 'buy-subscription');
alert('اشتراک فعالی ندارید , لطفا اشتراک تهیه نمایید.');
// Show error Toast for no active subscription
Toast.fire({
icon: 'error',
title: 'اشتراک فعالی ندارید، لطفا اشتراک تهیه نمایید.',
});
return;
}
this.isAddUserModalVisible = true;
@ -348,7 +365,6 @@ export default {
beforeUnmount() {
window.removeEventListener('resize', this.handleResize);
},
};
</script>
@ -846,7 +862,7 @@ export default {
.add-card {
width: 48%;
height: auto;
height: 11.38rem;
}
}

View File

@ -67,18 +67,15 @@ export default {
},
});
// Prepare login data
const loginData = {
mobile_number: this.form.mobileNumber,
password: this.form.password,
};
try {
// Send login request
const response = await apiClient.post('/login', loginData);
if (response.data.status === 200) {
// Store token and user data in localStorage
const token = response.data.data.token;
const user = response.data.data.user;
@ -91,7 +88,6 @@ export default {
title: 'ورود با موفقیت انجام شد',
});
// Redirect to dashboard
this.$router.push('/dashboard');
} else {
// Show error Toast with server message
@ -101,10 +97,8 @@ export default {
});
}
} catch (error) {
// Handle specific error cases
let errorMessage = 'خطا در ورود, لطفا دوباره تلاش کنید';
if (error.response) {
// Handle server errors (e.g., 400, 401, 500)
if (error.response.status === 401) {
errorMessage = '.شماره تماس یا رمز عبور اشتباه است';
} else if (error.response.status === 400) {
@ -113,7 +107,6 @@ export default {
errorMessage = error.response.data.message || errorMessage;
}
} else if (error.request) {
// Handle network errors (no response from server)
errorMessage = 'مشکل در ارتباط با سرور, لطفا دوباره تلاش کنید';
}
@ -123,7 +116,6 @@ export default {
title: errorMessage,
});
// Log error for debugging
console.error('Login error:', error);
}
},

View File

@ -64,7 +64,7 @@
</template>
<script>
import apiClient from '@/api/axios'; // Adjust the path based on your project structure
import apiClient from '@/api/axios';
export default {
data() {
@ -74,7 +74,7 @@ export default {
code: '',
password: '',
},
codeSent: false, // Tracks if the code has been sent
codeSent: false,
};
},
methods: {
@ -93,13 +93,11 @@ export default {
});
try {
// Send request to get reset code
const response = await apiClient.post('/requestResetCode', {
mobile_number: this.form.mobileNumber,
});
if (response.data.success) {
// Update state to show code and password input form
this.codeSent = true;
// Show success Toast
@ -115,10 +113,8 @@ export default {
});
}
} catch (error) {
// Handle specific error cases
let errorMessage = 'خطا در ارسال کد تأیید, لطفاً دوباره تلاش کنید';
if (error.response) {
// Handle server errors (e.g., 400, 401, 500)
if (error.response.status === 400) {
errorMessage = '.شماره تماس نامعتبر است';
} else if (error.response.status === 404) {
@ -127,7 +123,6 @@ export default {
errorMessage = error.response.data.message || errorMessage;
}
} else if (error.request) {
// Handle network errors (no response from server)
errorMessage = 'مشکل در ارتباط با سرور, لطفاً دوباره تلاش کنید';
}
@ -137,7 +132,6 @@ export default {
title: errorMessage,
});
// Log error for debugging
console.error('Error requesting reset code:', error);
}
},
@ -156,7 +150,6 @@ export default {
});
try {
// Send request to verify code and reset password
const response = await apiClient.post('/verifyResetCode', {
mobile_number: this.form.mobileNumber,
code: this.form.code,
@ -170,7 +163,6 @@ export default {
title: '.رمز عبور با موفقیت بازنشانی شد',
});
// Redirect to login page
this.$router.push('/');
} else {
// Show error Toast with server message
@ -180,10 +172,8 @@ export default {
});
}
} catch (error) {
// Handle specific error cases
let errorMessage = '.خطا در بازنشانی رمز عبور , لطفاً کد یا رمز عبور را بررسی کنید';
if (error.response) {
// Handle server errors (e.g., 400, 401, 500)
if (error.response.status === 400) {
errorMessage = '.کد تأیید یا رمز عبور نامعتبر است';
} else if (error.response.status === 401) {
@ -192,7 +182,6 @@ export default {
errorMessage = error.response.data.message || errorMessage;
}
} else if (error.request) {
// Handle network errors (no response from server)
errorMessage = '.مشکل در ارتباط با سرور , لطفاً دوباره تلاش کنید';
}
@ -202,7 +191,6 @@ export default {
title: errorMessage,
});
// Log error for debugging
console.error('Error resetting password:', error);
}
},

View File

@ -88,7 +88,6 @@ export default {
},
});
// Validate form inputs
if (!this.form.firstName || !this.form.lastName || !this.form.semat || !this.form.mobileNumber || !this.form.password) {
Toast.fire({
icon: 'error',
@ -97,7 +96,6 @@ export default {
return;
}
// Prepare the data to match API format
const signupData = {
first_name: this.form.firstName,
last_name: this.form.lastName,
@ -107,12 +105,9 @@ export default {
};
try {
// Send signup request
const response = await axios.post('http://194.62.43.230:8000/signup', signupData);
// Check if signup was successful
if (response.data.token) {
// Store token in localStorage
localStorage.setItem('token', response.data.token);
// Show success Toast
@ -121,7 +116,6 @@ export default {
title: '.حساب کاربری با موفقیت ساخته شد',
});
// Redirect to login page
this.$router.push('/');
} else {
// Show error Toast with server message
@ -131,17 +125,14 @@ export default {
});
}
} catch (error) {
// Handle specific error cases
let errorMessage = 'خطا در ثبت‌نام, لطفاً دوباره تلاش کنید';
if (error.response) {
// Handle server errors (e.g., 400)
if (error.response.status === 400) {
errorMessage = '.شماره تلفن قبلاً ثبت شده است';
} else {
errorMessage = error.response.data.message || errorMessage;
}
} else if (error.request) {
// Handle network errors (no response from server)
errorMessage = 'مشکل در ارتباط با سرور, لطفاً دوباره تلاش کنید';
}
@ -151,7 +142,6 @@ export default {
title: errorMessage,
});
// Log error for debugging
console.error('Signup error:', error);
}
},

View File

@ -52,7 +52,7 @@
</template>
<script>
import axios from '@/axios'; // Adjust the path based on your project structure
import axios from '@/axios';
export default {
data() {
@ -62,19 +62,18 @@ export default {
code: '',
password: '',
},
codeSent: false, // Tracks if the code has been sent
isButtonDisabled: false, // Tracks if resend button is disabled
countdown: 120, // Countdown timer in seconds (2 minutes)
countdownInterval: null, // Interval for countdown
codeSent: false,
isButtonDisabled: false,
countdown: 120,
countdownInterval: null,
};
},
mounted() {
// Check for token and trigger SMS sending on mount
const token = localStorage.getItem('token');
if (!token) {
window.location.reload();
} else {
this.sendSms(); // Automatically call sendSms on mount
this.sendSms();
}
},
methods: {
@ -93,10 +92,7 @@ export default {
});
try {
// Get token from localStorage
const token = localStorage.getItem('token');
// Send request to get verification SMS
const response = await axios.get('/sendSmsVerification', {
headers: {
Authorization: `Token ${token}`,
@ -105,29 +101,21 @@ export default {
});
if (response.status === 200) {
// Update state to indicate code was sent
this.codeSent = true;
// Show success Toast
Toast.fire({
icon: 'success',
title: '.کد تأیید به شماره موبایل شما ارسال شد',
});
// Start countdown for resend button
this.startCountdown();
} else {
// Show error Toast with server message
Toast.fire({
icon: 'error',
title: response.data.message || 'خطا در ارسال کد تأیید, لطفاً دوباره تلاش کنید',
});
}
} catch (error) {
// Handle specific error cases
let errorMessage = 'خطا در ارسال کد تأیید, لطفاً دوباره تلاش کنید';
if (error.response) {
// Handle server errors (e.g., 400, 401)
if (error.response.status === 400) {
errorMessage = '.درخواست نامعتبر است';
} else if (error.response.status === 401) {
@ -136,30 +124,23 @@ export default {
errorMessage = error.response.data.message || errorMessage;
}
} else if (error.request) {
// Handle network errors (no response from server)
errorMessage = 'مشکل در ارتباط با سرور, لطفاً دوباره تلاش کنید';
}
// Show error Toast
Toast.fire({
icon: 'error',
title: errorMessage,
});
// Log error for debugging
console.error('Error requesting SMS code:', error);
}
},
startCountdown() {
// Disable resend button and start countdown
this.isButtonDisabled = true;
this.countdown = 120; // Reset to 2 minutes
this.countdown = 120;
if (this.countdownInterval) {
clearInterval(this.countdownInterval);
}
// Update countdown every second
this.countdownInterval = setInterval(() => {
if (this.countdown > 0) {
this.countdown--;
@ -184,10 +165,7 @@ export default {
});
try {
// Get token from localStorage
const token = localStorage.getItem('token');
// Send request to verify SMS code
const response = await axios.post(
'/submitSmsVerification',
{
@ -202,26 +180,20 @@ export default {
);
if (response.status === 200) {
// Show success Toast
Toast.fire({
icon: 'success',
title: '.کد تأیید صحیح است',
});
// Redirect to dashboard
this.$router.push('/dashboard');
} else {
// Show error Toast with server message
Toast.fire({
icon: 'error',
title: response.data.message || '.کد تأیید نامعتبر است',
});
}
} catch (error) {
// Handle specific error cases
let errorMessage = '.کد تأیید نامعتبر است';
if (error.response) {
// Handle server errors (e.g., 400, 401)
if (error.response.status === 400) {
errorMessage = '.کد تأیید نامعتبر است';
} else if (error.response.status === 401) {
@ -230,17 +202,12 @@ export default {
errorMessage = error.response.data.message || errorMessage;
}
} else if (error.request) {
// Handle network errors (no response from server)
errorMessage = 'مشکل در ارتباط با سرور, لطفاً دوباره تلاش کنید';
}
// Show error Toast
Toast.fire({
icon: 'error',
title: errorMessage,
});
// Log error for debugging
console.error('Error verifying SMS code:', error);
}
},

View File

@ -73,7 +73,6 @@ export default {
};
},
setup() {
// Define male avatars
const maleAvatars = ref([
{ id: 1, name: 'مرد ۱', src: 'http://my.xroomapp.com:8000/media/user_glbs/men1.glb', profile_img: 'http://my.xroomapp.com:8000/media/user_images/men1.png' },
{ id: 2, name: 'مرد ۲', src: 'http://my.xroomapp.com:8000/media/user_glbs/men2.glb', profile_img: 'http://my.xroomapp.com:8000/media/user_images/men2.png' },
@ -81,7 +80,6 @@ export default {
{ id: 17, name: 'مرد ۴', src: 'http://my.xroomapp.com:8000/media/user_glbs/men4.glb', profile_img: 'http://my.xroomapp.com:8000/media/user_images/men4.png' },
]);
// Define female avatars
const femaleAvatars = ref([
{ id: 4, name: 'زن ۱', src: 'http://my.xroomapp.com:8000/media/user_glbs/women1.glb', profile_img: 'http://my.xroomapp.com:8000/media/user_images/women1.png' },
{ id: 10, name: 'زن ۲', src: 'http://my.xroomapp.com:8000/media/user_glbs/women2.glb', profile_img: 'http://my.xroomapp.com:8000/media/user_images/women2.png' },
@ -100,12 +98,10 @@ export default {
};
},
created() {
// Fetch user data on component creation
this.fetchUserData();
},
computed: {
userProfilePicUrl() {
// Get customer data from localStorage
const customer = JSON.parse(localStorage.getItem('customer') || {});
if (!customer.profile_img) return this.defaultProfileImage;
return `http://194.62.43.230:8000/media/${customer.profile_img}`;
@ -126,12 +122,10 @@ export default {
},
});
// Set saving state and selected avatar
this.saving = true;
this.selectedAvatar = avatar.id;
try {
// Send request to update profile with selected avatar
await axios.post(`${this.baseUrl}/editProfile/`, {
profile_glb_url: avatar.src,
profile_img: avatar.profile_img
@ -147,16 +141,13 @@ export default {
title: '.آواتار با موفقیت انتخاب شد',
});
// Delay redirect to allow Toast to be visible
setTimeout(() => {
window.location.assign('/dashboard');
}, 2000); // 3-second delay to match Toast duration
}, 2000);
} catch (error) {
// Handle specific error cases
let errorMessage = 'خطا در انتخاب آواتار. لطفاً دوباره تلاش کنید';
if (error.response) {
// Handle server errors (e.g., 400, 401)
if (error.response.status === 400) {
errorMessage = 'درخواست نامعتبر است.';
} else if (error.response.status === 401) {
@ -165,7 +156,6 @@ export default {
errorMessage = error.response.data.detail || error.response.data.message || errorMessage;
}
} else if (error.request) {
// Handle network errors (no response from server)
errorMessage = 'مشکل در ارتباط با سرور. لطفاً دوباره تلاش کنید';
}
@ -175,10 +165,8 @@ export default {
title: errorMessage,
});
// Log error for debugging
console.error('Error selecting avatar:', error);
} finally {
// Reset saving state and selected avatar
this.saving = false;
this.selectedAvatar = null;
}
@ -198,21 +186,17 @@ export default {
});
try {
// Fetch user data
const response = await axios.get('/getInfo');
this.userData = response.data;
} catch (error) {
// Handle specific error cases
let errorMessage = 'خطا در دریافت اطلاعات کاربر';
if (error.response) {
// Handle server errors (e.g., 400, 401)
if (error.response.status === 401) {
errorMessage = 'توکن نامعتبر است. لطفاً دوباره وارد شوید';
} else {
errorMessage = error.response.data.detail || error.response.data.message || errorMessage;
}
} else if (error.request) {
// Handle network errors (no response from server)
errorMessage = 'مشکل در ارتباط با سرور. لطفاً دوباره تلاش کنید';
}
@ -222,7 +206,6 @@ export default {
title: errorMessage,
});
// Log error for debugging
console.error('Error fetching user data:', error);
}
},
@ -240,10 +223,8 @@ export default {
},
});
// Set saving state
this.saving = true;
try {
// Prepare form data for profile update
const formData = new FormData();
formData.append('first_name', this.editForm.first_name);
formData.append('last_name', this.editForm.last_name);
@ -252,14 +233,12 @@ export default {
formData.append('profile_img', this.selectedProfileImage);
}
// Send request to update profile
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.new_password !== this.passwordForm.confirm_password) {
// Show error Toast for password mismatch
@ -270,14 +249,12 @@ export default {
throw new Error('رمز عبور جدید و تکرار آن مطابقت ندارند');
}
// Send request to reset password
await axios.post(`${this.baseUrl}/resetPassword/`, {
old_password: this.passwordForm.current_password,
new_password: this.passwordForm.new_password
});
}
// Fetch updated user data
await this.fetchUserData();
// Show success Toast
@ -286,10 +263,8 @@ export default {
title: 'تغییرات با موفقیت ذخیره شد',
});
} catch (error) {
// Handle specific error cases
let errorMessage = 'خطا در ذخیره تغییرات. لطفاً دوباره تلاش کنید';
if (error.response) {
// Handle server errors (e.g., 400, 401)
if (error.response.status === 400) {
errorMessage = '.درخواست نامعتبر است';
} else if (error.response.status === 401) {
@ -298,7 +273,6 @@ export default {
errorMessage = error.response.data.detail || error.response.data.message || errorMessage;
}
} else if (error.request) {
// Handle network errors (no response from server)
errorMessage = 'مشکل در ارتباط با سرور. لطفاً دوباره تلاش کنید';
}
@ -308,10 +282,8 @@ export default {
title: errorMessage,
});
// Log error for debugging
console.error('Error saving profile:', error);
} finally {
// Reset saving state
this.saving = false;
}
},
@ -356,7 +328,6 @@ export default {
});
},
uploadProfileImage(event) {
// Handle profile image upload
const file = event.target.files[0];
if (file) {
this.selectedProfileImage = file;

View File

@ -151,11 +151,9 @@ export default {
},
computed: {
userProfilePicUrl() {
// 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;
},
@ -176,13 +174,11 @@ export default {
try {
const response = await axios.get('/getInfo');
// 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
const userData = response.data.data;
if (!userData.user || !userData.customer) {
throw new Error('داده‌های کاربر یا مشتری در پاسخ سرور وجود ندارد');
}
@ -200,7 +196,6 @@ export default {
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({
@ -208,7 +203,6 @@ export default {
title: 'خطا در بارگذاری اطلاعات کاربر. لطفاً دوباره تلاش کنید',
});
console.error('Error fetching user data:', error);
// Initialize with default values to prevent breaking the UI
this.editForm = {
first_name: '',
last_name: '',

View File

@ -260,6 +260,19 @@ export default {
},
methods: {
async updateMeeting(updatedMeeting) {
// Define Toast configuration with SweetAlert2
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 {
this.meetings = this.meetings.map((meeting) =>
meeting.id === updatedMeeting.id
@ -278,8 +291,17 @@ export default {
this.$nextTick(() => {
this.refreshSwiper();
});
// Show success Toast
Toast.fire({
icon: 'success',
title: 'جلسه با موفقیت به‌روزرسانی شد',
});
} catch (error) {
alert(`خطا در به‌روزرسانی جلسات: ${error.message}`);
// Show error Toast
Toast.fire({
icon: 'error',
title: `خطا در به‌روزرسانی جلسات: ${error.message}`,
});
}
},
openMeetingInfo(meeting) {
@ -293,6 +315,19 @@ export default {
}
},
async fetchMeetings() {
// Define Toast configuration with SweetAlert2
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 {
let token = localStorage.getItem('token');
if (!token) throw new Error('توکن احراز هویت پیدا نشد');
@ -341,7 +376,11 @@ export default {
this.filterMeetings();
this.refreshSwiper();
} catch (error) {
alert(`خطایی در دریافت جلسات رخ داد: ${error.response?.data?.message || error.message}`);
// Show error Toast
Toast.fire({
icon: 'error',
title: `خطایی در دریافت جلسات رخ داد: ${error.response?.data?.message || error.message}`,
});
}
},
filterMeetings() {
@ -366,6 +405,19 @@ export default {
this.filterMeetings();
},
async refreshToken() {
// Define Toast configuration with SweetAlert2
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.post(`${API_BASE_URL}/refresh_token`, {
refresh_token: localStorage.getItem('refresh_token'),
@ -374,12 +426,29 @@ export default {
localStorage.setItem('token', newToken);
return newToken;
} catch (error) {
alert('لطفاً دوباره وارد شوید');
// Show error Toast and redirect to login
Toast.fire({
icon: 'error',
title: 'لطفاً دوباره وارد شوید',
});
window.location.href = '/login';
throw error;
}
},
async createNewMeeting(meetingData) {
// Define Toast configuration with SweetAlert2
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 {
let token = localStorage.getItem('token');
if (!token) throw new Error('توکن احراز هویت پیدا نشد');
@ -404,9 +473,17 @@ export default {
await new Promise((resolve) => setTimeout(resolve, 500));
await this.fetchMeetings();
this.showModal = false;
alert('جلسه با موفقیت ایجاد شد!');
// Show success Toast
Toast.fire({
icon: 'success',
title: 'جلسه با موفقیت ایجاد شد',
});
} catch (error) {
alert(`خطایی در ایجاد جلسه رخ داد: ${error.response?.data?.message || error.message}`);
// Show error Toast
Toast.fire({
icon: 'error',
title: `خطایی در ایجاد جلسه رخ داد: ${error.response?.data?.message || error.message}`,
});
}
},
},

View File

@ -96,8 +96,8 @@ export default {
],
activeSharingFilter: 'all',
activeSpaceTypeFilter: 'spaces',
spaces: [], // Initialize the spaces array
selectedSpace: null, // Store the selected space
spaces: [],
selectedSpace: null,
};
},
computed: {
@ -126,14 +126,14 @@ export default {
},
async fetchSpaces() {
try {
const token = localStorage.getItem('token'); // Retrieve the token from localStorage
const token = localStorage.getItem('token');
if (!token) {
console.error('No token found!');
return;
}
const response = await axios.get(
'http://my.xroomapp.com:8000/get_spaces', // API endpoint
'http://my.xroomapp.com:8000/get_spaces',
{
headers: {
Authorization: `Token ${token}`,
@ -142,28 +142,26 @@ export default {
}
);
// Store the spaces data in the spaces array
this.spaces = response.data.spaces.map(space => ({
name: space.name,
img: space.assetBundleRoomId.img, // Assuming 'img' exists in the API response
img: space.assetBundleRoomId.img,
capacity: space.capacity,
type: space.Private ? 'Private' : 'Public', // Adjust if you have a different field
type: space.Private ? 'Private' : 'Public',
sharing: space.Private ? 'private' : 'team',
spaceType: 'spaces',
description: space.description, // Store description from response
description: space.description,
}));
} catch (error) {
console.error('Error fetching spaces:', error);
}
},
handleCreateSpaceSubmit(space) {
// Handle form submission here, space will contain the selected space and the additional fields
console.log('Form submitted with:', space);
this.closeCreateSpaceModal(); // Close the modal after submission
this.closeCreateSpaceModal();
},
},
mounted() {
this.fetchSpaces(); // Fetch spaces when the component is mounted
this.fetchSpaces();
},
};
</script>

View File

@ -585,7 +585,7 @@ export default {
}
.file-card, .swiper-file-card {
width: calc(33.333% - .67rem);
width: 23.7%;
border: 1px solid #b8c0cb;
border-radius: 16px;
background: #fff;
@ -740,16 +740,16 @@ export default {
.file-card {
border-radius: 16px;
padding: .5rem .5rem 1rem;
padding: 6px;
}
.file-image {
height: 190px;
border-radius: 15px;
border-radius: 12px;
}
.file-pdf, .file-video, .file-glb, .file-other {
width: 100%;
width: 70%;
}
.file-card-info {
@ -757,8 +757,8 @@ export default {
}
.file-title {
color: #444d5a;
font-size: 1.25rem;
color: #101010;
font-size: 19px;
}
.file-meta svg {

View File

@ -16,175 +16,209 @@
</template>
<script>
import axios from '@/axios';
export default {
name: 'ChangeAvatar',
components: {
import axios from '@/axios';
export default {
name: 'ChangeAvatar',
components: {},
data() {
return {
subdomain: 'xroom',
avatarUrl: '',
frame: null,
saving: false,
userData: {
user: { first_name: '', last_name: '' },
},
maleAvatars: [
{ id: 1, name: 'مرد ۱', src: 'http://194.62.43.230:8000/media/2025/5/5/men1.glb' },
{ id: 2, name: 'مرد ۲', src: 'http://194.62.43.230:8000/media/2025/5/5/men1.glb' },
{ id: 7, name: 'مرد ۳', src: 'http://194.62.43.230:8000/media/2025/5/5/men1.glb' },
],
femaleAvatars: [
{ id: 4, name: 'زن ۱', src: 'http://194.62.43.230:8000/media/2025/5/5/men1.glb' },
{ id: 10, name: 'زن ۳', src: 'http://194.62.43.230:8000/media/2025/5/5/men1.glb' },
],
baseUrl: 'http://194.62.43.230:8000',
};
},
computed: {
iframeSrc() {
return `https://${this.subdomain}.readyplayer.me/avatar?frameApi`;
},
data() {
return {
subdomain: 'xroom',
avatarUrl: '',
frame: null,
saving: false,
userData: {
user: { first_name: '', last_name: '' }
},
maleAvatars: [
{ id: 1, name: 'مرد ۱', src: 'http://194.62.43.230:8000/media/2025/5/5/men1.glb' },
{ id: 2, name: 'مرد ۲', src: 'http://194.62.43.230:8000/media/2025/5/5/men1.glb' },
{ id: 7, name: 'مرد ۳', src: 'http://194.62.43.230:8000/media/2025/5/5/men1.glb' },
],
femaleAvatars: [
{ id: 4, name: 'زن ۱', src: 'http://194.62.43.230:8000/media/2025/5/5/men1.glb' },
{ id: 10, name: 'زن ۳', src: 'http://194.62.43.230:8000/media/2025/5/5/men1.glb' },
],
baseUrl: 'http://194.62.43.230:8000'
};
},
computed: {
iframeSrc() {
return `https://${this.subdomain}.readyplayer.me/avatar?frameApi`;
}
},
mounted() {
this.frame = document.getElementById('frame');
window.addEventListener('message', this.subscribe);
document.addEventListener('message', this.subscribe);
// Load existing avatar if available
this.loadUserData();
},
beforeUnmount() {
window.removeEventListener('message', this.subscribe);
document.removeEventListener('message', this.subscribe);
},
methods: {
async saveAvatarUrl(glbUrl) {
},
mounted() {
this.frame = document.getElementById('frame');
window.addEventListener('message', this.subscribe);
document.addEventListener('message', this.subscribe);
this.loadUserData();
},
beforeUnmount() {
window.removeEventListener('message', this.subscribe);
document.removeEventListener('message', this.subscribe);
},
methods: {
async saveAvatarUrl(glbUrl) {
try {
const customer = JSON.parse(localStorage.getItem('customer') || '{}');
const payload = {
profile_glb_url: glbUrl
profile_glb_url: glbUrl,
};
// If profile_img is null, set it to the thumbnail of the GLB
if (!customer.profile_img) {
payload.profile_img = this.getAvatarThumbnail(glbUrl);
}
const response = await axios.post(`${this.baseUrl}/editProfile/`, payload, {
headers: {
'Content-Type': 'application/json'
}
'Content-Type': 'application/json',
},
});
// Update local storage
if (!customer.profile_img) {
customer.profile_img = payload.profile_img;
}
customer.profile_glb_url = glbUrl;
localStorage.setItem('customer', JSON.stringify(customer));
return response.data;
} catch (error) {
console.error('Error saving avatar URL:', error);
throw error;
}
},
getAvatarThumbnail(glbUrl) {
// Replace .glb with .png for thumbnail
// Adjust this based on your actual thumbnail URLs
if (glbUrl.includes('readyplayer.me')) {
// For Ready Player Me avatars, use their thumbnail service
return glbUrl.replace('.glb', '.png');
}
return glbUrl.replace('.glb', '.png') || 'https://i.imgur.com/QbXfV6C.png';
},
loadUserData() {
const customer = JSON.parse(localStorage.getItem('customer') || '{}');
if (customer.profile_glb_url) {
this.avatarUrl = customer.profile_glb_url;
}
},
async subscribe(event) {
const json = this.parse(event);
if (json?.source !== 'readyplayerme') {
return;
}
if (json.eventName === 'v1.frame.ready') {
this.frame.contentWindow.postMessage(
JSON.stringify({
target: 'readyplayerme',
type: 'subscribe',
eventName: 'v1.**'
}),
'*'
);
}
if (json.eventName === 'v1.avatar.exported') {
this.saving = true;
try {
console.log(`Avatar URL: ${json.data.url}`);
this.avatarUrl = json.data.url;
this.frame.hidden = true;
// Save the avatar URL to your backend
await this.saveAvatarUrl(json.data.url);
alert('آواتار با موفقیت ذخیره شد');
this.$router.push('/dashboard');
loadUserData() {
const customer = JSON.parse(localStorage.getItem('customer') || '{}');
if (customer.profile_glb_url) {
this.avatarUrl = customer.profile_glb_url;
}
},
async subscribe(event) {
const json = this.parse(event);
if (json?.source !== 'readyplayerme') {
return;
}
if (json.eventName === 'v1.frame.ready') {
this.frame.contentWindow.postMessage(
JSON.stringify({
target: 'readyplayerme',
type: 'subscribe',
eventName: 'v1.**',
}),
'*'
);
}
if (json.eventName === 'v1.avatar.exported') {
// Define Toast configuration
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;
},
});
} catch (error) {
console.error('Error saving avatar:', error);
alert('خطا در ذخیره آواتار');
} finally {
this.saving = false;
}
}
},
parse(event) {
try {
return JSON.parse(event.data);
} catch (error) {
return null;
}
},
openAvatarEditor() {
this.frame.hidden = false;
},
async selectAvatar(avatar) {
this.saving = true;
try {
await this.saveAvatarUrl(avatar.src);
this.avatarUrl = avatar.src;
alert('آواتار با موفقیت انتخاب شد');
this.$router.push('/dashboard');
console.log(`Avatar URL: ${json.data.url}`);
this.avatarUrl = json.data.url;
this.frame.hidden = true;
await this.saveAvatarUrl(json.data.url);
// Show success Toast
Toast.fire({
icon: 'success',
title: 'آواتار با موفقیت ذخیره شد',
});
this.$router.push('/dashboard');
} catch (error) {
console.error('Error selecting avatar:', error);
alert(error.response?.data?.detail || error.message || 'خطا در انتخاب آواتار');
// Show error Toast
Toast.fire({
icon: 'error',
title: error.response?.data?.detail || 'خطا در ذخیره آواتار',
});
console.error('Error saving avatar:', error);
} finally {
this.saving = false;
}
},
async fetchUserData() {
try {
const response = await axios.get('/getInfo');
this.userData = response.data;
} catch (error) {
console.error('Error fetching user data:', error);
}
}
}
};
</script>
},
parse(event) {
try {
return JSON.parse(event.data);
} catch (error) {
return null;
}
},
openAvatarEditor() {
this.frame.hidden = false;
},
async selectAvatar(avatar) {
// Define Toast configuration
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;
try {
await this.saveAvatarUrl(avatar.src);
this.avatarUrl = avatar.src;
// Show success Toast
Toast.fire({
icon: 'success',
title: 'آواتار با موفقیت انتخاب شد',
});
this.$router.push('/dashboard');
} catch (error) {
// Show error Toast with specific message
Toast.fire({
icon: 'error',
title: error.response?.data?.detail || 'خطا در انتخاب آواتار',
});
console.error('Error selecting avatar:', error);
} finally {
this.saving = false;
}
},
async fetchUserData() {
try {
const response = await axios.get('/getInfo');
this.userData = response.data;
} catch (error) {
console.error('Error fetching user data:', error);
}
},
},
};
</script>
<style scoped>
/* Previous styles remain the same, add these new styles */

View File

@ -63,6 +63,7 @@
</div>
</template>
<script>
import TeamUser from '@/components/TeamUser.vue';
import BuySubscription from '@/components/BuySubscription.vue';
@ -82,8 +83,8 @@ export default {
teamMemberCapacity: 0,
subscriptionCount: 0,
hasActiveSubscription: false,
hasExpiredSubscription: false, // جدید: بررسی اشتراک منقضیشده
subscriptionEndTime: null, // جدید: ذخیره تاریخ انقضای اشتراک
hasExpiredSubscription: false,
subscriptionEndTime: null,
teamId: null,
subscriptionId: null,
isBillingModalVisible: false,
@ -107,16 +108,46 @@ export default {
this.activeTab = tabName;
},
async fetchTeamData() {
// Define Toast configuration for SweetAlert2
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 this.axiosGet('/get_team');
const team = response.data.teams[0];
this.teamId = team?.id || null;
} catch (error) {
// Log and show error Toast
console.error('Error fetching team data:', error);
alert('خطا در بارگذاری اطلاعات تیم.');
Toast.fire({
icon: 'error',
title: 'خطا در بارگذاری اطلاعات تیم.',
});
}
},
async fetchTeamMemberInfo() {
// Define Toast configuration for SweetAlert2
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 this.axiosGet('/get_all_team_members');
this.userList = response.data.members.map(member => ({
@ -128,28 +159,62 @@ export default {
}));
this.teamMemberCapacity = response.data.members.length;
} catch (error) {
// Log and show error Toast
console.error('Error fetching team members:', error);
alert('خطا در بارگذاری اطلاعات اعضای تیم.');
Toast.fire({
icon: 'error',
title: 'خطا در بارگذاری اطلاعات اعضای تیم.',
});
}
},
async fetchUserData() {
// Define Toast configuration for SweetAlert2
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 this.axiosGet('/get_user_subscriptions');
const subscriptions = response.data.subscriptions || [];
this.subscriptionCount = subscriptions.reduce((total, sub) => total + sub.user_count, 0);
this.subscriptionId = subscriptions[0]?.id || null;
this.subscriptionEndTime = subscriptions[0]?.endTime || null; // جدید: تاریخ انقضا
this.subscriptionEndTime = subscriptions[0]?.endTime || null;
const now = new Date();
const isExpiredByTime = this.subscriptionEndTime && new Date(this.subscriptionEndTime) < now;
const isExpiredByCapacity = this.subscriptionCount <= this.teamMemberCapacity;
this.hasActiveSubscription = subscriptions.length > 0 && !isExpiredByTime && !isExpiredByCapacity;
this.hasExpiredSubscription = subscriptions.length > 0 && (isExpiredByTime || isExpiredByCapacity);
} catch (error) {
// Log and show error Toast
console.error('Error fetching user data:', error);
alert('خطا در بارگذاری اطلاعات اشتراک.');
Toast.fire({
icon: 'error',
title: 'خطا در بارگذاری اطلاعات اشتراک.',
});
}
},
async handlePaymentSuccess({ subscriptionId }) {
// Define Toast configuration for SweetAlert2
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 {
this.subscriptionId = subscriptionId;
await Promise.all([
@ -160,14 +225,26 @@ export default {
if (!this.teamId && this.subscriptionId) {
await this.createTeam();
alert('اشتراک و تیم به درستی ساخته شد.');
// Show success Toast
Toast.fire({
icon: 'success',
title: 'اشتراک و تیم با موفقیت ساخته شد.',
});
} else if (this.teamId) {
alert('تیم از قبل وجود دارد.');
// Show message if team already exists
Toast.fire({
icon: 'info',
title: 'تیم از قبل وجود دارد.',
});
}
this.activeTab = 'membership';
} catch (error) {
// Log and show error Toast
console.error('Error handling payment success:', error);
alert('خطا در پردازش پرداخت یا ساخت تیم.');
Toast.fire({
icon: 'error',
title: 'خطا در پردازش پرداخت یا ساخت تیم.',
});
}
},
async createTeam() {
@ -181,13 +258,34 @@ export default {
await this.fetchTeamData();
},
async submitNewUser(newUser) {
// Define Toast configuration for SweetAlert2
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;
},
});
if (this.subscriptionCount - this.teamMemberCapacity <= 0) {
alert('اشتراک فعالی ندارید , اشتراک تهیه نمایید.');
// Show error if no active subscription
Toast.fire({
icon: 'warning',
title: 'اشتراک فعالی ندارید، لطفاً اشتراک تهیه کنید.',
});
this.activeTab = 'buy-subscription';
return;
}
if (!this.teamId) {
alert('خطا: اطلاعات تیم یافت نشد.');
// Show error if team ID is missing
Toast.fire({
icon: 'error',
title: 'خطا: اطلاعات تیم یافت نشد.',
});
return;
}
try {
@ -200,10 +298,18 @@ export default {
});
this.teamMemberCapacity++;
await this.fetchTeamMemberInfo();
alert('کاربر با موفقیت اضافه شد.');
// Show success Toast
Toast.fire({
icon: 'success',
title: 'کاربر با موفقیت اضافه شد.',
});
} catch (error) {
// Log and show error Toast
console.error('Error adding user:', error);
alert('خطا در اضافه کردن کاربر.');
Toast.fire({
icon: 'error',
title: 'خطا در اضافه کردن کاربر.',
});
}
},
handleTeamData(data) {
@ -211,14 +317,14 @@ export default {
},
async axiosGet(endpoint) {
const token = localStorage.getItem('token');
if (!token) throw new Error('توکن احراز هویت یافت نشد.');
if (!token) throw new Error('Authentication token not found.');
return await axios.get(`${this.baseUrl}${endpoint}`, {
headers: { Authorization: `Token ${token}`, 'Content-Type': 'application/json' },
});
},
async axiosPost(endpoint, data) {
const token = localStorage.getItem('token');
if (!token) throw new Error('توکن احراز هویت یافت نشد.');
if (!token) throw new Error('Authentication token not found.');
return await axios.post(`${this.baseUrl}${endpoint}`, data, {
headers: { Authorization: `Token ${token}`, 'Content-Type': 'application/json' },
});
@ -232,7 +338,6 @@ export default {
};
</script>
<style scoped>
.section-title {