2025-05-24 23:13:36 +00:00
|
|
|
|
<template>
|
2025-05-31 14:19:08 +00:00
|
|
|
|
<div>
|
2025-05-24 23:13:36 +00:00
|
|
|
|
<!-- Top Header -->
|
|
|
|
|
<AppHeader pageTitle="فضاها" />
|
|
|
|
|
|
|
|
|
|
<!-- Description -->
|
|
|
|
|
<div class="section-description">
|
|
|
|
|
<div class="section-title">مدیریت فضای مجازی</div>
|
|
|
|
|
<p class="title-description">
|
|
|
|
|
با همکاران خود در یک فضای مجازی ملاقات کنید. در این صفحه میتوانید فضای اطراف خود را مشاهده و مدیریت کنید.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-05-28 08:42:55 +00:00
|
|
|
|
<!-- Add Space Button -->
|
|
|
|
|
<button class="add-space" @click="openCreateSpaceModal">
|
|
|
|
|
+ <span style="margin-right: 0.5rem;">اضافه کردن فضای اختصاصی</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Spaces -->
|
|
|
|
|
<div v-if="filteredSpaces.length > 0 " style="z-index: 0;">
|
|
|
|
|
<swiper
|
2025-06-08 15:50:16 +00:00
|
|
|
|
:slidesPerView="1.7"
|
|
|
|
|
:spaceBetween="20"
|
|
|
|
|
:freeMode="true"
|
2025-05-28 08:42:55 +00:00
|
|
|
|
:pagination="{ clickable: false }"
|
|
|
|
|
:modules="modules"
|
2025-06-08 15:50:16 +00:00
|
|
|
|
:breakpoints="{
|
|
|
|
|
768: { slidesPerView: 3.3, spaceBetween: 15 },
|
|
|
|
|
1024: { slidesPerView: 2.8, spaceBetween: 15 },
|
|
|
|
|
1280: { slidesPerView: 4.1, spaceBetween: 25 },
|
|
|
|
|
}"
|
2025-05-28 08:42:55 +00:00
|
|
|
|
class="mySwiper"
|
|
|
|
|
>
|
|
|
|
|
<swiper-slide v-for="(space, index) in filteredSpaces" :key="index" class="card">
|
|
|
|
|
<img :src="'http://my.xroomapp.com:8000' + space.img" alt="تصویر فضا" />
|
|
|
|
|
<div class="card-texts">
|
|
|
|
|
<h2>{{ space.name }}</h2>
|
|
|
|
|
<p class="space-capacity">
|
|
|
|
|
حداکثر: {{ space.capacity }} کاربر
|
|
|
|
|
</p>
|
|
|
|
|
<p class="space-type">
|
|
|
|
|
{{ space.type }}
|
|
|
|
|
</p>
|
2025-05-24 23:13:36 +00:00
|
|
|
|
</div>
|
2025-05-28 08:42:55 +00:00
|
|
|
|
</swiper-slide>
|
|
|
|
|
</swiper>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-else class="no-spaces-message">
|
|
|
|
|
<p>هیچ فضایی با فیلترهای انتخابشده یافت نشد.</p>
|
2025-05-24 23:13:36 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-05-28 08:42:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Create Space Modal -->
|
|
|
|
|
<CreateSpaceModal
|
|
|
|
|
:isVisible="isCreateSpaceModalVisible"
|
|
|
|
|
@close="closeCreateSpaceModal"
|
|
|
|
|
:spaces="spaces"
|
|
|
|
|
@submit="handleCreateSpaceSubmit"
|
|
|
|
|
/>
|
|
|
|
|
|
2025-05-24 23:13:36 +00:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import CreateSpaceModal from '@/components/CreateSpaceModal.vue';
|
|
|
|
|
import { Swiper, SwiperSlide } from 'swiper/vue';
|
|
|
|
|
import 'swiper/css';
|
2025-06-08 15:50:16 +00:00
|
|
|
|
import { FreeMode, Pagination } from 'swiper/modules';
|
2025-05-28 08:42:55 +00:00
|
|
|
|
import axios from 'axios';
|
2025-05-24 23:13:36 +00:00
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
name: 'DashboardPage',
|
|
|
|
|
components: {
|
|
|
|
|
CreateSpaceModal,
|
|
|
|
|
Swiper,
|
|
|
|
|
SwiperSlide,
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
2025-06-08 15:50:16 +00:00
|
|
|
|
modules: [FreeMode, Pagination],
|
2025-05-24 23:13:36 +00:00
|
|
|
|
isCreateSpaceModalVisible: false,
|
|
|
|
|
sharingFilters: [
|
|
|
|
|
{ label: 'همه', value: 'all' },
|
|
|
|
|
{ label: 'تیم', value: 'team' },
|
|
|
|
|
{ label: 'حریم خصوصی', value: 'private' },
|
|
|
|
|
],
|
|
|
|
|
spaceTypeFilters: [
|
|
|
|
|
{ label: 'فضاها', value: 'spaces' },
|
|
|
|
|
{ label: 'قالبها', value: 'templates' },
|
|
|
|
|
{ label: 'همه', value: 'all' },
|
|
|
|
|
],
|
|
|
|
|
activeSharingFilter: 'all',
|
|
|
|
|
activeSpaceTypeFilter: 'spaces',
|
2025-05-28 08:42:55 +00:00
|
|
|
|
spaces: [], // Initialize the spaces array
|
|
|
|
|
selectedSpace: null, // Store the selected space
|
2025-05-24 23:13:36 +00:00
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
filteredSpaces() {
|
|
|
|
|
return this.spaces.filter((space) => {
|
|
|
|
|
const matchesSharing =
|
|
|
|
|
this.activeSharingFilter === 'all' || space.sharing === this.activeSharingFilter;
|
|
|
|
|
const matchesSpaceType =
|
|
|
|
|
this.activeSpaceTypeFilter === 'all' || space.spaceType === this.activeSpaceTypeFilter;
|
|
|
|
|
return matchesSharing && matchesSpaceType;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
setActiveSharingFilter(value) {
|
|
|
|
|
this.activeSharingFilter = value;
|
|
|
|
|
},
|
|
|
|
|
setActiveSpaceTypeFilter(value) {
|
|
|
|
|
this.activeSpaceTypeFilter = value;
|
|
|
|
|
},
|
|
|
|
|
openCreateSpaceModal() {
|
|
|
|
|
this.isCreateSpaceModalVisible = true;
|
|
|
|
|
},
|
|
|
|
|
closeCreateSpaceModal() {
|
|
|
|
|
this.isCreateSpaceModalVisible = false;
|
|
|
|
|
},
|
2025-05-28 08:42:55 +00:00
|
|
|
|
async fetchSpaces() {
|
|
|
|
|
try {
|
|
|
|
|
const token = localStorage.getItem('token'); // Retrieve the token from localStorage
|
|
|
|
|
if (!token) {
|
|
|
|
|
console.error('No token found!');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const response = await axios.get(
|
|
|
|
|
'http://my.xroomapp.com:8000/get_spaces', // API endpoint
|
|
|
|
|
{
|
|
|
|
|
headers: {
|
|
|
|
|
Authorization: `Token ${token}`,
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
capacity: space.capacity,
|
|
|
|
|
type: space.Private ? 'Private' : 'Public', // Adjust if you have a different field
|
|
|
|
|
sharing: space.Private ? 'private' : 'team',
|
|
|
|
|
spaceType: 'spaces',
|
|
|
|
|
description: space.description, // Store description from response
|
|
|
|
|
}));
|
|
|
|
|
} 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
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
this.fetchSpaces(); // Fetch spaces when the component is mounted
|
2025-05-24 23:13:36 +00:00
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
2025-06-08 15:50:16 +00:00
|
|
|
|
<style>
|
|
|
|
|
/* Base styles applied across all screen sizes */
|
2025-05-24 23:13:36 +00:00
|
|
|
|
.section-title {
|
2025-06-08 15:50:16 +00:00
|
|
|
|
font-weight: 700;
|
|
|
|
|
color: #101010;
|
|
|
|
|
font-size: 19px;
|
|
|
|
|
line-height: 26.6px;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 15:41:53 +00:00
|
|
|
|
.section-description {
|
|
|
|
|
margin: 1rem 0 3rem;
|
2025-06-08 15:50:16 +00:00
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #2d3748;
|
2025-05-30 15:41:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-description p {
|
2025-06-08 15:50:16 +00:00
|
|
|
|
line-height: 190%;
|
|
|
|
|
color: #4f5a69;
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
text-align: justify;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.filter-section {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 2.5rem;
|
|
|
|
|
padding: 24px 16px;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
background-color: #FFFFFF;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sharing-filters {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
max-width: 79%;
|
|
|
|
|
width: 100%;
|
|
|
|
|
margin-left: 1.5rem;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.space-type-filter {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
max-width: 21%;
|
|
|
|
|
width: 100%;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.active-filter {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
background-color: #3A57E8;
|
|
|
|
|
color: #FFFFFF;
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
border: none;
|
|
|
|
|
padding: 7px 12px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
margin-left: 1rem;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.disable-filter {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
color: #3A57E8;
|
|
|
|
|
background-color: #FFFFFF;
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
border: none;
|
|
|
|
|
padding: 7px 10px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
margin-left: 1rem;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
2025-05-28 08:42:55 +00:00
|
|
|
|
|
2025-05-24 23:13:36 +00:00
|
|
|
|
.filter-buttons {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
margin-top: 1rem;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.add-space {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
display: block;
|
|
|
|
|
background-color: #3A57E8;
|
|
|
|
|
color: #FFFFFF;
|
2025-06-08 15:50:16 +00:00
|
|
|
|
border-radius: 8px;
|
2025-05-28 08:42:55 +00:00
|
|
|
|
border: none;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
width: max-content;
|
|
|
|
|
margin: auto;
|
2025-06-08 15:50:16 +00:00
|
|
|
|
font-weight: 500;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.mySwiper {
|
2025-06-08 15:50:16 +00:00
|
|
|
|
margin: 2.5rem 0;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card {
|
2025-06-08 15:50:16 +00:00
|
|
|
|
height: auto;
|
2025-05-28 08:42:55 +00:00
|
|
|
|
border: 1px solid #B8C0CB;
|
|
|
|
|
border-radius: 16px;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
cursor: pointer;
|
2025-06-08 15:50:16 +00:00
|
|
|
|
padding: 4px;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card img {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
width: 100%;
|
2025-06-08 15:50:16 +00:00
|
|
|
|
height: 10rem;
|
2025-05-28 08:42:55 +00:00
|
|
|
|
border-radius: 14px;
|
|
|
|
|
border: none;
|
2025-06-08 15:50:16 +00:00
|
|
|
|
object-fit: cover;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-texts {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
width: 100%;
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
padding-right: 1rem;
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 1rem;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-06-08 15:50:16 +00:00
|
|
|
|
.card-texts h2 {
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
overflow-x: clip;
|
|
|
|
|
width: 170px;
|
2025-05-28 08:42:55 +00:00
|
|
|
|
font-weight: 600;
|
2025-06-08 15:50:16 +00:00
|
|
|
|
color: #101010;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.space-capacity {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
2025-06-08 15:50:16 +00:00
|
|
|
|
font-size: 14px;
|
2025-05-28 08:42:55 +00:00
|
|
|
|
font-weight: 500;
|
|
|
|
|
color: #718096;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.space-type {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
2025-06-08 15:50:16 +00:00
|
|
|
|
font-size: 14px;
|
2025-05-28 08:42:55 +00:00
|
|
|
|
font-weight: 500;
|
|
|
|
|
color: #3A57E8;
|
2025-06-08 15:50:16 +00:00
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
overflow-x: clip;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
width: 170px;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.no-spaces-message {
|
2025-05-28 08:42:55 +00:00
|
|
|
|
font-size: 18px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
color: #101010;
|
|
|
|
|
margin-top: 4rem;
|
|
|
|
|
margin-bottom: 12rem;
|
|
|
|
|
text-align: center;
|
2025-05-24 23:13:36 +00:00
|
|
|
|
}
|
2025-06-08 15:50:16 +00:00
|
|
|
|
|
|
|
|
|
/* Media Queries for responsive adjustments */
|
|
|
|
|
@media (max-width: 600px) {
|
|
|
|
|
.card {
|
|
|
|
|
max-width: 250px;
|
|
|
|
|
height: 17.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-texts h2 {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.add-space {
|
|
|
|
|
padding : 8px 18px ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (min-width: 600px) and (max-width: 1024px) {
|
|
|
|
|
.card-texts h2 {
|
|
|
|
|
font-size: 17px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card {
|
|
|
|
|
height: 17.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.add-space {
|
|
|
|
|
padding : 8px 18px ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (min-width: 1024px) and (max-width: 1280px) {
|
|
|
|
|
.section-title {
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #101010;
|
|
|
|
|
margin: 20px 0 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.add-space {
|
|
|
|
|
padding: 10px 20px;
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-texts h2 {
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card {
|
|
|
|
|
height: 17.5rem;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (min-width: 1280px) {
|
|
|
|
|
.section-title {
|
|
|
|
|
font-size: 21px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-description p {
|
|
|
|
|
font-size: 17.5px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.add-space {
|
|
|
|
|
padding: 12px 24px;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card {
|
|
|
|
|
max-width: 250px;
|
|
|
|
|
height: 20rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card img {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 12rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-texts h2 {
|
|
|
|
|
font-size: 21px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.space-capacity,
|
|
|
|
|
.space-type {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</style>
|