youtube-ulbi-vue/src/pages/PostsPageWithStore.vue
2025-01-16 06:40:25 +03:00

135 lines
3.0 KiB
Vue

<template>
<div>
<h1>Страница постов (Vuex)</h1>
<my-input
v-focus
:model-value="searchQuery"
@update:model-value="setSearchQuery"
placeholder="Поиск"
class="search"
/>
<div class="app__btns">
<my-button @click="showCreateDialog" class="createBtn">
Создать пост
</my-button>
<my-select
:model-value="selectedSort"
@update:model-value="setSelectedSort"
:options="sortOptions"
/>
</div>
<my-dialog v-model:show="dialogVisible">
<post-form @createPost="createPost" />
</my-dialog>
<div v-if="isPostLoading" style="margin-top: 15px">Loading...</div>
<post-list v-else :posts="sortedAndSearchedPosts" @removePost="removePost" class="postList"/>
<div v-intersection="getIntersectionData()" ref="observer" class="observer"></div>
</div>
</template>
<script>
import PostForm from '@/components/PostForm.vue';
import PostList from '@/components/PostList.vue';
import {mapActions, mapState, mapGetters, mapMutations} from 'vuex';
export default {
components: {
PostForm,
PostList
},
data() {
return {
dialogVisible: false,
}
},
methods: {
...mapMutations({
setPage: 'post/setPage',
setSearchQuery: 'post/setSearchQuery',
setSelectedSort: 'post/setSelectedSort',
}),
...mapActions({
fetchPosts: 'post/fetchPosts',
loadMorePost: 'post/loadMorePost'
}),
createPost(newPost) {
this.posts.push(newPost);
this.dialogVisible = false;
},
removePost(post) {
this.posts = this.posts.filter(p => p.id !== post.id)
},
showCreateDialog() {
this.dialogVisible = true;
},
getIntersectionData() {
return {
loadMorePost: this.loadMorePost,
page: this.page,
totalPages: this.totalPages,
}
}
},
computed: {
...mapState({
posts: (state) => state.post.posts,
isPostLoading: (state) => state.post.isPostLoading,
selectedSort: (state) => state.post.selectedSort,
sortOptions: (state) => state.post.sortOptions,
searchQuery: (state) => state.post.searchQuery,
page: (state) => state.post.page,
limit: (state) => state.post.limit,
totalPages: (state) => state.post.totalPagess
}),
...mapGetters({
sortedPost: 'post/sortedPost',
sortedAndSearchedPosts: 'post/sortedAndSearchedPosts'
})
},
watch: {
dialogVisible(newValue) {
if (newValue) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = 'auto';
}
},
},
mounted() {
this.fetchPosts();
}
}
</script>
<style>
.createBtn {
margin-top: 15px;
}
.postList {
margin-top: 15px;
}
.app__btns {
display: flex;
justify-content: space-between;
align-items: center;
}
.search {
margin-top: 15px;
}
.observer {
height: 0px;
background: teal;
}
</style>