mirror of
https://github.com/Dadechin/XRoomDashboardFront.git
synced 2025-07-02 00:04:35 +00:00
add spaces API && fix APIs in Teams
This commit is contained in:
parent
d8a0da9986
commit
8f96b6a571
|
@ -1,4 +1,3 @@
|
|||
// src/axios.js
|
||||
import axios from 'axios';
|
||||
|
||||
const instance = axios.create({
|
||||
|
|
|
@ -179,7 +179,6 @@ export default {
|
|||
this.selectedPlan = null;
|
||||
this.$emit('payment-success');
|
||||
} catch (error) {
|
||||
console.error('خطا در ارسال اطلاعات اشتراک:', error);
|
||||
alert('خطا در ثبت اشتراک. لطفاً دوباره تلاش کنید.');
|
||||
}
|
||||
},
|
||||
|
|
|
@ -171,7 +171,7 @@
|
|||
type="number"
|
||||
v-model.number="form.startHour"
|
||||
min="0"
|
||||
max="24"
|
||||
max="23"
|
||||
required
|
||||
/>
|
||||
<button type="button" @click="decrementTime('startHour')">
|
||||
|
@ -259,7 +259,7 @@
|
|||
type="number"
|
||||
v-model.number="form.endHour"
|
||||
min="0"
|
||||
max="24"
|
||||
max="23"
|
||||
required
|
||||
/>
|
||||
<button type="button" @click="decrementTime('endHour')">
|
||||
|
@ -284,9 +284,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label style="font-size: 19px; font-weight: 600;">اتاقهای جلسات</label>
|
||||
<label style="font-size: 19px; font-weight: 600;">اتاق جلسه</label>
|
||||
<div class="rooms-selecter">
|
||||
<span>{{ form.selectedRooms.length }} انتخاب شده</span>
|
||||
<span>{{ form.selectedRoom ? '0 اتاق انتخاب شده' : '0 اتاق انتخاب شده' }}</span>
|
||||
<button type="button" @click="openRoomSelection" style="cursor: pointer;">انتخاب اتاق جلسه</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -297,8 +297,8 @@
|
|||
میتوانید به مجری اجازه بدهید تا ابزارهایی برای مدیریت این جلسه و همچنین ابزارهایی برای مدیریت مجوزها در طول جلسه به او بدهد.
|
||||
</span>
|
||||
</div>
|
||||
<div class="presenter">
|
||||
<div style="display: flex;align-items: center;height: 100%;">
|
||||
<div class="presenter">
|
||||
<div style="display: flex; align-items: center; height: 100%;">
|
||||
<div class="avatar-wrapper">
|
||||
<img class="user-avatar" :src="profileIcon" />
|
||||
</div>
|
||||
|
@ -361,7 +361,7 @@
|
|||
<RoomSelectionModal
|
||||
:is-open="isRoomSelectionOpen"
|
||||
@close="isRoomSelectionOpen = false"
|
||||
@submit-rooms="handleRoomSelection"
|
||||
@submit-room="handleRoomSelection"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
@ -392,7 +392,7 @@ export default {
|
|||
startMinute: 0,
|
||||
endHour: 18,
|
||||
endMinute: 0,
|
||||
selectedRooms: [],
|
||||
selectedRoom: null,
|
||||
},
|
||||
participants: [],
|
||||
newParticipantPhone: '',
|
||||
|
@ -402,6 +402,10 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
customer() {
|
||||
// دریافت اطلاعات کاربر از localStorage با کلید customer
|
||||
return JSON.parse(localStorage.getItem('customer') || '{}');
|
||||
},
|
||||
fullName() {
|
||||
const user = JSON.parse(localStorage.getItem('user') || '{}');
|
||||
return user.first_name && user.last_name
|
||||
|
@ -409,15 +413,18 @@ export default {
|
|||
: 'کاربر مهمان';
|
||||
},
|
||||
userPhone() {
|
||||
return '09123456789'; // شماره تلفن کاربر اصلی (میتوانید از localStorage یا منبع دیگری بگیرید)
|
||||
return 3;
|
||||
},
|
||||
userRole() {
|
||||
return 'مجری';
|
||||
return this.customer.semat || 'مجری';
|
||||
},
|
||||
profileIcon() {
|
||||
const customer = JSON.parse(localStorage.getItem('customer') || '{}');
|
||||
return customer.profile_img || this.defaultProfileIcon;
|
||||
return this.customer.profile_img || this.defaultProfileIcon;
|
||||
},
|
||||
userId() {
|
||||
const customer = JSON.parse(localStorage.getItem('customer') || '{}');
|
||||
return customer.id || null;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isOpen(newVal) {
|
||||
|
@ -442,8 +449,8 @@ export default {
|
|||
openRoomSelection() {
|
||||
this.isRoomSelectionOpen = true;
|
||||
},
|
||||
handleRoomSelection(rooms) {
|
||||
this.form.selectedRooms = rooms;
|
||||
handleRoomSelection(room) {
|
||||
this.form.selectedRoom = room;
|
||||
this.isRoomSelectionOpen = false;
|
||||
},
|
||||
addParticipant() {
|
||||
|
@ -471,8 +478,7 @@ export default {
|
|||
this.participants = this.participants.filter((p) => p.phone !== phone);
|
||||
},
|
||||
validatePhone(phone) {
|
||||
// اعتبارسنجی شماره تلفن (مثال: فرمت شماره تلفن ایرانی)
|
||||
return /^09[0-9]{9}$/.test(phone); // فرمت: 09XXXXXXXXX (11 رقم، شروع با 09)
|
||||
return /^09[0-9]{9}$/.test(phone);
|
||||
},
|
||||
closeModal() {
|
||||
this.$emit('close');
|
||||
|
@ -487,7 +493,7 @@ export default {
|
|||
startMinute: 0,
|
||||
endHour: 18,
|
||||
endMinute: 0,
|
||||
selectedRooms: [],
|
||||
selectedRoom: null,
|
||||
};
|
||||
this.participants = [];
|
||||
this.newParticipantPhone = '';
|
||||
|
@ -516,7 +522,7 @@ export default {
|
|||
this.form.endMinute--;
|
||||
}
|
||||
},
|
||||
handleSubmit() {
|
||||
async handleSubmit() {
|
||||
if (!this.form.title || !this.form.date) {
|
||||
this.error = 'لطفاً نام جلسه و تاریخ را وارد کنید.';
|
||||
return;
|
||||
|
@ -540,39 +546,36 @@ export default {
|
|||
second: 0,
|
||||
})
|
||||
.toISOString();
|
||||
const endDateTime = momentDate
|
||||
.clone()
|
||||
.set({
|
||||
hour: this.form.endHour,
|
||||
minute: this.form.endMinute,
|
||||
second: 0,
|
||||
})
|
||||
.toISOString();
|
||||
const meetingData = {
|
||||
title: this.form.title,
|
||||
description: this.form.description,
|
||||
startDateTime,
|
||||
endDateTime,
|
||||
rooms: this.form.selectedRooms,
|
||||
participants: [
|
||||
...(this.userPhone ? [{ phone: this.userPhone, role: this.userRole }] : []),
|
||||
...this.participants.map((p) => ({
|
||||
phone: p.phone,
|
||||
role: p.role,
|
||||
})),
|
||||
],
|
||||
};
|
||||
console.log('دادههای جلسه:', meetingData);
|
||||
this.$emit('submit', meetingData);
|
||||
this.closeModal();
|
||||
|
||||
try {
|
||||
const userIds = [
|
||||
...(this.userPhone ? [this.userPhone] : []),
|
||||
...this.participants.map((p) => p.phone),
|
||||
];
|
||||
|
||||
const meetingData = {
|
||||
name: this.form.title,
|
||||
description: this.form.description,
|
||||
date_time: startDateTime,
|
||||
space: this.form.selectedRoom ? this.form.selectedRoom.id : null,
|
||||
asset_bundle: 1,
|
||||
use_space: !!this.form.selectedRoom,
|
||||
user_ids: userIds,
|
||||
};
|
||||
|
||||
console.log('دادههای ارسالی به API:', JSON.stringify(meetingData, null, 2));
|
||||
|
||||
this.$emit('create-meeting', meetingData);
|
||||
this.closeModal();
|
||||
} catch (error) {
|
||||
this.error = `خطا در آمادهسازی دادهها: ${error.message}`;
|
||||
console.error('خطا در handleSubmit:', error);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
<style scoped>
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
|
|
|
@ -208,9 +208,6 @@ export default {
|
|||
updateBillingInfo(newBillingInfo) {
|
||||
this.billingInfo = { ...newBillingInfo };
|
||||
},
|
||||
manageMemberships() {
|
||||
console.log('مدیریت عضویتها');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div v-if="isOpen" class="modal-overlay" @click="cancel">
|
||||
<div class="modal-content" @click.stop>
|
||||
<div class="popUp-header">
|
||||
<h2>اتاقهای این جلسه را انتخاب کنید</h2>
|
||||
<h2>اتاق این جلسه را انتخاب کنید</h2>
|
||||
<button @click="cancel">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
@ -32,15 +32,15 @@
|
|||
</div>
|
||||
<div class="popUp-title">
|
||||
<h2>فضاها</h2>
|
||||
<span>اجازه دسترسی به این اتاقهای تیم را بدهید</span>
|
||||
<span>یک اتاق برای این جلسه انتخاب کنید</span>
|
||||
</div>
|
||||
<div class="rooms-list">
|
||||
<div class="rooms-list" v-if="rooms.length > 0">
|
||||
<div
|
||||
v-for="room in rooms"
|
||||
:key="room.id"
|
||||
class="room-item"
|
||||
:class="{ selected: selectedRooms.includes(room.id) }"
|
||||
@click="toggleRoomSelection(room.id)"
|
||||
:class="{ selected: selectedRoom === room.id }"
|
||||
@click="selectRoom(room.id)"
|
||||
>
|
||||
<img
|
||||
:src="room.image"
|
||||
|
@ -48,6 +48,7 @@
|
|||
class="room-image"
|
||||
width="120px"
|
||||
height="120px"
|
||||
@error="room.image = 'https://via.placeholder.com/150'"
|
||||
/>
|
||||
<div class="room-details" style="margin-right: 10px;">
|
||||
<h3 class="room-title">{{ room.name }}</h3>
|
||||
|
@ -164,145 +165,149 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="Temporaryrooms.length > 0">
|
||||
<div class="popUp-title">
|
||||
<h2>اتاقهای موقت</h2>
|
||||
<span>اتاقهای موقت ایجادشده برای این جلسه</span>
|
||||
<div v-else>
|
||||
<span>هیچ فضایی یافت نشد.</span>
|
||||
</div>
|
||||
<div class="temporary-rooms-list">
|
||||
<div
|
||||
v-for="room in Temporaryrooms"
|
||||
:key="room.id"
|
||||
class="room-item"
|
||||
:class="{ selected: selectedRooms.includes(room.id) }"
|
||||
@click="toggleRoomSelection(room.id)"
|
||||
>
|
||||
<img
|
||||
:src="room.image"
|
||||
alt="Room Image"
|
||||
class="room-image"
|
||||
width="120px"
|
||||
height="120px"
|
||||
/>
|
||||
<div class="room-details" style="margin-right: 10px;">
|
||||
<h3 class="room-title">{{ room.name }}</h3>
|
||||
<p class="room-capacity">
|
||||
<span style="margin-left: 4px;">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="17"
|
||||
viewBox="0 0 16 17"
|
||||
fill="none"
|
||||
>
|
||||
<g clip-path="url(#clip0_622_1334)">
|
||||
<div v-if="temporaryRooms.length > 0">
|
||||
<div class="popUp-title">
|
||||
<h2>اتاقهای موقت</h2>
|
||||
<span>اتاقهای موقت ایجادشده برای این جلسه</span>
|
||||
</div>
|
||||
<div class="temporary-rooms-list">
|
||||
<div
|
||||
v-for="room in temporaryRooms"
|
||||
:key="room.id"
|
||||
class="room-item"
|
||||
:class="{ selected: selectedRoom === room.id }"
|
||||
@click="selectRoom(room.id)"
|
||||
>
|
||||
<img
|
||||
:src="room.image"
|
||||
alt="Room Image"
|
||||
class="room-image"
|
||||
width="120px"
|
||||
height="120px"
|
||||
@error="room.image = 'https://via.placeholder.com/150'"
|
||||
/>
|
||||
<div class="room-details" style="margin-right: 10px;">
|
||||
<h3 class="room-title">{{ room.name }}</h3>
|
||||
<p class="room-capacity">
|
||||
<span style="margin-left: 4px;">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="17"
|
||||
viewBox="0 0 16 17"
|
||||
fill="none"
|
||||
>
|
||||
<g clip-path="url(#clip0_622_1334)">
|
||||
<path
|
||||
d="M3.33203 5.16667C3.33203 5.87391 3.61298 6.55219 4.11308 7.05228C4.61318 7.55238 5.29145 7.83333 5.9987 7.83333C6.70594 7.83333 7.38422 7.55238 7.88432 7.05228C8.38441 6.55219 8.66536 5.87391 8.66536 5.16667C8.66536 4.45942 8.38441 3.78115 7.88432 3.28105C7.38422 2.78095 6.70594 2.5 5.9987 2.5C5.29145 2.5 4.61318 2.78095 4.11308 3.28105C3.61298 3.78115 3.33203 4.45942 3.33203 5.16667Z"
|
||||
stroke="#718096"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M2 14.5V13.1667C2 12.4594 2.28095 11.7811 2.78105 11.281C3.28115 10.781 3.95942 10.5 4.66667 10.5H7.33333C8.04058 10.5 8.71885 10.781 9.21895 11.281C9.71905 11.7811 10 12.4594 10 13.1667V14.5"
|
||||
stroke="#718096"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M10.668 2.58667C11.2416 2.73354 11.75 3.06714 12.1131 3.53488C12.4761 4.00262 12.6732 5.17 12.6732 5.17C12.6732 5.76212 12.4761 6.33739 12.1131 6.80513C11.75 7.27287 11.2416 7.60647 10.668 7.75334"
|
||||
stroke="#718096"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M14 14.5V13.1666C13.9966 12.5781 13.7986 12.0072 13.4368 11.5429C13.0751 11.0786 12.5699 10.7471 12 10.6"
|
||||
stroke="#718096"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_622_1334">
|
||||
<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</span>
|
||||
حداکثر: {{ room.capacity }} کاربر
|
||||
</p>
|
||||
<p class="room-type">
|
||||
<span style="margin-left: 4px;">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="17"
|
||||
viewBox="0 0 16 17"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M3.33203 5.16667C3.33203 5.87391 3.61298 6.55219 4.11308 7.05228C4.61318 7.55238 5.29145 7.83333 5.9987 7.83333C6.70594 7.83333 7.38422 7.55238 7.88432 7.05228C8.38441 6.55219 8.66536 5.87391 8.66536 5.16667C8.66536 4.45942 8.38441 3.78115 7.88432 3.28105C7.38422 2.78095 6.70594 2.5 5.9987 2.5C5.29145 2.5 4.61318 2.78095 4.11308 3.28105C3.61298 3.78115 3.33203 4.45942 3.33203 5.16667Z"
|
||||
stroke="#718096"
|
||||
stroke-width="1.5"
|
||||
d="M4 15.1667V3.16671C4 2.81309 4.14048 2.47395 4.39052 2.2239C4.64057 1.97385 4.97971 1.83337 5.33333 1.83337H10.6667C11.0203 1.83337 11.3594 1.97385 11.6095 2.2239C11.8595 2.47395 12 2.81309 12 3.16671V15.1667H4Z"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M2 14.5V13.1667C2 12.4594 2.28095 11.7811 2.78105 11.281C3.28115 10.781 3.95942 10.5 4.66667 10.5H7.33333C8.04058 10.5 8.71885 10.781 9.21895 11.281C9.71905 11.7811 10 12.4594 10 13.1667V14.5"
|
||||
stroke="#718096"
|
||||
stroke-width="1.5"
|
||||
d="M3.9987 8.5H2.66536C2.31174 8.5 1.9726 8.64048 1.72256 8.89052C1.47251 9.14057 1.33203 9.47971 1.33203 9.83333V13.8333C1.33203 14.187 1.47251 14.5261 1.72256 14.7761C1.9726 15.0262 2.31174 15.1667 2.66536 15.1667H3.9987"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M10.668 2.58667C11.2416 2.73354 11.75 3.06714 12.1131 3.53488C12.4761 4.00262 12.6732 5.17 12.6732 5.17C12.6732 5.76212 12.4761 6.33739 12.1131 6.80513C11.75 7.27287 11.2416 7.60647 10.668 7.75334"
|
||||
stroke="#718096"
|
||||
stroke-width="1.5"
|
||||
d="M12 6.5H13.3333C13.687 6.5 14.0261 6.64048 14.2761 6.89052C14.5262 7.14057 14.6667 7.47971 14.6667 7.83333V13.8333C14.6667 14.187 14.5262 14.5261 14.2761 14.7761C14.0261 15.0262 13.687 15.1667 13.3333 15.1667H12"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M14 14.5V13.1666C13.9966 12.5781 13.7986 12.0072 13.4368 11.5429C13.0751 11.0786 12.5699 10.7471 12 10.6"
|
||||
stroke="#718096"
|
||||
stroke-width="1.5"
|
||||
d="M6.66797 4.5H9.33464"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_622_1334">
|
||||
<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</span>
|
||||
حداکثر: {{ room.capacity }} کاربر
|
||||
</p>
|
||||
<p class="room-type">
|
||||
<span style="margin-left: 4px;">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="17"
|
||||
viewBox="0 0 16 17"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M4 15.1667V3.16671C4 2.81309 4.14048 2.47395 4.39052 2.2239C4.64057 1.97385 4.97971 1.83337 5.33333 1.83337H10.6667C11.0203 1.83337 11.3594 1.97385 11.6095 2.2239C11.8595 2.47395 12 2.81309 12 3.16671V15.1667H4Z"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M3.9987 8.5H2.66536C2.31174 8.5 1.9726 8.64048 1.72256 8.89052C1.47251 9.14057 1.33203 9.47971 1.33203 9.83333V13.8333C1.33203 14.187 1.47251 14.5261 1.72256 14.7761C1.9726 15.0262 2.31174 15.1667 2.66536 15.1667H3.9987"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M12 6.5H13.3333C13.687 6.5 14.0261 6.64048 14.2761 6.89052C14.5262 7.14057 14.6667 7.47971 14.6667 7.83333V13.8333C14.6667 14.187 14.5262 14.5261 14.2761 14.7761C14.0261 15.0262 13.687 15.1667 13.3333 15.1667H12"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M6.66797 4.5H9.33464"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M6.66797 7.16663H9.33464"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M6.66797 9.83337H9.33464"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M6.66797 12.5H9.33464"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
{{ room.type }}
|
||||
</p>
|
||||
<path
|
||||
d="M6.66797 7.16663H9.33464"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M6.66797 9.83337H9.33464"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M6.66797 12.5H9.33464"
|
||||
stroke="#3A57E8"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
{{ room.type }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="popUp-title">
|
||||
<h2>ایجاد اتاق موقت</h2>
|
||||
<span>اتاقهای موقت را فقط برای این جلسه ایجاد کنید</span>
|
||||
<span>اتاق موقت را فقط برای این جلسه ایجاد کنید</span>
|
||||
</div>
|
||||
<div class="temporary-room-form">
|
||||
<form @submit.prevent="createTemporaryRoom">
|
||||
|
@ -332,13 +337,15 @@
|
|||
</div>
|
||||
<div class="form-actions">
|
||||
<button type="button" class="cancel-button" @click="cancel">لغو</button>
|
||||
<button type="button" class="submit-button" @click="submitRooms">تأیید</button>
|
||||
<button type="button" class="submit-button" @click="submitRoom" :disabled="!selectedRoom">تأیید</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
|
||||
export default {
|
||||
name: 'RoomSelectionModal',
|
||||
props: {
|
||||
|
@ -349,110 +356,77 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
rooms: [
|
||||
{
|
||||
id: 1,
|
||||
image: require('@/assets/img/img.jpg'),
|
||||
name: 'Interview room 1',
|
||||
capacity: 33,
|
||||
type: 'فضا تیم',
|
||||
isTemporary: false, // اضافه کردن ویژگی isTemporary
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
image: require('@/assets/img/img.jpg'),
|
||||
name: 'Interview room 2',
|
||||
capacity: 24,
|
||||
type: 'آموزشی',
|
||||
isTemporary: false,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
image: require('@/assets/img/img.jpg'),
|
||||
name: 'Interview room 3',
|
||||
capacity: 60,
|
||||
type: 'جلسه تیمی',
|
||||
isTemporary: false,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
image: require('@/assets/img/img.jpg'),
|
||||
name: 'Interview room 4',
|
||||
capacity: 33,
|
||||
type: 'فضا تیم',
|
||||
isTemporary: false,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
image: require('@/assets/img/img.jpg'),
|
||||
name: 'Interview room 5',
|
||||
capacity: 24,
|
||||
type: 'آموزشی',
|
||||
isTemporary: false,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
image: require('@/assets/img/img.jpg'),
|
||||
name: 'Interview room 6',
|
||||
capacity: 60,
|
||||
type: 'جلسه تیمی',
|
||||
isTemporary: false,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
image: require('@/assets/img/img.jpg'),
|
||||
name: 'Interview room 7',
|
||||
capacity: 33,
|
||||
type: 'فضا تیم',
|
||||
isTemporary: false,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
image: require('@/assets/img/img.jpg'),
|
||||
name: 'Interview room 8',
|
||||
capacity: 24,
|
||||
type: 'آموزشی',
|
||||
isTemporary: false,
|
||||
},
|
||||
],
|
||||
Temporaryrooms: [],
|
||||
selectedRooms: [],
|
||||
rooms: [],
|
||||
temporaryRooms: [],
|
||||
selectedRoom: null,
|
||||
newTempRoom: {
|
||||
name: '',
|
||||
capacity: 0,
|
||||
type: '',
|
||||
image: null,
|
||||
},
|
||||
error: null,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.fetchSpaces();
|
||||
},
|
||||
methods: {
|
||||
toggleRoomSelection(roomId) {
|
||||
if (this.selectedRooms.includes(roomId)) {
|
||||
this.selectedRooms = this.selectedRooms.filter((id) => id !== roomId);
|
||||
} else {
|
||||
this.selectedRooms.push(roomId);
|
||||
async fetchSpaces() {
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
if (!token) {
|
||||
this.error = 'توکن احراز هویت پیدا نشد';
|
||||
console.error('توکن احراز هویت پیدا نشد');
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await axios.get('http://my.xroomapp.com:8000/get_space', {
|
||||
headers: {
|
||||
Authorization: `Token ${token.trim()}`,
|
||||
},
|
||||
});
|
||||
|
||||
console.log('فضاها:', response.data.spaces);
|
||||
this.rooms = response.data.spaces.map((space) => {
|
||||
const imageUrl = space.assetBundleRoomId?.img
|
||||
? `http://my.xroomapp.com:8000${space.assetBundleRoomId.img}`
|
||||
: 'https://via.placeholder.com/150';
|
||||
return {
|
||||
id: space.id,
|
||||
image: imageUrl,
|
||||
name: space.name,
|
||||
capacity: space.capacity,
|
||||
type: space.description || 'فضا',
|
||||
isTemporary: false,
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('خطا در دریافت فضاها:', error);
|
||||
this.error = 'خطا در بارگذاری لیست اتاقها';
|
||||
if (error.response && error.response.status === 403) {
|
||||
alert('لطفاً دوباره وارد شوید');
|
||||
window.location.href = '/login';
|
||||
}
|
||||
}
|
||||
},
|
||||
selectRoom(roomId) {
|
||||
this.selectedRoom = roomId;
|
||||
},
|
||||
cancel() {
|
||||
this.$emit('close');
|
||||
this.selectedRooms = [];
|
||||
this.selectedRoom = null;
|
||||
},
|
||||
submitRooms() {
|
||||
const selectedRoomDetails = [
|
||||
...this.rooms,
|
||||
...this.Temporaryrooms,
|
||||
]
|
||||
.filter((room) => this.selectedRooms.includes(room.id))
|
||||
.map((room) => ({
|
||||
id: room.id,
|
||||
name: room.name,
|
||||
capacity: room.capacity,
|
||||
type: room.type,
|
||||
image: room.image,
|
||||
isTemporary: room.isTemporary,
|
||||
}));
|
||||
this.$emit('submit-rooms', selectedRoomDetails);
|
||||
this.selectedRooms = [];
|
||||
submitRoom() {
|
||||
if (!this.selectedRoom) {
|
||||
alert('لطفاً یک اتاق انتخاب کنید.');
|
||||
return;
|
||||
}
|
||||
const selectedRoomDetails = [...this.rooms, ...this.temporaryRooms].find(
|
||||
(room) => room.id === this.selectedRoom
|
||||
);
|
||||
this.$emit('submit-room', selectedRoomDetails);
|
||||
this.selectedRoom = null;
|
||||
},
|
||||
handleImageUpload(event) {
|
||||
const file = event.target.files[0];
|
||||
|
@ -462,20 +436,21 @@ export default {
|
|||
},
|
||||
createTemporaryRoom() {
|
||||
const newRoom = {
|
||||
id: this.rooms.length + this.Temporaryrooms.length + 1,
|
||||
image: this.newTempRoom.image || require('@/assets/img/img.jpg'),
|
||||
id: this.rooms.length + this.temporaryRooms.length + 1,
|
||||
image: this.newTempRoom.image || 'https://via.placeholder.com/150',
|
||||
name: this.newTempRoom.name,
|
||||
capacity: this.newTempRoom.capacity,
|
||||
type: this.newTempRoom.type,
|
||||
isTemporary: true,
|
||||
};
|
||||
this.Temporaryrooms.push(newRoom);
|
||||
this.temporaryRooms.push(newRoom);
|
||||
this.newTempRoom = { name: '', capacity: 0, type: '', image: null };
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
|
|
|
@ -236,7 +236,6 @@ export default {
|
|||
width: 72px;
|
||||
height: 72px;
|
||||
border-radius: 12px;
|
||||
object-fit: none;
|
||||
}
|
||||
|
||||
.profile-container {
|
||||
|
|
|
@ -108,6 +108,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
|
||||
export default {
|
||||
name: 'TeamDetails',
|
||||
data() {
|
||||
|
@ -116,6 +118,7 @@ export default {
|
|||
teamName: '',
|
||||
companyName: '',
|
||||
activityType: '',
|
||||
teamId: null,
|
||||
},
|
||||
teamLogo: null,
|
||||
uploadedLogoFile: null,
|
||||
|
@ -124,9 +127,37 @@ export default {
|
|||
{ path: '/img/sample-logo.png', alt: 'نمونه لوگو' },
|
||||
{ path: '/img/sample-logo.png', alt: 'نمونه لوگو' },
|
||||
],
|
||||
baseUrl: 'http://my.xroomapp.com:8000',
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// دریافت اطلاعات تیم در زمان ایجاد کامپوننت
|
||||
this.fetchTeamData();
|
||||
},
|
||||
methods: {
|
||||
/* دریافت اطلاعات تیم از API */
|
||||
async fetchTeamData() {
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
const response = await axios.get(`${this.baseUrl}/get_team`, {
|
||||
headers: {
|
||||
Authorization: `Token ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
const team = response.data.teams[0];
|
||||
if (team) {
|
||||
this.form.teamName = team.name || '';
|
||||
this.form.activityType = team.description || '';
|
||||
this.form.teamId = team.id;
|
||||
} else {
|
||||
alert('هیچ اطلاعاتی برای تیم یافت نشد.');
|
||||
}
|
||||
} catch (error) {
|
||||
alert('خطا در بارگذاری اطلاعات تیم. لطفاً دوباره تلاش کنید.');
|
||||
}
|
||||
},
|
||||
|
||||
handleLogoUpload(event) {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
|
@ -134,8 +165,9 @@ export default {
|
|||
this.uploadedLogoFile = file;
|
||||
}
|
||||
},
|
||||
submitForm() {
|
||||
// Check if there's any data to submit
|
||||
|
||||
/* ارسال فرم برای بهروزرسانی اطلاعات تیم */
|
||||
async submitForm() {
|
||||
const hasFormData = this.form.teamName || this.form.companyName || this.form.activityType;
|
||||
const hasLogo = !!this.uploadedLogoFile;
|
||||
|
||||
|
@ -144,27 +176,41 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
// Prepare data to emit, including only non-empty fields
|
||||
const formData = {};
|
||||
if (this.form.teamName) formData.teamName = this.form.teamName;
|
||||
if (this.form.companyName) formData.companyName = this.form.companyName;
|
||||
if (this.form.activityType) formData.activityType = this.form.activityType;
|
||||
if (hasLogo) formData.teamLogo = this.uploadedLogoFile;
|
||||
const formData = new FormData();
|
||||
if (this.form.teamName) formData.append('name', this.form.teamName);
|
||||
if (this.form.companyName) formData.append('company_name', this.form.companyName);
|
||||
if (this.form.activityType) formData.append('description', this.form.activityType);
|
||||
if (this.uploadedLogoFile) formData.append('logo', this.uploadedLogoFile);
|
||||
|
||||
this.$emit('update:teamData', formData);
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
await axios.patch(`${this.baseUrl}/update_team/${this.form.teamId}/`, formData, {
|
||||
headers: {
|
||||
Authorization: `Token ${token}`,
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
this.$emit('update:teamData', {
|
||||
teamName: this.form.teamName,
|
||||
companyName: this.form.companyName,
|
||||
activityType: this.form.activityType,
|
||||
teamLogo: this.uploadedLogoFile,
|
||||
});
|
||||
alert('اطلاعات تیم با موفقیت بهروزرسانی شد');
|
||||
|
||||
// Reset form and logo
|
||||
this.form = {
|
||||
teamName: '',
|
||||
companyName: '',
|
||||
activityType: '',
|
||||
};
|
||||
this.teamLogo = null;
|
||||
this.uploadedLogoFile = null;
|
||||
// Reset file input
|
||||
const fileInput = this.$refs.fileUpload;
|
||||
if (fileInput) {
|
||||
fileInput.value = '';
|
||||
// ریست فرم و لوگو
|
||||
this.form.teamName = '';
|
||||
this.form.companyName = '';
|
||||
this.form.activityType = '';
|
||||
this.teamLogo = null;
|
||||
this.uploadedLogoFile = null;
|
||||
const fileInput = this.$refs.fileUpload;
|
||||
if (fileInput) {
|
||||
fileInput.value = '';
|
||||
}
|
||||
await this.fetchTeamData();
|
||||
} catch (error) {
|
||||
alert('خطا در بهروزرسانی اطلاعات تیم. لطفاً دوباره تلاش کنید.');
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,69 +1,156 @@
|
|||
<template>
|
||||
<div class="card license-card">
|
||||
<span>لایسنس های قابل استفاده : 0</span>
|
||||
<div class="buy-subscription" @click="goToBuySubscription">
|
||||
<p>خرید اشتراک</p>
|
||||
<span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" viewBox="0 0 24 25" fill="none">
|
||||
<path d="M12 19.5L5 12.5L12 5.5" stroke="#48BB78" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M19 12.5H5" stroke="#48BB78" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<div class="card license-card">
|
||||
<span>لایسنسهای قابل استفاده: {{ remainingCapacity }}</span>
|
||||
<div class="buy-subscription" @click="goToBuySubscription">
|
||||
<p>خرید اشتراک</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="25"
|
||||
viewBox="0 0 24 25"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M12 19.5L5 12.5L12 5.5"
|
||||
stroke="#48BB78"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M19 12.5H5"
|
||||
stroke="#48BB78"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="user-cards">
|
||||
<div class="user-card" v-for="(user, index) in userList" :key="index">
|
||||
<div class="user-card-header">
|
||||
<img :src="user.avatar" class="user-avatar" alt="avatar" />
|
||||
<div class="user-info-box">
|
||||
<div class="user-info-tags">
|
||||
<div class="user-name">{{ user.name }}</div>
|
||||
<div class="user-email">{{ user.email }}</div>
|
||||
</div>
|
||||
<div class="user-activity">
|
||||
<div class="user-role">{{ user.role }}</div>
|
||||
<div class="user-version">{{ user.version }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-footer">
|
||||
<span>اکانت XRoom</span>
|
||||
<div class="user-actions">
|
||||
<button>
|
||||
<i class="icon">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="25"
|
||||
height="25"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M16.666 5.83325H9.16602"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M11.666 14.1667H4.16602"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M14.166 16.6667C15.5467 16.6667 16.666 15.5475 16.666 14.1667C16.666 12.786 15.5467 11.6667 14.166 11.6667C12.7853 11.6667 11.666 12.786 11.666 14.1667C11.666 15.5475 12.7853 16.6667 14.166 16.6667Z"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M5.83398 8.33325C7.2147 8.33325 8.33398 7.21396 8.33398 5.83325C8.33398 4.45254 7.2147 3.33325 5.83398 3.33325C4.45327 3.33325 3.33398 4.45254 3.33398 5.83325C3.33398 7.21396 4.45327 8.33325 5.83398 8.33325Z"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</i>
|
||||
</button>
|
||||
<button>
|
||||
<i class="icon">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="25"
|
||||
height="25"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M2.5 5H17.5"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M15.8327 5V16.6667C15.8327 17.5 14.9993 18.3333 14.166 18.3333H5.83268C4.99935 18.3333 4.16602 17.5 4.16602 16.6667V5"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M6.66602 5.00008V3.33341C6.66602 2.50008 7.49935 1.66675 8.33268 1.66675H11.666C12.4993 1.66675 13.3327 2.50008 13.3327 3.33341V5.00008"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M8.33398 9.16675V14.1667"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M11.666 9.16675V14.1667"
|
||||
stroke="white"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-card add-card" @click="openAddUserModal">
|
||||
<span class="add-text">
|
||||
<span style="font-size: 23px; margin-left: 0.5rem;">+</span> اضافه کردن کاربر جدید
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="user-cards">
|
||||
<div class="user-card" v-for="(user, index) in userList" :key="index">
|
||||
<div class="user-card-header">
|
||||
<img :src="user.avatar" class="user-avatar" alt="avatar" />
|
||||
<div class="user-info-box">
|
||||
<div class="user-info-tags">
|
||||
<div class="user-name">{{ user.name }}</div>
|
||||
<div class="user-email">{{ user.email }}</div>
|
||||
</div>
|
||||
<div class="user-activity">
|
||||
<div class="user-role">{{ user.role }}</div>
|
||||
<div class="user-version">{{ user.version }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-footer">
|
||||
<span>اکانت XRoom</span>
|
||||
<div class="user-actions">
|
||||
<button><i class="icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 20 20" fill="none">
|
||||
<path d="M16.666 5.83325H9.16602" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11.666 14.1667H4.16602" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14.166 16.6667C15.5467 16.6667 16.666 15.5475 16.666 14.1667C16.666 12.786 15.5467 11.6667 14.166 11.6667C12.7853 11.6667 11.666 12.786 11.666 14.1667C11.666 15.5475 12.7853 16.6667 14.166 16.6667Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5.83398 8.33325C7.2147 8.33325 8.33398 7.21396 8.33398 5.83325C8.33398 4.45254 7.2147 3.33325 5.83398 3.33325C4.45327 3.33325 3.33398 4.45254 3.33398 5.83325C3.33398 7.21396 4.45327 8.33325 5.83398 8.33325Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</i></button>
|
||||
<button><i class="icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 20 20" fill="none">
|
||||
<path d="M2.5 5H17.5" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M15.8327 5V16.6667C15.8327 17.5 14.9993 18.3333 14.166 18.3333H5.83268C4.99935 18.3333 4.16602 17.5 4.16602 16.6667V5" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.66602 5.00008V3.33341C6.66602 2.50008 7.49935 1.66675 8.33268 1.66675H11.666C12.4993 1.66675 13.3327 2.50008 13.3327 3.33341V5.00008" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8.33398 9.16675V14.1667" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11.666 9.16675V14.1667" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-card add-card" @click="openAddUserModal">
|
||||
<span class="add-text"><span style="font-size: 23px;margin-left: 0.5rem;">+</span> اضافه کردن کاربر جدید</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<AddUserModal
|
||||
:isVisible="isAddUserModalVisible"
|
||||
@close="closeAddUserModal"
|
||||
@add-user="submitNewUser"
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<!-- Modal -->
|
||||
<AddUserModal
|
||||
:isVisible="isAddUserModalVisible"
|
||||
@close="closeAddUserModal"
|
||||
@add-user="submitNewUser"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -88,15 +175,15 @@ export default {
|
|||
default: 0,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isAddUserModalVisible: false,
|
||||
};
|
||||
computed: {
|
||||
remainingCapacity() {
|
||||
const capacity = this.subscriptionCount - this.teamMemberCapacity;
|
||||
return capacity;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
openAddUserModal() {
|
||||
const remainingCapacity = this.subscriptionCount - this.teamMemberCapacity;
|
||||
if (remainingCapacity <= 0) {
|
||||
if (this.remainingCapacity <= 0) {
|
||||
alert('ظرفیت تیم پر شده است. لطفاً اشتراک جدیدی خریداری کنید.');
|
||||
this.goToBuySubscription();
|
||||
return;
|
||||
|
@ -108,15 +195,21 @@ export default {
|
|||
},
|
||||
submitNewUser(user) {
|
||||
this.$emit('add-user', user);
|
||||
|
||||
this.closeAddUserModal();
|
||||
},
|
||||
goToBuySubscription() {
|
||||
this.$emit('change-tab', 'buy-subscription');
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isAddUserModalVisible: false,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
/* User Info Section */
|
||||
.user-info {
|
||||
|
|
|
@ -1,136 +1,137 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- Description -->
|
||||
<div class="section-description">
|
||||
<div class="section-title">مدیریت جلسات</div>
|
||||
<p class="title-description">
|
||||
با استفاده از جلسات، میتوانید همکاران و کاربران خارجی XRoom را به تیم و اتاقهای خصوصی خود دعوت کنید. شرکتکنندگان جلسه شما میتوانند با استفاده از کد جلسه ایجاد شده در زمانهای معین به جلسه بپیوندند.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Meeting Section -->
|
||||
<div class="meeting-section">
|
||||
<div class="meeting-filters">
|
||||
<div class="search-section">
|
||||
<span style="font-size: 17px; font-weight: 600;">جستجو</span>
|
||||
<div class="search-wrapper">
|
||||
<input
|
||||
type="text"
|
||||
class="search-input"
|
||||
placeholder="جستجو جلسه مدنظر ..."
|
||||
v-model="searchQuery"
|
||||
@input="filterMeetings"
|
||||
/>
|
||||
<button class="search-button">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M7.33333 12.6667C10.2789 12.6667 12.6667 10.2789 12.6667 7.33333C12.6667 4.38781 10.2789 2 7.33333 2C4.38781 2 2 4.38781 2 7.33333C2 10.2789 4.38781 12.6667 7.33333 12.6667Z"
|
||||
stroke="#101010"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M13.9995 14L11.1328 11.1333"
|
||||
stroke="#101010"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-section">
|
||||
<span style="font-size: 17px; font-weight: 600;">فیلتر</span>
|
||||
<div class="filter-buttons">
|
||||
<button
|
||||
:class="{ 'active-filter': activeFilter === 'future', 'disable-filter': activeFilter !== 'future' }"
|
||||
@click="setFilter('future')"
|
||||
>
|
||||
آینده
|
||||
</button>
|
||||
<button
|
||||
:class="{ 'active-filter': activeFilter === 'all', 'disable-filter': activeFilter !== 'all' }"
|
||||
@click="setFilter('all')"
|
||||
>
|
||||
همه
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Meet Discover -->
|
||||
<div :class="filteredMeetings.length === 0 ? 'meet-discover' : 'meetings-container'">
|
||||
<span class="discover-result" v-if="filteredMeetings.length === 0">
|
||||
هیچ جلسهای یافت نشد. با کلیک کردن، یک جلسه جدید ایجاد کنید
|
||||
</span>
|
||||
<div v-else class="meetings-list">
|
||||
<div v-for="meeting in filteredMeetings" :key="meeting.id" class="meeting-item">
|
||||
<img :src="meeting.image" alt="Meeting Image" class="meeting-image" width="120px" height="120px" />
|
||||
<div class="meeting-details" style="margin-right: 10px;">
|
||||
<h3 class="meet-title">{{ meeting.title }}</h3>
|
||||
<p class="meet-capacity">
|
||||
<span style="margin-left: 4px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="none">
|
||||
<g clip-path="url(#clip0_622_1334)">
|
||||
<path d="M3.33203 5.16667C3.33203 5.87391 3.61298 6.55219 4.11308 7.05228C4.61318 7.55238 5.29145 7.83333 5.9987 7.83333C6.70594 7.83333 7.38422 7.55238 7.88432 7.05228C8.38441 6.55219 8.66536 5.87391 8.66536 5.16667C8.66536 4.45942 8.38441 3.78115 7.88432 3.28105C7.38422 2.78095 6.70594 2.5 5.9987 2.5C5.29145 2.5 4.61318 2.78095 4.11308 3.28105C3.61298 3.78115 3.33203 4.45942 3.33203 5.16667Z" stroke="#718096" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M2 14.5V13.1667C2 12.4594 2.28095 11.7811 2.78105 11.281C3.28115 10.781 3.95942 10.5 4.66667 10.5H7.33333C8.04058 10.5 8.71885 10.781 9.21895 11.281C9.71905 11.7811 10 12.4594 10 13.1667V14.5" stroke="#718096" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M10.668 2.58667C11.2416 2.73354 11.75 3.06714 12.1131 3.53488C12.4761 4.00262 12.6732 5.17 12.6732 5.17C12.6732 5.76212 12.4761 6.33739 12.1131 6.80513C11.75 7.27287 11.2416 7.60647 10.668 7.75334" stroke="#718096" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14 14.5V13.1666C13.9966 12.5781 13.7986 12.0072 13.4368 11.5429C13.0751 11.0786 12.5699 10.7471 12 10.6" stroke="#718096" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_622_1334">
|
||||
<rect width="16" height="16" fill="white" transform="translate(0 0.5)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</span>
|
||||
حداکثر: {{ meeting.maxCapacity }} کاربر
|
||||
</p>
|
||||
<p class="meet-type">
|
||||
<span style="margin-left: 4px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="none">
|
||||
<path d="M4 15.1667V3.16671C4 2.81309 4.14048 2.47395 4.39052 2.2239C4.64057 1.97385 4.97971 1.83337 5.33333 1.83337H10.6667C11.0203 1.83337 11.3594 1.97385 11.6095 2.2239C11.8595 2.47395 12 2.81309 12 3.16671V15.1667H4Z" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M3.9987 8.5H2.66536C2.31174 8.5 1.9726 8.64048 1.72256 8.89052C1.47251 9.14057 1.33203 9.47971 1.33203 9.83333V13.8333C1.33203 14.187 1.47251 14.5261 1.72256 14.7761C1.9726 15.0262 2.31174 15.1667 2.66536 15.1667H3.9987" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12 6.5H13.3333C13.687 6.5 14.0261 6.64048 14.2761 6.89052C14.5262 7.14057 14.6667 7.47971 14.6667 7.83333V13.8333C14.6667 14.187 14.5262 14.5261 14.2761 14.7761C14.0261 15.0262 13.687 15.1667 13.3333 15.1667H12" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.66797 4.5H9.33464" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.66797 7.16663H9.33464" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.66797 9.83337H9.33464" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.66797 12.5H9.33464" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</span>
|
||||
{{ meeting.type }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="create-meet"
|
||||
@click="showModal = true"
|
||||
:style="{ width: filteredMeetings.length === 0 ? 'auto' : '191px', margin: filteredMeetings.length === 0 ? '0' : 'auto'}"
|
||||
>
|
||||
+ <span style="margin-right: 0.5rem;">ایجاد جلسه جدید</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Create Meeting Modal -->
|
||||
<CreateMeetingModal
|
||||
:is-open="showModal"
|
||||
@create-meeting="createNewMeeting"
|
||||
@close="showModal = false"
|
||||
/>
|
||||
<div>
|
||||
<!-- Description -->
|
||||
<div class="section-description">
|
||||
<div class="section-title">مدیریت جلسات</div>
|
||||
<p class="title-description">
|
||||
با استفاده از جلسات، میتوانید همکاران و کاربران خارجی XRoom را به تیم و اتاقهای خصوصی خود دعوت کنید. شرکتکنندگان جلسه شما میتوانند با استفاده از کد جلسه ایجاد شده در زمانهای معین به جلسه بپیوندند.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Meeting Section -->
|
||||
<div class="meeting-section">
|
||||
<div class="meeting-filters">
|
||||
<div class="search-section">
|
||||
<span style="font-size: 17px; font-weight: 600;">جستجو</span>
|
||||
<div class="search-wrapper">
|
||||
<input
|
||||
type="text"
|
||||
class="search-input"
|
||||
placeholder="جستجو جلسه مدنظر ..."
|
||||
v-model="searchQuery"
|
||||
@input="filterMeetings"
|
||||
/>
|
||||
<button class="search-button">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M7.33333 12.6667C10.2789 12.6667 12.6667 10.2789 12.6667 7.33333C12.6667 4.38781 10.2789 2 7.33333 2C4.38781 2 2 4.38781 2 7.33333C2 10.2789 4.38781 12.6667 7.33333 12.6667Z"
|
||||
stroke="#101010"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M13.9995 14L11.1328 11.1333"
|
||||
stroke="#101010"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-section">
|
||||
<span style="font-size: 17px; font-weight: 600;">فیلتر</span>
|
||||
<div class="filter-buttons">
|
||||
<button
|
||||
:class="{ 'active-filter': activeFilter === 'future', 'disable-filter': activeFilter !== 'future' }"
|
||||
@click="setFilter('future')"
|
||||
>
|
||||
آینده
|
||||
</button>
|
||||
<button
|
||||
:class="{ 'active-filter': activeFilter === 'all', 'disable-filter': activeFilter !== 'all' }"
|
||||
@click="setFilter('all')"
|
||||
>
|
||||
همه
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Meet Discover -->
|
||||
<div :class="filteredMeetings.length === 0 ? 'meet-discover' : 'meetings-container'">
|
||||
<span class="discover-result" v-if="filteredMeetings.length === 0">
|
||||
هیچ جلسهای یافت نشد. با کلیک کردن، یک جلسه جدید ایجاد کنید
|
||||
</span>
|
||||
<div v-else class="meetings-list">
|
||||
<div v-for="meeting in filteredMeetings" :key="meeting.id" class="meeting-item">
|
||||
<img :src="meeting.image" alt="Meeting Image" class="meeting-image" width="120px" height="120px" />
|
||||
<div class="meeting-details" style="margin-right: 10px;">
|
||||
<h3 class="meet-title">{{ meeting.title }}</h3>
|
||||
<p class="meet-capacity">
|
||||
<span style="margin-left: 4px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="none">
|
||||
<g clip-path="url(#clip0_622_1334)">
|
||||
<path d="M3.33203 5.16667C3.33203 5.87391 3.61298 6.55219 4.11308 7.05228C4.61318 7.55238 5.29145 7.83333 5.9987 7.83333C6.70594 7.83333 7.38422 7.55238 7.88432 7.05228C8.38441 6.55219 8.66536 5.87391 8.66536 5.16667C8.66536 4.45942 8.38441 3.78115 7.88432 3.28105C7.38422 2.78095 6.70594 2.5 5.9987 2.5C5.29145 2.5 4.61318 2.78095 4.11308 3.28105C3.61298 3.78115 3.33203 4.45942 3.33203 5.16667Z" stroke="#718096" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M2 14.5V13.1667C2 12.4594 2.28095 11.7811 2.78105 11.281C3.28115 10.781 3.95942 10.5 4.66667 10.5H7.33333C8.04058 10.5 8.71885 10.781 9.21895 11.281C9.71905 11.7811 10 12.4594 10 13.1667V14.5" stroke="#718096" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M10.668 2.58667C11.2416 2.73354 11.75 3.06714 12.1131 3.53488C12.4761 4.00262 12.6732 5.17 12.6732 5.17C12.6732 5.76212 12.4761 6.33739 12.1131 6.80513C11.75 7.27287 11.2416 7.60647 10.668 7.75334" stroke="#718096" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14 14.5V13.1666C13.9966 12.5781 13.7986 12.0072 13.4368 11.5429C13.0751 11.0786 12.5699 10.7471 12 10.6" stroke="#718096" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_622_1334">
|
||||
<rect width="16" height="16" fill="white" transform="translate(0 0.5)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</span>
|
||||
حداکثر: {{ meeting.maxCapacity }} کاربر
|
||||
</p>
|
||||
<p class="meet-type">
|
||||
<span style="margin-left: 4px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="none">
|
||||
<path d="M4 15.1667V3.16671C4 2.81309 4.14048 2.47395 4.39052 2.2239C4.64057 1.97385 4.97971 1.83337 5.33333 1.83337H10.6667C11.0203 1.83337 11.3594 1.97385 11.6095 2.2239C11.8595 2.47395 12 2.81309 12 3.16671V15.1667H4Z" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M3.9987 8.5H2.66536C2.31174 8.5 1.9726 8.64048 1.72256 8.89052C1.47251 9.14057 1.33203 9.47971 1.33203 9.83333V13.8333C1.33203 14.187 1.47251 14.5261 1.72256 14.7761C1.9726 15.0262 2.31174 15.1667 2.66536 15.1667H3.9987" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12 6.5H13.3333C13.687 6.5 14.0261 6.64048 14.2761 6.89052C14.5262 7.14057 14.6667 7.47971 14.6667 7.83333V13.8333C14.6667 14.187 14.5262 14.5261 14.2761 14.7761C14.0261 15.0262 13.687 15.1667 13.3333 15.1667H12" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.66797 4.5H9.33464" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.66797 7.16663H9.33464" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.66797 9.83337H9.33464" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.66797 12.5H9.33464" stroke="#3A57E8" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</span>
|
||||
{{ meeting.type }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="create-meet"
|
||||
@click="showModal = true"
|
||||
:style="{ width: filteredMeetings.length === 0 ? 'auto' : '191px', margin: filteredMeetings.length === 0 ? '0' : 'auto'}"
|
||||
>
|
||||
+ <span style="margin-right: 0.5rem;">ایجاد جلسه جدید</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Create Meeting Modal -->
|
||||
<CreateMeetingModal
|
||||
:is-open="showModal"
|
||||
@create-meeting="createNewMeeting"
|
||||
@close="showModal = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CreateMeetingModal from '@/components/CreateMeetingModal.vue';
|
||||
import axios from 'axios';
|
||||
|
||||
export default {
|
||||
name: 'DashboardPage',
|
||||
|
@ -194,22 +195,90 @@ export default {
|
|||
this.activeFilter = filter;
|
||||
this.filterMeetings();
|
||||
},
|
||||
createNewMeeting(meetingData) {
|
||||
const newMeeting = {
|
||||
id: this.meetings.length + 1,
|
||||
title: meetingData.title,
|
||||
date: meetingData.date,
|
||||
image: 'https://via.placeholder.com/150',
|
||||
type: meetingData.type,
|
||||
maxCapacity: meetingData.maxCapacity,
|
||||
};
|
||||
this.meetings.push(newMeeting);
|
||||
this.filterMeetings();
|
||||
this.showModal = false;
|
||||
async refreshToken() {
|
||||
try {
|
||||
const response = await axios.post('http://my.xroomapp.com:8000/refresh_token', {
|
||||
refresh_token: localStorage.getItem('refresh_token'),
|
||||
});
|
||||
const newToken = response.data.access_token;
|
||||
localStorage.setItem('token', newToken);
|
||||
return newToken;
|
||||
} catch (error) {
|
||||
console.error('خطا در refresh توکن:', error);
|
||||
alert('لطفاً دوباره وارد شوید');
|
||||
window.location.href = '/login';
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async createNewMeeting(meetingData) {
|
||||
try {
|
||||
console.log('دادههای ارسالی به API:', JSON.stringify(meetingData, null, 2));
|
||||
let token = localStorage.getItem('token');
|
||||
console.log('توکن اولیه:', token);
|
||||
if (!token) {
|
||||
throw new Error('توکن احراز هویت پیدا نشد');
|
||||
}
|
||||
|
||||
let response = await axios.post(
|
||||
'http://my.xroomapp.com:8000/add_meeting',
|
||||
meetingData,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Token ${token.trim()}`,
|
||||
},
|
||||
}
|
||||
).catch(async (error) => {
|
||||
if (error.response && error.response.status === 403) {
|
||||
console.log('تلاش برای refresh توکن...');
|
||||
token = await this.refreshToken();
|
||||
if (token) {
|
||||
return await axios.post(
|
||||
'http://my.xroomapp.com:8000/add_meeting',
|
||||
meetingData,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Token ${token.trim()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
|
||||
console.log('پاسخ API:', response.data);
|
||||
|
||||
const newMeeting = {
|
||||
id: response.data.meeting.id,
|
||||
title: response.data.meeting.name,
|
||||
date: response.data.meeting.date_time,
|
||||
image: 'https://via.placeholder.com/150',
|
||||
type: 'جلسه',
|
||||
maxCapacity: 10,
|
||||
};
|
||||
|
||||
this.meetings.push(newMeeting);
|
||||
this.filterMeetings();
|
||||
this.showModal = false;
|
||||
alert('جلسه با موفقیت ایجاد شد!');
|
||||
} catch (error) {
|
||||
console.error('خطا در ارسال درخواست به API:', error);
|
||||
if (error.response) {
|
||||
console.error('جزئیات پاسخ سرور:', error.response.data);
|
||||
alert(`خطایی در ایجاد جلسه رخ داد: ${error.response.data.message || error.message}`);
|
||||
} else {
|
||||
alert(`خطایی در ایجاد جلسه رخ داد: ${error.message}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<style scoped>
|
||||
/* .dashboard-page {
|
||||
margin-right: 360px;
|
||||
|
@ -278,7 +347,8 @@ export default {
|
|||
|
||||
.search-wrapper {
|
||||
margin-top: 1rem;
|
||||
padding: 1.2px;
|
||||
padding: 1px;
|
||||
padding-left: 0.7px;
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(to right, #001940, #4364F7);
|
||||
position: relative;
|
||||
|
|
|
@ -98,7 +98,11 @@
|
|||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="recentFiles.length === 0" class="no-files-message">
|
||||
<p>شما اخیرا فایلی آپلود نکردید</p>
|
||||
</div>
|
||||
<swiper
|
||||
v-else
|
||||
:slides-per-view="2.2"
|
||||
:space-between="15"
|
||||
:loop="true"
|
||||
|
@ -322,6 +326,14 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.no-files-message{
|
||||
text-align: center;
|
||||
margin-top: 3rem;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
|
||||
.dashboard {
|
||||
padding: 20px 0px;
|
||||
font-family: 'IRANSansXFaNum-Medium', Helvetica, sans-serif;
|
||||
|
|
|
@ -90,29 +90,7 @@ export default {
|
|||
memberCount: 5,
|
||||
availableMemberOptions: [5, 10, 20, 100],
|
||||
selectedPlan: null,
|
||||
userList: [
|
||||
{
|
||||
name: 'دانیال پژوهش کیا',
|
||||
email: 'aminimperator@gmail.com',
|
||||
role: 'نسخه آزمایشی',
|
||||
version: '',
|
||||
avatar: 'https://models.readyplayer.me/681f59760bc631a87ad25172.png',
|
||||
},
|
||||
{
|
||||
name: 'امین رمضانی',
|
||||
email: 'aminimperator@gmail.com',
|
||||
role: 'مدیر',
|
||||
version: 'نسخه آزمایشی',
|
||||
avatar: 'https://models.readyplayer.me/681f59760bc631a87ad25172.png',
|
||||
},
|
||||
{
|
||||
name: 'نوید رمضانی',
|
||||
email: 'aminimperator@gmail.com',
|
||||
role: 'مدیر',
|
||||
version: 'نسخه آزمایشی',
|
||||
avatar: 'https://models.readyplayer.me/681f59760bc631a87ad25172.png',
|
||||
},
|
||||
],
|
||||
userList: [],
|
||||
activeTab: 'users',
|
||||
previewUrl: '',
|
||||
currentPreviewIndex: null,
|
||||
|
@ -137,6 +115,7 @@ export default {
|
|||
pdfs: [],
|
||||
videos: [],
|
||||
glbs: [],
|
||||
subscription: null,
|
||||
},
|
||||
newFileName: '',
|
||||
selectedFile: null,
|
||||
|
@ -147,11 +126,13 @@ export default {
|
|||
fileAccept: '*/*',
|
||||
teamMemberCapacity: 0,
|
||||
subscriptionCount: 0,
|
||||
teamId: null,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.fetchUserData();
|
||||
this.fetchTeamMemberInfo();
|
||||
this.fetchTeamData();
|
||||
const tab = this.$route.query.tab;
|
||||
if (tab) {
|
||||
this.activeTab = tab;
|
||||
|
@ -161,44 +142,88 @@ export default {
|
|||
changeTab(tabName) {
|
||||
this.activeTab = tabName;
|
||||
},
|
||||
async handlePaymentSuccess() {
|
||||
await this.fetchTeamMemberInfo();
|
||||
this.activeTab = 'membership';
|
||||
},
|
||||
async fetchTeamMemberInfo() {
|
||||
async fetchTeamData() {
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
const response = await axios.get(`${this.baseUrl}/get_team_member_info`, {
|
||||
const response = await axios.get('http://my.xroomapp.com:8000/get_team', {
|
||||
headers: {
|
||||
Authorization: `Token ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
this.teamMemberCapacity = response.data.data.team_member_capacity;
|
||||
this.subscriptionCount = response.data.data.subscriptionCount;
|
||||
console.log('تعداد اشتراکها (subscriptionCount):', this.subscriptionCount);
|
||||
const team = response.data.teams[0];
|
||||
if (team) {
|
||||
this.teamId = team.id;
|
||||
} else {
|
||||
this.teamId = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('خطا در دریافت اطلاعات اشتراک:', error);
|
||||
alert('خطا در بارگذاری اطلاعات اشتراک. لطفاً دوباره تلاش کنید.');
|
||||
alert('خطا در بارگذاری اطلاعات تیم. لطفاً دوباره تلاش کنید.');
|
||||
}
|
||||
},
|
||||
async handlePaymentSuccess() {
|
||||
await this.fetchTeamMemberInfo();
|
||||
await this.fetchUserData();
|
||||
this.activeTab = 'membership';
|
||||
},
|
||||
async fetchTeamMemberInfo() {
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
const response = await axios.get(`${this.baseUrl}/get_all_team_members`, {
|
||||
headers: {
|
||||
Authorization: `Token ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
this.userList = response.data.members.map((member) => ({
|
||||
name: `${member.first_name} ${member.last_name}`,
|
||||
email: member.username,
|
||||
role: 'کاربر',
|
||||
version: 'نسخه آزمایشی',
|
||||
avatar: 'https://models.readyplayer.me/681f59760bc631a87ad25172.png',
|
||||
}));
|
||||
this.teamMemberCapacity = response.data.members.length;
|
||||
} catch (error) {
|
||||
alert('خطا در بارگذاری اطلاعات اعضای تیم. لطفاً دوباره تلاش کنید.');
|
||||
}
|
||||
},
|
||||
async fetchUserData() {
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
const response = await axios.get(`${this.baseUrl}/getInfo`, {
|
||||
headers: {
|
||||
Authorization: `Token ${token}`,
|
||||
},
|
||||
});
|
||||
this.userData = response.data;
|
||||
if (this.userData.data.subscription) {
|
||||
this.subscriptionCount = this.userData.data.subscription || 0;
|
||||
} else {
|
||||
this.subscriptionCount = 0;
|
||||
}
|
||||
} catch (error) {
|
||||
alert('خطا در بارگذاری اطلاعات کاربر. لطفاً دوباره تلاش کنید.');
|
||||
}
|
||||
},
|
||||
async submitNewUser(newUser) {
|
||||
console.log('اطلاعات کاربر جدید:', newUser);
|
||||
|
||||
const remainingCapacity = this.subscriptionCount - this.teamMemberCapacity;
|
||||
if (remainingCapacity <= 0) {
|
||||
alert('ظرفیت تیم پر شده است. لطفاً اشتراک جدیدی خریداری کنید.');
|
||||
this.activeTab = 'buy-subscription';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.teamId) {
|
||||
alert('خطا: اطلاعات تیم یافت نشد. لطفاً دوباره تلاش کنید.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
|
||||
await axios.post(
|
||||
'http://my.xroomapp.com:8000/add_teamMember/',
|
||||
newUser,
|
||||
{
|
||||
...newUser,
|
||||
teamId: this.teamId,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Token ${token}`,
|
||||
|
@ -206,21 +231,16 @@ export default {
|
|||
},
|
||||
}
|
||||
);
|
||||
|
||||
this.userList.push({
|
||||
...newUser,
|
||||
avatar: 'https://models.readyplayer.me/681f59760bc631a87ad25172.png',
|
||||
role: newUser.role || 'کاربر',
|
||||
version: newUser.version || 'نسخه آزمایشی',
|
||||
});
|
||||
|
||||
this.teamMemberCapacity++;
|
||||
|
||||
await this.fetchTeamMemberInfo();
|
||||
|
||||
alert('کاربر با موفقیت اضافه شد');
|
||||
} catch (error) {
|
||||
console.error('خطا در اضافه کردن کاربر:', error);
|
||||
alert('خطا در اضافه کردن کاربر. لطفاً دوباره تلاش کنید.');
|
||||
}
|
||||
},
|
||||
|
@ -229,9 +249,6 @@ export default {
|
|||
this.closePreviewDialog();
|
||||
}
|
||||
},
|
||||
handleTeamData(data) {
|
||||
console.log('اطلاعات دریافتی : ', data);
|
||||
},
|
||||
openPreviewDialog(type, index, url) {
|
||||
if (type === 'video') {
|
||||
this.videoOptions.sources[0].src = url;
|
||||
|
@ -240,14 +257,11 @@ export default {
|
|||
});
|
||||
}
|
||||
if (!this.$refs.filePreviewDialog) {
|
||||
console.error('Dialog element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentPreviewType = type;
|
||||
this.currentPreviewIndex = index;
|
||||
this.previewUrl = url;
|
||||
|
||||
if (type === 'video') {
|
||||
this.videoOptions.sources[0].src = url;
|
||||
this.videoOptions.poster = this.getVideoThumbnail();
|
||||
|
@ -255,11 +269,9 @@ export default {
|
|||
} else {
|
||||
this.previewUrl = url;
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.$refs.filePreviewDialog?.showModal();
|
||||
});
|
||||
|
||||
if (type === 'image') {
|
||||
this.previewImageUrl = url;
|
||||
this.previewPdfUrl = '';
|
||||
|
@ -267,7 +279,6 @@ export default {
|
|||
this.previewPdfUrl = url;
|
||||
this.previewImageUrl = '';
|
||||
}
|
||||
|
||||
this.$refs.filePreviewDialog.showModal();
|
||||
},
|
||||
getVideoThumbnail() {
|
||||
|
@ -277,8 +288,6 @@ export default {
|
|||
const dialog = this.$refs.filePreviewDialog;
|
||||
if (dialog && typeof dialog.close === 'function') {
|
||||
dialog.close();
|
||||
} else {
|
||||
console.warn('Dialog reference not found or close method unavailable');
|
||||
}
|
||||
this.previewUrl = '';
|
||||
this.currentPreviewIndex = null;
|
||||
|
@ -288,38 +297,32 @@ export default {
|
|||
const url =
|
||||
this.currentPreviewType === 'image' ? this.previewImageUrl : this.previewPdfUrl;
|
||||
if (!url) return;
|
||||
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
const blob = await response.blob();
|
||||
const downloadUrl = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = downloadUrl;
|
||||
|
||||
if (this.currentPreviewType === 'image') {
|
||||
a.download = `image-${new Date().getTime()}.${url.split('.').pop()}`;
|
||||
} else if (this.currentPreviewType === 'pdf') {
|
||||
a.download = `document-${new Date().getTime()}.pdf`;
|
||||
}
|
||||
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(downloadUrl);
|
||||
document.body.removeChild(a);
|
||||
} catch (error) {
|
||||
console.error('Error downloading file:', error);
|
||||
alert('خطا در دانلود فایل');
|
||||
}
|
||||
},
|
||||
async deleteFile() {
|
||||
if (this.currentPreviewIndex === null || !this.currentPreviewType) return;
|
||||
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
let deleteUrl = '';
|
||||
let itemId = '';
|
||||
let fileArray = [];
|
||||
|
||||
switch (this.currentPreviewType) {
|
||||
case 'image':
|
||||
fileArray = this.userData.images;
|
||||
|
@ -342,34 +345,18 @@ export default {
|
|||
deleteUrl = `${this.baseUrl}/deleteGlb/${itemId}/`;
|
||||
break;
|
||||
}
|
||||
|
||||
await axios.delete(deleteUrl, {
|
||||
headers: {
|
||||
Authorization: `Token ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
this.closePreviewDialog();
|
||||
await this.fetchUserData();
|
||||
alert('فایل با موفقیت حذف شد');
|
||||
} catch (error) {
|
||||
console.error('Error deleting file:', error);
|
||||
alert('خطا در حذف فایل');
|
||||
}
|
||||
},
|
||||
async fetchUserData() {
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
const response = await axios.get(`${this.baseUrl}/getInfo`, {
|
||||
headers: {
|
||||
Authorization: `Token ${token}`,
|
||||
},
|
||||
});
|
||||
this.userData = response.data;
|
||||
} catch (error) {
|
||||
console.error('Error fetching user data:', error);
|
||||
}
|
||||
},
|
||||
getFullImageUrl(relativePath) {
|
||||
if (!relativePath) return '';
|
||||
return `${this.baseUrl}${relativePath}`;
|
||||
|
@ -381,7 +368,6 @@ export default {
|
|||
},
|
||||
openDialog(type) {
|
||||
this.currentUploadType = type;
|
||||
|
||||
switch (type) {
|
||||
case 'image':
|
||||
this.dialogTitle = 'آپلود تصویر جدید';
|
||||
|
@ -400,7 +386,6 @@ export default {
|
|||
this.fileAccept = '.glb';
|
||||
break;
|
||||
}
|
||||
|
||||
this.$refs.newFileDialog.showModal();
|
||||
},
|
||||
closeDialog() {
|
||||
|
@ -412,13 +397,12 @@ export default {
|
|||
this.selectedFile = event.target.files[0];
|
||||
},
|
||||
async uploadFile() {
|
||||
if (!this.selectedFile) return;
|
||||
|
||||
if (!this.selectedFile) {
|
||||
return;
|
||||
}
|
||||
this.uploading = true;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('name', this.newFileName || this.selectedFile.name);
|
||||
|
||||
switch (this.currentUploadType) {
|
||||
case 'image':
|
||||
formData.append('image', this.selectedFile);
|
||||
|
@ -433,11 +417,9 @@ export default {
|
|||
formData.append('glb', this.selectedFile);
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
let uploadUrl = '';
|
||||
|
||||
switch (this.currentUploadType) {
|
||||
case 'image':
|
||||
uploadUrl = `${this.baseUrl}/uploadImage/`;
|
||||
|
@ -452,19 +434,16 @@ export default {
|
|||
uploadUrl = `${this.baseUrl}/uploadGlb/`;
|
||||
break;
|
||||
}
|
||||
|
||||
await axios.post(uploadUrl, formData, {
|
||||
headers: {
|
||||
Authorization: `Token ${token}`,
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
|
||||
this.closeDialog();
|
||||
await this.fetchUserData();
|
||||
alert('فایل با موفقیت آپلود شد');
|
||||
} catch (error) {
|
||||
console.error('Error uploading file:', error);
|
||||
alert('خطا در آپلود فایل');
|
||||
} finally {
|
||||
this.uploading = false;
|
||||
|
@ -476,8 +455,8 @@ export default {
|
|||
if (newTab) {
|
||||
this.activeTab = newTab;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user