XRoomDashboardFront/xroom-dashboard/src/pages/dashboard/team.vue

330 lines
9.9 KiB
Vue
Raw Normal View History

2025-05-12 08:24:39 +00:00
<template>
2025-06-07 23:29:17 +00:00
<div>
<!-- Section Description -->
<div class="section-description">
<div class="section-title">مدیریت اعضا</div>
<p>در این بخش میتوانید اتاقها، فایلها و جلسات را با همکاران خود به اشتراک بگذارید و تیم خود را مدیریت کنید.</p>
2025-05-18 13:45:35 +00:00
</div>
2025-06-07 23:29:17 +00:00
<!-- Tab Buttons -->
<div class="tab-buttons">
<button
:class="['tab-btn', { active: activeTab === 'users' }]"
@click="activeTab = 'users'"
>کاربران</button>
<button
:class="['tab-btn', { active: activeTab === 'buy-subscription' }]"
@click="activeTab = 'buy-subscription'"
>خرید اشتراک</button>
<button
:class="['tab-btn', { active: activeTab === 'membership' }]"
@click="activeTab = 'membership'"
>اشتراکها</button>
<button
:class="['tab-btn', { active: activeTab === 'details' }]"
@click="activeTab = 'details'"
>جزئیات</button>
</div>
<!-- Tab Content -->
<div v-if="activeTab === 'users'">
<TeamUser
:user-list="userList"
:team-member-capacity="teamMemberCapacity"
:subscription-count="subscriptionCount"
:has-active-subscription="hasActiveSubscription"
@add-user="submitNewUser"
@change-tab="changeTab"
/>
</div>
<div v-if="activeTab === 'membership'">
<Membership
:subscription-count="subscriptionCount"
:team-member-capacity="teamMemberCapacity"
:is-billing-modal-visible="isBillingModalVisible"
@change-tab="changeTab"
@update:is-billing-modal-visible="isBillingModalVisible = $event"
/>
</div>
<div v-if="activeTab === 'details'">
<TeamDetails @update:team-data="handleTeamData" />
</div>
<div v-if="activeTab === 'buy-subscription'">
<BuySubscription
:member-count="memberCount"
:available-member-options="availableMemberOptions"
:base-url="baseUrl"
:has-active-subscription="hasActiveSubscription"
:has-expired-subscription="hasExpiredSubscription"
@update:member-count="memberCount = $event"
@payment-success="handlePaymentSuccess"
/>
</div>
</div>
2025-05-12 08:24:39 +00:00
</template>
<script>
2025-05-27 00:01:58 +00:00
import TeamUser from '@/components/TeamUser.vue';
import BuySubscription from '@/components/BuySubscription.vue';
import Membership from '@/components/Membership.vue';
import TeamDetails from '@/components/TeamDetails.vue';
2025-05-27 00:01:58 +00:00
import axios from 'axios';
2025-05-12 08:24:39 +00:00
export default {
2025-06-07 23:29:17 +00:00
name: 'Team',
components: { TeamUser, BuySubscription, Membership, TeamDetails },
2025-05-12 08:24:39 +00:00
data() {
return {
2025-06-07 23:29:17 +00:00
activeTab: 'users',
userList: [],
2025-05-18 13:45:35 +00:00
memberCount: 5,
availableMemberOptions: [5, 10, 20, 100],
teamMemberCapacity: 0,
subscriptionCount: 0,
2025-06-07 23:29:17 +00:00
hasActiveSubscription: false,
hasExpiredSubscription: false, // جدید: بررسی اشتراک منقضی‌شده
subscriptionEndTime: null, // جدید: ذخیره تاریخ انقضای اشتراک
2025-06-05 17:33:09 +00:00
teamId: null,
2025-06-07 23:29:17 +00:00
subscriptionId: null,
isBillingModalVisible: false,
baseUrl: 'http://my.xroomapp.com:8000',
2025-05-27 00:01:58 +00:00
};
2025-05-12 08:24:39 +00:00
},
created() {
2025-06-07 23:29:17 +00:00
this.initializeData();
2025-05-12 08:24:39 +00:00
},
methods: {
2025-06-07 23:29:17 +00:00
async initializeData() {
const tab = this.$route.query.tab;
if (tab) this.activeTab = tab;
await Promise.all([
this.fetchUserData(),
this.fetchTeamMemberInfo(),
this.fetchTeamData(),
]);
},
2025-05-27 00:01:58 +00:00
changeTab(tabName) {
this.activeTab = tabName;
},
2025-06-05 17:33:09 +00:00
async fetchTeamData() {
try {
2025-06-07 23:29:17 +00:00
const response = await this.axiosGet('/get_team');
2025-06-05 17:33:09 +00:00
const team = response.data.teams[0];
2025-06-07 23:29:17 +00:00
this.teamId = team?.id || null;
2025-06-05 17:33:09 +00:00
} catch (error) {
2025-06-07 23:29:17 +00:00
console.error('Error fetching team data:', error);
alert('خطا در بارگذاری اطلاعات تیم.');
2025-06-05 17:33:09 +00:00
}
},
async fetchTeamMemberInfo() {
try {
2025-06-07 23:29:17 +00:00
const response = await this.axiosGet('/get_all_team_members');
this.userList = response.data.members.map(member => ({
name: `${member.user.first_name} ${member.user.last_name}`,
email: member.user.username,
role: member.semat || 'کاربر',
2025-06-05 17:33:09 +00:00
version: 'نسخه آزمایشی',
2025-06-07 23:29:17 +00:00
avatar: member.profile_img || 'https://models.readyplayer.me/681f59760bc631a87ad25172.png',
2025-06-05 17:33:09 +00:00
}));
this.teamMemberCapacity = response.data.members.length;
} catch (error) {
2025-06-07 23:29:17 +00:00
console.error('Error fetching team members:', error);
alert('خطا در بارگذاری اطلاعات اعضای تیم.');
2025-06-05 17:33:09 +00:00
}
},
async fetchUserData() {
try {
2025-06-07 23:29:17 +00:00
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; // جدید: تاریخ انقضا
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) {
console.error('Error fetching user data:', error);
alert('خطا در بارگذاری اطلاعات اشتراک.');
}
},
async handlePaymentSuccess({ subscriptionId }) {
try {
this.subscriptionId = subscriptionId;
await Promise.all([
this.fetchUserData(),
this.fetchTeamMemberInfo(),
this.fetchTeamData(),
]);
if (!this.teamId && this.subscriptionId) {
await this.createTeam();
alert('اشتراک و تیم به درستی ساخته شد.');
} else if (this.teamId) {
alert('تیم از قبل وجود دارد.');
2025-06-05 17:33:09 +00:00
}
2025-06-07 23:29:17 +00:00
this.activeTab = 'membership';
2025-06-05 17:33:09 +00:00
} catch (error) {
2025-06-07 23:29:17 +00:00
console.error('Error handling payment success:', error);
alert('خطا در پردازش پرداخت یا ساخت تیم.');
}
},
2025-06-07 23:29:17 +00:00
async createTeam() {
const teamData = {
name: 'تیم 1',
description: 'فعالیت',
max_persons: this.subscriptionCount.toString(),
subscriptionId: this.subscriptionId,
};
await this.axiosPost('/add_team', teamData);
await this.fetchTeamData();
},
async submitNewUser(newUser) {
2025-06-07 23:29:17 +00:00
if (this.subscriptionCount - this.teamMemberCapacity <= 0) {
alert('اشتراک فعالی ندارید , اشتراک تهیه نمایید.');
this.activeTab = 'buy-subscription';
return;
}
2025-06-05 17:33:09 +00:00
if (!this.teamId) {
2025-06-07 23:29:17 +00:00
alert('خطا: اطلاعات تیم یافت نشد.');
2025-06-05 17:33:09 +00:00
return;
}
try {
2025-06-07 23:29:17 +00:00
await this.axiosPost('/add_teamMember/', { ...newUser, teamId: this.teamId });
this.userList.push({
...newUser,
avatar: 'https://models.readyplayer.me/681f59760bc631a87ad25172.png',
role: newUser.role || 'کاربر',
version: newUser.version || 'نسخه آزمایشی',
});
this.teamMemberCapacity++;
await this.fetchTeamMemberInfo();
2025-06-07 23:29:17 +00:00
alert('کاربر با موفقیت اضافه شد.');
} catch (error) {
2025-06-07 23:29:17 +00:00
console.error('Error adding user:', error);
alert('خطا در اضافه کردن کاربر.');
}
2025-05-27 00:01:58 +00:00
},
2025-06-07 23:29:17 +00:00
handleTeamData(data) {
console.log('Team data updated:', data);
2025-05-27 00:01:58 +00:00
},
2025-06-07 23:29:17 +00:00
async axiosGet(endpoint) {
const token = localStorage.getItem('token');
if (!token) throw new Error('توکن احراز هویت یافت نشد.');
return await axios.get(`${this.baseUrl}${endpoint}`, {
headers: { Authorization: `Token ${token}`, 'Content-Type': 'application/json' },
2025-05-27 00:01:58 +00:00
});
2025-05-12 08:24:39 +00:00
},
2025-06-07 23:29:17 +00:00
async axiosPost(endpoint, data) {
const token = localStorage.getItem('token');
if (!token) throw new Error('توکن احراز هویت یافت نشد.');
return await axios.post(`${this.baseUrl}${endpoint}`, data, {
headers: { Authorization: `Token ${token}`, 'Content-Type': 'application/json' },
});
2025-05-27 00:01:58 +00:00
},
},
2025-06-03 23:27:19 +00:00
watch: {
'$route.query.tab'(newTab) {
2025-06-07 23:29:17 +00:00
if (newTab) this.activeTab = newTab;
2025-06-05 17:33:09 +00:00
},
},
2025-05-27 00:01:58 +00:00
};
2025-05-12 08:24:39 +00:00
</script>
2025-06-07 23:29:17 +00:00
<style scoped>
2025-05-12 08:24:39 +00:00
.section-title {
2025-06-11 15:42:22 +00:00
font-weight: 700;
color: #101010;
font-size: 19px;
line-height: 26.6px;
2025-05-30 15:41:53 +00:00
}
.section-description {
2025-06-11 15:42:22 +00:00
margin: 1rem 0 3rem;
font-size: 20px;
font-weight: 600;
color: #2d3748;
2025-05-30 15:41:53 +00:00
}
.section-description p {
2025-06-11 15:42:22 +00:00
line-height: 190%;
color: #4f5a69;
font-size: 15px;
margin-top: 1rem;
font-weight: 500;
text-align: justify;
2025-05-12 08:24:39 +00:00
}
2025-05-12 13:14:57 +00:00
.tab-buttons {
display: flex;
gap: 25px;
margin-top: 2rem;
margin-bottom: 2rem;
2025-06-11 15:42:22 +00:00
justify-content: space-between;
padding : 8px;
2025-05-12 13:14:57 +00:00
}
.tab-btn {
background: none;
border: none;
color: gray;
2025-06-11 15:42:22 +00:00
font-size: 16px;
2025-05-12 13:14:57 +00:00
padding: 8px 16px;
cursor: pointer;
border-bottom: 2px solid transparent;
transition: all 0.2s ease-in-out;
2025-06-11 15:42:22 +00:00
padding-right: 0px;
padding-left: 0;
2025-05-12 13:14:57 +00:00
}
.tab-btn.active {
color: #3a57e8;
border-bottom: 2px solid #3a57e8;
2025-06-11 15:42:22 +00:00
font-size: 16px;
}
@media (min-width: 600px) and (max-width: 1024px) {
.tab-buttons {
justify-content: flex-start;
}
}
@media (min-width: 1024px) and (max-width: 1280px) {
.section-title {
font-size: 20px;
font-weight: 600;
color: #101010;
margin: 20px 0 10px;
}
}
@media (min-width: 1280px) {
.section-title {
font-size: 21px;
}
.section-description p {
font-size: 17.5px;
}
.tab-btn {
font-size: 18px;
padding: 8px 16px;
}
.tab-btn.active {
font-size: 21px;
}
.tab-buttons {
padding: 0;
justify-content: flex-start;
}
2025-05-12 13:14:57 +00:00
}
2025-05-27 00:01:58 +00:00
</style>