Feat: Add comment component

This commit is contained in:
jhynsoo 2024-05-15 17:59:45 +09:00
parent 19f52d4a48
commit b88e2fe28a
4 changed files with 159 additions and 28 deletions

View File

@ -0,0 +1,23 @@
<script setup>
import CommentForm from './CommentForm.vue';
import CommentList from './CommentList.vue';
const { articleId, comments } = defineProps({ articleId: Number, comments: Array });
</script>
<template>
<div class="comments">
<h2>댓글</h2>
<CommentForm :article-id="articleId" />
<CommentList :comments="comments" />
</div>
</template>
<style scoped>
.comments {
display: flex;
flex-direction: column;
margin: 0 20px;
gap: 12px;
}
</style>

View File

@ -0,0 +1,81 @@
<script setup>
import { ref } from 'vue';
import FilledButton from '../common/FilledButton.vue';
import TextButton from '../common/TextButton.vue';
const { id } = defineProps({ id: Number });
const isActive = ref(false);
const textDiv = ref(null);
const text = ref('');
function handleFocus(e) {
console.log(e);
isActive.value = true;
}
function handleCancel() {
text.value = '';
isActive.value = false;
}
function handleSubmit() {
console.log(id, text.value);
// TODO: add api call
text.value = '';
isActive.value = false;
textDiv.value.blur();
}
</script>
<template>
<form action="POST" @submit.prevent="handleSubmit">
<input type="text" ref="textDiv" v-model="text" @focus="handleFocus" placeholder="댓글 쓰기" />
<div class="control" v-if="isActive">
<TextButton @click="handleCancel">취소</TextButton>
<FilledButton primary type="submit">등록</FilledButton>
</div>
</form>
</template>
<style scoped>
form {
display: flex;
flex-direction: column;
gap: 8px;
}
.control {
display: flex;
justify-self: flex-start;
justify-content: flex-end;
gap: 8px;
}
input {
border: 1px solid var(--color-border);
}
@media (hover: hover) and (pointer: fine) {
button:hover {
background-color: var(--color-background-soft);
}
button[type='submit']:hover {
background-color: var(--color-primary-soft);
}
}
button:active {
transform: scale(0.95);
background-color: var(--color-background-soft);
}
button[type='submit'] {
background-color: var(--color-primary);
color: var(--color-background);
}
button[type='submit']:active {
background-color: var(--color-primary-soft);
}
</style>

View File

@ -0,0 +1,50 @@
<script setup>
import { ref } from 'vue';
import TextButton from '../common/TextButton.vue';
const { comment } = defineProps({ comment: Object });
const isDeleted = ref(false);
function handleDelete() {
console.log('delete', comment.id);
// TODO: add api call
}
</script>
<template>
<li v-if="!isDeleted">
<div class="header">
<div class="info">
<div class="nickname">{{ comment.nickname }}</div>
<div class="date">{{ comment.date }}</div>
</div>
<div v-if="!comment.isAuthor" class="control">
<TextButton @click="handleDelete">삭제</TextButton>
</div>
</div>
<p class="text">{{ comment.text }}</p>
</li>
</template>
<style scoped>
li {
padding: 16px 12px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
.info,
.control {
display: flex;
gap: 12px;
font-size: 14px;
}
.date {
color: var(--color-text-secondary);
}
</style>

View File

@ -1,41 +1,18 @@
<script setup>
import { ref } from 'vue';
import { getComment } from '@/api/comment';
import CommentItem from './CommentItem.vue';
const props = defineProps({ id: Number });
const id = props.id;
const comments = ref([]);
const text = ref('');
getComment(id, ({ data }) => {
comments.value = data;
});
const { comments } = defineProps({ comments: Array });
</script>
<template>
<div>
<h2>댓글</h2>
<input type="text" ref="textDiv" v-model="text" />
</div>
<ul>
<li v-for="comment in comments" :key="comment.id">
<div class="info">
<div class="nickname">{{ comment.nickname }}</div>
<div class="date">{{ comment.date }}</div>
</div>
<div class="info">
<div class="text">{{ comment.text }}</div>
</div>
</li>
<CommentItem v-for="comment in comments" :key="comment.id" :comment="comment" />
</ul>
</template>
<style scoped>
.info {
ul {
display: flex;
gap: 20px;
font-size: 0.8rem;
color: var(--color-text-secondary);
flex-direction: column;
}
</style>