Feat: Use api in article detail page
This commit is contained in:
parent
9f340ee6ef
commit
b83426e94c
@ -4,6 +4,7 @@ import { useRoute } from 'vue-router';
|
|||||||
import BoardHeader from './BoardHeader.vue';
|
import BoardHeader from './BoardHeader.vue';
|
||||||
import { getArticle } from '@/api/article';
|
import { getArticle } from '@/api/article';
|
||||||
import CommentArea from './CommentArea.vue';
|
import CommentArea from './CommentArea.vue';
|
||||||
|
import { getComment } from '@/api/comment';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
@ -14,30 +15,9 @@ const comments = ref([]);
|
|||||||
getArticle(id, ({ data }) => {
|
getArticle(id, ({ data }) => {
|
||||||
article.value = data;
|
article.value = data;
|
||||||
});
|
});
|
||||||
|
getComment(id, ({ data }) => {
|
||||||
// FIXME: remove mock data
|
comments.value = data;
|
||||||
setTimeout(() => {
|
});
|
||||||
article.value = {
|
|
||||||
title: '제목',
|
|
||||||
text: '내용',
|
|
||||||
author: '작성자',
|
|
||||||
date: '2024-04-11 13:12:14',
|
|
||||||
};
|
|
||||||
comments.value = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
nickname: '닉네임',
|
|
||||||
date: '2024-04-11 13:12:14',
|
|
||||||
text: '댓글 내용',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
nickname: '닉네임',
|
|
||||||
date: '2024-04-11 13:12:14',
|
|
||||||
text: '댓글 내용',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}, 100);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -46,7 +26,7 @@ setTimeout(() => {
|
|||||||
<h1>{{ article.title }}</h1>
|
<h1>{{ article.title }}</h1>
|
||||||
</template>
|
</template>
|
||||||
<template #info>
|
<template #info>
|
||||||
<div class="author">{{ article.author }}</div>
|
<div class="author">{{ article.name }}</div>
|
||||||
<div class="date">{{ article.date }}</div>
|
<div class="date">{{ article.date }}</div>
|
||||||
</template>
|
</template>
|
||||||
</BoardHeader>
|
</BoardHeader>
|
||||||
@ -56,9 +36,9 @@ setTimeout(() => {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
p {
|
p {
|
||||||
margin: 20px;
|
margin: 40px 20px 20px;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 40px;
|
||||||
border-bottom: 1px solid var(--color-border);
|
border-bottom: 1px solid var(--color-border);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,43 +1,52 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { getArticles } from '@/api/article';
|
import { getArticles } from '@/api/article';
|
||||||
import { ref , reactive } from 'vue';
|
import { ref, reactive, watch } from 'vue';
|
||||||
import { RouterLink } from 'vue-router';
|
import { RouterLink } from 'vue-router';
|
||||||
import FilledButton from '../common/FilledButton.vue';
|
import FilledButton from '../common/FilledButton.vue';
|
||||||
import PageNavigation from "../common/PageNavigation.vue";
|
|
||||||
|
|
||||||
const articles = ref([]);
|
const articles = ref([]);
|
||||||
|
|
||||||
const params = reactive({
|
const params = reactive({
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
key: 'all',
|
key: 'all',
|
||||||
word: ''
|
word: '',
|
||||||
})
|
});
|
||||||
|
const hasNextPage = ref(true);
|
||||||
|
|
||||||
const currentPage = ref(1)
|
const lastElement = ref(null);
|
||||||
const totalpage = ref(1)
|
|
||||||
|
watch(lastElement, (el) => {
|
||||||
|
if (!el) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
([entry]) => {
|
||||||
|
if (entry.isIntersecting && hasNextPage.value) {
|
||||||
|
params.pageNo += 1;
|
||||||
|
searchList();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ threshold: 1 }
|
||||||
|
);
|
||||||
|
|
||||||
|
observer.observe(el);
|
||||||
|
});
|
||||||
|
|
||||||
function searchList() {
|
function searchList() {
|
||||||
getArticles(
|
getArticles(
|
||||||
params,
|
params,
|
||||||
({ data }) => {
|
({ data }) => {
|
||||||
articles.value = data.articles
|
if ((data?.articles?.length ?? 0) === 0) {
|
||||||
currentPage.value = data.page.pageNo
|
hasNextPage.value = false;
|
||||||
totalpage.value = data.page.total
|
return;
|
||||||
console.log(articles.value)
|
}
|
||||||
console.log(currentPage.value)
|
articles.value = [...articles.value, ...(data?.articles ?? [])];
|
||||||
console.log(totalpage.value)
|
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
searchList()
|
searchList();
|
||||||
|
|
||||||
function pageChange(value) {
|
|
||||||
params.pageNo = value
|
|
||||||
searchList()
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -61,7 +70,7 @@ function pageChange(value) {
|
|||||||
</RouterLink>
|
</RouterLink>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<PageNavigation :currentPage="currentPage" :totalPage="totalpage" @page-change="pageChange" />
|
<div ref="lastElement"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { useMemberStore } from '@/stores/memberStore';
|
||||||
import CommentForm from './CommentForm.vue';
|
import CommentForm from './CommentForm.vue';
|
||||||
import CommentList from './CommentList.vue';
|
import CommentList from './CommentList.vue';
|
||||||
|
|
||||||
const { articleId, comments } = defineProps({ articleId: Number, comments: Array });
|
const { articleId, comments } = defineProps({ articleId: Number, comments: Array });
|
||||||
|
const memberStore = useMemberStore();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -10,7 +12,7 @@ const { articleId, comments } = defineProps({ articleId: Number, comments: Array
|
|||||||
<h2>
|
<h2>
|
||||||
댓글 <span>{{ comments.length }}</span>
|
댓글 <span>{{ comments.length }}</span>
|
||||||
</h2>
|
</h2>
|
||||||
<CommentForm :article-id="articleId" />
|
<CommentForm :article-id="articleId" v-if="memberStore.isLogin" />
|
||||||
<CommentList :comments="comments" />
|
<CommentList :comments="comments" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import FilledButton from '../common/FilledButton.vue';
|
import FilledButton from '../common/FilledButton.vue';
|
||||||
import TextButton from '../common/TextButton.vue';
|
import TextButton from '../common/TextButton.vue';
|
||||||
|
import { addComment } from '@/api/comment';
|
||||||
|
|
||||||
const { id } = defineProps({ id: Number });
|
const { id } = defineProps({ id: Number });
|
||||||
const isActive = ref(false);
|
const isActive = ref(false);
|
||||||
@ -20,6 +21,7 @@ function handleCancel() {
|
|||||||
|
|
||||||
function handleSubmit() {
|
function handleSubmit() {
|
||||||
console.log(id, text.value);
|
console.log(id, text.value);
|
||||||
|
addComment({ id, text: text.value });
|
||||||
// TODO: add api call
|
// TODO: add api call
|
||||||
text.value = '';
|
text.value = '';
|
||||||
isActive.value = false;
|
isActive.value = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user