pixelfed/resources/assets/components/groups/partials/SelfDiscover.vue

466 lines
16 KiB
Vue
Raw Normal View History

2024-07-10 05:52:08 +00:00
<template>
<div class="self-discover-component col-12 col-md-9 bg-lighter border-left mb-4">
<div class="px-5">
<div class="jumbotron my-4 text-light bg-mantle">
<div class="container">
<h1 class="display-4">Discover</h1>
<p class="lead mb-0">Explore group communities and topics</p>
<!-- <p class="lead">
<button class="btn btn-outline-light">Browse Categories</button>
</p> -->
</div>
</div>
</div>
<div v-if="tab === 'home'" class="px-5">
<div class="row mb-4 pt-5">
<div class="col-12 col-md-4">
<h4 class="font-weight-bold">Popular</h4>
<div class="list-group list-group-scroll">
<a v-for="(group, index) in popularGroups"
class="list-group-item p-1"
:href="group.url">
<group-list-card :group="group" :compact="true" />
</a>
</div>
</div>
<div class="col-12 col-md-4">
<div class="card card-body shadow-none bg-mantle text-light" style="margin-top: 33px;">
<h3 class="mb-4 font-weight-lighter">Discover communities and topics based on your interests</h3>
<p class="mb-0">
<button class="btn btn-outline-light font-weight-light btn-block" @click="toggleTab('categories')">Browse Categories</button>
</p>
</div>
<div class="card card-body shadow-none bg-light text-dark border" style="margin-top: 20px;">
<p class="lead mb-4 text-muted font-weight-lighter mb-1">Browse Public Groups</p>
<!-- <p class="lead mb-4 text-muted font-weight-lighter">Tips for growing your group membership</p> -->
<!-- <h5 class="mb-4 text-muted font-weight-lighter">Create and easily organize events</h5> -->
<p class="mb-0">
<button class="btn btn-light border font-weight-light btn-block">Group Directory</button>
</p>
</div>
</div>
<div class="col-12 col-md-4">
<h4 class="font-weight-bold">New</h4>
<div class="list-group list-group-scroll">
<a v-for="(group, index) in newGroups"
class="list-group-item p-1"
:href="group.url">
<group-list-card :group="group" :compact="true" />
</a>
</div>
</div>
</div>
<div class="jumbotron mb-4 text-light bg-black" style="margin-top: 5rem;">
<div class="container">
<h1 class="display-4">Across the Fediverse</h1>
<p class="mb-0">
<button
class="btn btn-outline-light"
@click="toggleTab('fediverseGroups')"
>
Explore fediverse groups <i class="fal fa-chevron-right ml-2"></i>
</button>
</p>
<hr class="my-4">
<p class="lead">We're in the early stages of Group federation, and working with other projects to support cross-platform compatibility. <a href="#">Learn more about group federation <i class="fal fa-chevron-right ml-2 fa-sm"></i></a></p>
</div>
</div>
<div class="row my-4 py-5">
<div class="col-12 col-md-4">
<div class="card card-body shadow-none bg-light" style="border:1px solid #E5E7EB;">
<p class="text-center text-lighter">
<i class="fal fa-lightbulb fa-4x"></i>
</p>
<p class="text-center lead mb-0">What's New</p>
</div>
</div>
<div class="col-12 col-md-4">
<div class="card card-body shadow-none bg-light" style="border:1px solid #E5E7EB;">
<p class="text-center text-lighter">
<i class="fal fa-clipboard-list-check fa-4x"></i>
</p>
<p class="text-center lead mb-0">User Guide</p>
</div>
</div>
<div class="col-12 col-md-4">
<div class="card card-body shadow-none bg-light" style="border:1px solid #E5E7EB;">
<p class="text-center text-lighter">
<i class="fal fa-question-circle fa-4x"></i>
</p>
<p class="text-center lead mb-0">Groups Help</p>
</div>
</div>
</div>
<p class="text-lighter" style="font-size:9px">
<span class="font-weight-bold mr-1">Groups v0.0.1</span>
</p>
<!-- <div class="my-4 pt-5">
<p class="h4 font-weight-bold mb-1">Suggested for You</p>
<p class="lead text-muted mb-0">Groups you might be interested in</p>
</div>
<div class="row mb-4">
<div v-for="(group, index) in recommended.slice(recommendedStart, recommendedEnd)" :key="'rec:'+group.id+':'+index" class="col-12 col-md-4 slide-fade">
<div class="card shadow-sm border text-decoration-none text-dark">
<img v-if="group.metadata && group.metadata.hasOwnProperty('header')" :src="group.metadata.header.url" class="card-img-top" style="width: 100%; height: auto;object-fit: cover;max-height: 160px;">
<div v-else class="bg-primary" style="width:100%;height:160px;"></div>
<div class="card-body">
<div class="lead font-weight-bold d-flex align-items-top" style="height: 60px;">
{{ group.name }}
<span v-if="group.verified" class="fa-stack ml-n2 mt-n2">
<i class="fas fa-circle fa-stack-1x fa-lg" style="color: #22a7f0cc;font-size:18px"></i>
<i class="fas fa-check fa-stack-1x text-white" style="font-size:10px"></i>
</span>
</div>
<div class="text-muted font-weight-light d-flex justify-content-between">
<span>{{group.member_count}} Members</span>
</div>
<hr>
<p class="mb-0">
<a class="btn btn-light btn-block border rounded-lg font-weight-bold" :href="group.url">View Group</a>
</p>
</div>
</div>
<div v-if="index == 0 && recommended.length > 3 && recommendedStart != 0" style="position: absolute; top: 45%; left: 0px;transform:translateY(-55%);">
<button class="btn btn-light shadow-lg btn-lg rounded-circle border d-flex align-items-center justify-content-center" style="width: 50px;height:50px;" @click="recommendedPrev()">
<i class="fas fa-chevron-left fa-lg"></i>
</button>
</div>
<div v-if="index == 2 && recommended.length > 3" style="position: absolute; top: 45%; right: 0px;transform:translateY(-55%);">
<button class="btn btn-light shadow-lg btn-lg rounded-circle border d-flex align-items-center justify-content-center" style="width: 50px;height:50px;" @click="recommendedNext()">
<i class="fas fa-chevron-right fa-lg"></i>
</button>
</div>
</div>
</div>
<div class="py-2 mb-2">
<hr>
</div> -->
<!-- <div class="px-4 pb-4">
<p class="h4 font-weight-bold mb-1">Friends' Groups</p>
<p class="lead text-muted mb-0">Groups your mutuals are in.</p>
</div> -->
<!-- <div class="px-4 py-2">
<hr>
</div> -->
<!-- <div class="pb-4">
<p class="h4 font-weight-bold mb-1">Categories</p>
<p class="lead text-muted mb-0">Find a group by browsing top categories</p>
</div>
<div class="row mb-4">
<div v-for="(group, index) in categories.slice(categoriesStart, categoriesEnd)" :key="'rec:'+group.id+':'+index" class="col-12 col-md-2 slide-fade">
<div class="card card-body rounded-lg shadow-sm border text-decoration-none bg-primary p-2 text-white d-flex justify-content-end" style="width: 150px; height:150px; background: linear-gradient(45deg, #ff512f, #dd2476);">
<p class="mb-0 font-weight-bold" style="font-size:15px">{{group}}</p>
</div>
<div v-if="index == 0 && categories.length > 3 && categoriesStart != 0" style="position: absolute; top: 50%; left: -10px;transform:translateY(-50%);">
<button class="btn btn-light shadow-lg btn-lg rounded-circle border d-flex align-items-center justify-content-center" style="width: 50px;height:50px;" @click="categoriesPrev()">
<i class="fas fa-chevron-left fa-lg"></i>
</button>
</div>
<div v-if="index == 5 && categories.length > 3" style="position: absolute; top: 50%; right: -10px;transform:translateY(-50%);">
<button class="btn btn-light shadow-lg btn-lg rounded-circle border d-flex align-items-center justify-content-center" style="width: 50px;height:50px;" @click="categoriesNext()">
<i class="fas fa-chevron-right fa-lg"></i>
</button>
</div>
</div>
</div> -->
<!-- <div class="py-2 mb-2">
<hr>
</div> -->
<!-- <div class="pb-4 my-4">
<p class="h4 font-weight-bold mb-1">My Groups</p>
<p class="lead text-muted mb-0">Groups you are a member of</p>
</div>
<div class="row mb-4">
<div v-for="(group, index) in selfGroups.slice(selfGroupsStart, selfGroupsEnd)" :key="'rec:'+group.id+':'+index" class="col-12 col-md-4 slide-fade">
<div class="card shadow-sm border text-decoration-none text-dark">
<img v-if="group.metadata && group.metadata.hasOwnProperty('header')" :src="group.metadata.header.url" class="card-img-top" style="width: 100%; height: auto;object-fit: cover;max-height: 160px;">
<div v-else class="bg-primary" style="width:100%;height:160px;"></div>
<div class="card-body">
<div class="lead font-weight-bold d-flex align-items-top" style="height: 60px;">
{{ group.name }}
<span v-if="group.verified" class="fa-stack ml-n2 mt-n2">
<i class="fas fa-circle fa-stack-1x fa-lg" style="color: #22a7f0cc;font-size:18px"></i>
<i class="fas fa-check fa-stack-1x text-white" style="font-size:10px"></i>
</span>
</div>
<div class="text-muted font-weight-light d-flex justify-content-between">
<span>{{group.member_count}} Members</span>
</div>
<hr>
<p class="mb-0">
<a class="btn btn-light btn-block border rounded-lg font-weight-bold" :href="group.url">View Group</a>
</p>
</div>
</div>
<div v-if="index == 0 && selfGroups.length > 3 && selfGroupsStart != 0" style="position: absolute; top: 50%; left: -10px;transform:translateY(-50%);">
<button class="btn btn-light shadow-lg btn-lg rounded-circle border d-flex align-items-center justify-content-center" style="width: 50px;height:50px;" @click="selfGroupsPrev()">
<i class="fas fa-chevron-left fa-lg"></i>
</button>
</div>
<div v-if="index == 2 && selfGroups.length > 3" style="position: absolute; top: 50%; right: -10px;transform:translateY(-50%);">
<button class="btn btn-light shadow-lg btn-lg rounded-circle border d-flex align-items-center justify-content-center" style="width: 50px;height:50px;" @click="selfGroupsNext()">
<i class="fas fa-chevron-right fa-lg"></i>
</button>
</div>
</div>
</div> -->
</div>
<div v-if="tab === 'categories'" class="px-5">
<div class="row my-4 justify-content-center">
<div class="col-12 col-md-6">
<div class="title mb-4">
<span>Categories</span>
<button class="btn btn-light font-weight-bold" @click="toggleTab('home')">Go Back</button>
</div>
<div class="list-group">
<div
v-for="(group, index) in categories"
:key="'rec:'+group.id+':'+index"
class="list-group-item"
@click="selectCategory(index)">
<p class="mb-0 font-weight-bold">
{{group}}
<span class="float-right">
<i class="fal fa-chevron-right"></i>
</span>
</p>
</div>
</div>
</div>
</div>
</div>
<div v-if="tab === 'category'" class="px-5">
<div class="row my-4 justify-content-center">
<div class="col-12 col-md-6">
<div class="title mb-4">
<div>
<div class="mb-n2 small text-uppercase text-lighter">Categories</div>
<span>{{ categories[activeCategoryIndex] }}</span>
</div>
<button class="btn btn-light font-weight-bold" @click="toggleTab('categories')">Go Back</button>
</div>
<div v-if="categoryGroupsLoaded">
<div class="list-group">
<a v-for="(group, index) in categoryGroups"
class="list-group-item p-1"
:href="group.url">
<group-list-card :group="group" :showStats="true" />
</a>
<div
v-if="categoryGroupsCanLoadMore"
class="list-group-item">
<button
class="btn btn-light font-weight-bold btn-block"
@click="fetchCategoryGroups">
Load more
</button>
</div>
</div>
<div v-if="categoryGroups.length === 0" class="mt-3">
<div class="bg-white border text-center p-3">
<p class="font-weight-light mb-0">No groups found in this category</p>
</div>
</div>
</div>
<div v-else>
<div class="card card-body shadow-none border justify-content-center flex-row">
<b-spinner />
</div>
</div>
</div>
</div>
</div>
<div v-if="tab === 'fediverseGroups'" class="px-5">
<div class="row my-4 justify-content-center">
<div class="col-12 col-md-6">
<div class="title mb-4">
<span>Fediverse Groups</span>
<button class="btn btn-light font-weight-bold" @click="toggleTab('home')">Go Back</button>
</div>
<div class="mt-3">
<div class="bg-white border text-center p-3">
<p class="font-weight-light mb-0">No fediverse groups found</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script type="text/javascript">
import GroupListCard from './GroupListCard.vue';
export default {
props: {
profile: {
type: Object
}
},
components: {
"group-list-card": GroupListCard
},
data() {
return {
isLoaded: false,
tab: 'home',
popularGroups: [],
newGroups: [],
activeCategoryIndex: undefined,
activeCategoryPage: 1,
categories: [],
categoriesStart: 0,
categoriesEnd: 6,
categoryGroups: [],
categoryGroupsLoaded: false,
categoryGroupsCanLoadMore: false,
// selfGroups: [],
// selfGroupsStart: 0,
// selfGroupsEnd: 3
}
},
mounted() {
this.fetchPopular();
this.fetchCategories();
// this.fetchSelf();
},
methods: {
fetchPopular() {
axios.get('/api/v0/groups/discover/popular')
.then(res => {
this.popularGroups = res.data;
this.fetchNew();
})
},
fetchNew() {
axios.get('/api/v0/groups/discover/new')
.then(res => {
this.newGroups = res.data;
})
},
fetchCategories() {
axios.get('/api/v0/groups/categories/list')
.then(res => {
this.categories = res.data;
})
},
toggleTab(tab) {
window.scrollTo(0, 0);
this.tab = tab;
},
selectCategory(index) {
window.scrollTo(0, 0);
if(index !== this.activeCategoryIndex) {
this.activeCategoryPage = 1;
}
this.activeCategoryIndex = index;
this.fetchCategoryGroups();
},
fetchCategoryGroups() {
if(this.activeCategoryPage == 1) {
this.categoryGroupsLoaded = false;
}
axios.get('/api/v0/groups/category/list', {
params: {
name: this.categories[this.activeCategoryIndex],
page: this.activeCategoryPage
}
})
.then(res => {
this.tab = 'category';
if(this.activeCategoryPage == 1) {
this.categoryGroups = res.data;
} else {
this.categoryGroups.push(...res.data);
}
if(res.data.length == 6) {
this.categoryGroupsCanLoadMore = true;
this.activeCategoryPage++;
} else {
this.categoryGroupsCanLoadMore = false;
}
setTimeout(() => {
this.categoryGroupsLoaded = true;
}, 600);
})
}
}
}
</script>
<style lang="scss">
.self-discover-component {
.list-group-item {
text-decoration: none;
&:hover {
background-color: #F3F4F6;
}
}
.bg-mantle {
background: linear-gradient(45deg, #24c6dc, #514a9d);
}
.bg-black {
background-color: #000;
hr {
border-top: 1px solid rgba(255, 255, 255, 0.12);
}
}
.title {
display: flex;
justify-content: space-between;
align-items: center;
span {
font-size: 24px;
font-weight: 600;
}
.btn {
border: 1px solid #E5E7EB;
}
}
}
</style>