원하는 트윗을 클릭하면
트윗 페이지로 이동해서
트윗의 상세 정보와 댓글들을 확인할 수 있는 페이지를 만들거임
router
-> index.js에 tweet 페이지를 추가한다.
{
path: "/tweet/:id",
name: "tweet",
component: Tweet,
meta: { isMenu: false, layout: "DefaultLayout", requireAuth: true },
},
pages에서 Tweet 컴포넌트 생성
router import 해서
뒤로가기 버튼 클릭하면 router.go(-1)하면 이전페이지로 돌아감 (신기)
<template>
<div class="flex-1 flex">
<div class="flex-1 border-r border-gray-100">
<div class="flex flex-col">
<!-- title -->
<div
class="flex justify-start items-center px-3 py-2 border-b border-gray-100"
>
<button @click="router.go(-1)">
<i
class="fas fa-arrow-left text-primary text-lg ml-3 hover:bg-blue-50 p2 rounded-full h-8 w-8"
></i>
</button>
<span class="font-bold text-lg ml-6">트윗</span>
</div>
<!-- tweet -->
<div class="px-3 py-2 flex">
<img
class="w-10 h-10 rounded-full hover:opacity-90"
/>
<div class="ml-2">
<div class="font-bold">이메일</div>
<div class="text-gray text-sm">@id</div>
</div>
</div>
<div class="px-3 py-2">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Obcaecati
cupiditate molestias, temporibus, sapiente consectetur atque saepe
quibusdam aut at culpa delectus quas sed impedit! Tempora suscipit est
quam id natus.
</div>
<div class="px-3 py-2 text-gray text-xs">오후:7:00 2021년 2월 20일</div>
<div class="h-px w-full bg-gray-100"></div>
<div class="flex space-x-2 px-3 py-2 items-center">
<span class="">1</span>
<span class="text-sm text-gray">리트윗</span>
<span class="ml-5">1</span>
<span class="text-sm text-gray">마음에 들어요</span>
</div>
<div class="h-px w-full bg-gray-100"></div>
<!-- buttons -->
<div class="flex justify-around py-2">
<button>
<i
class="far fa-comment text-gray-400 text-xl hover:bg-blue-50 hover:text-primary p-2 rounded-full w-10 h-10"
></i>
</button>
<button>
<i
class="fas fa-retweet text-gray-400 text-xl hover:bg-green-50 hover:text-green-400 p-2 rounded-full w-10 h-10"
></i>
</button>
<button>
<i
class="far fa-heart text-gray-400 text-xl hover:bg-red-50 hover:text-red-400 p-2 rounded-full w-10 h-10"
></i>
</button>
</div>
<div class="h-px w-full bg-gray-100"></div>
<!-- comments -->
<div
v-for="comment in 10"
:key="comment"
class="flex hover:bg-gray-100 cursor-pointer px-3 py-3 border-b border-gray-100"
>
<img
class="w-10 h-10 rounded-full hover:opacity-90"
/>
<div class="ml-2 flex-1">
<div class="flex items-center space-x-2">
<span class="font-bold">hong@gmail.com</span>
<span class="text-gray text-sm">hong</span>
<span>19 days ago</span>
</div>
<div>댓글</div>
</div>
<button>
<i
class="fas fa-trash text-red-400 hover:bg-red-50 w-10 h-10 rounded-full p-2"
></i>
</button>
</div>
</div>
</div>
<Trends />
</div>
</template>
<script>
import Trends from "../components/Trends.vue";
import router from "../router";
export default {
components: { Trends },
setup() {
return {
router,
};
},
};
</script>
<style></style>
현재는 실제 데이터를 넣은것이 아닌 더미데이터를 넣었다.
Tweet 컴포넌트에서
트윗 바디를 클릭하면 상세보기 페이지로 넘어갈수있게
router-link로 교체한다.
<!-- 트윗 바디 -->
<router-link :to="`/tweet/${tweet.id}`">
{{ tweet.tweet_body }}
</router-link>
이제 트윗을 클릭하면
트윗 페이지로 넘어간다.
이제 실제 데이터로 교체하면됨
Tweet페이지에서
<script>
import Trends from "../components/Trends.vue";
import router from "../router";
import { onBeforeMount, ref, computed } from "vue";
import store from "../store";
import { useRoute } from "vue-router";
import { doc, onSnapshot } from "firebase/firestore";
import getTweetInfo from "../utils/getTweetInfo";
import { db } from "../firebase";
import moment from "moment";
export default {
components: { Trends },
setup() {
const tweet = ref(null);
const comments = ref([]);
const currentUser = computed(() => store.state.user);
const route = useRoute();
onBeforeMount(async () => {
const unsub = onSnapshot(
doc(db, "tweets", route.params.id),
async (doc) => {
let t = await getTweetInfo(doc.data(), currentUser.value);
tweet.value = t;
}
);
});
return {
router,
tweet,
comments,
currentUser,
moment,
};
},
};
</script>
onSnapshot으로 실시간 데이터를 가져옴
그리고 그 데이터를 return 해서
<template>
<div class="flex-1 flex">
<div class="flex-1 border-r border-gray-100">
<div class="flex flex-col" v-if="tweet">
<!-- title -->
<div
class="flex justify-start items-center px-3 py-2 border-b border-gray-100"
>
<button @click="router.go(-1)">
<i
class="fas fa-arrow-left text-primary text-lg ml-3 hover:bg-blue-50 p2 rounded-full h-8 w-8"
></i>
</button>
<span class="font-bold text-lg ml-6">트윗</span>
</div>
<!-- tweet -->
<div class="px-3 py-2 flex">
<img
:src="`${tweet.profile_image_url}`"
class="w-10 h-10 rounded-full hover:opacity-90"
/>
<div class="ml-2">
<div class="font-bold">{{ tweet.email }}</div>
<div class="text-gray text-sm">@{{ tweet.username }}</div>
</div>
</div>
<div class="px-3 py-2">
{{ tweet.tweet_body }}
</div>
<div class="px-3 py-2 text-gray text-xs">
{{ moment(tweet.created_at).fromNow() }}
</div>
<div class="h-px w-full bg-gray-100"></div>
<div class="flex space-x-2 px-3 py-2 items-center">
<span class="">{{ tweet.num_retweets }}</span>
<span class="text-sm text-gray">리트윗</span>
<span class="ml-5">{{ tweet.num_likes }}</span>
<span class="text-sm text-gray">마음에 들어요</span>
</div>
<div class="h-px w-full bg-gray-100"></div>
<!-- buttons -->
<div class="flex justify-around py-2">
<button>
<i
class="far fa-comment text-gray-400 text-xl hover:bg-blue-50 hover:text-primary p-2 rounded-full w-10 h-10"
></i>
</button>
<button>
<i
class="fas fa-retweet text-gray-400 text-xl hover:bg-green-50 hover:text-green-400 p-2 rounded-full w-10 h-10"
></i>
</button>
<button>
<i
class="far fa-heart text-gray-400 text-xl hover:bg-red-50 hover:text-red-400 p-2 rounded-full w-10 h-10"
></i>
</button>
</div>
<div class="h-px w-full bg-gray-100"></div>
<!-- comments -->
<div
v-for="comment in 10"
:key="comment"
class="flex hover:bg-gray-100 cursor-pointer px-3 py-3 border-b border-gray-100"
>
<img
class="w-10 h-10 rounded-full hover:opacity-90"
/>
<div class="ml-2 flex-1">
<div class="flex items-center space-x-2">
<span class="font-bold">hong@gmail.com</span>
<span class="text-gray text-sm">hong</span>
<span>19 days ago</span>
</div>
<div>댓글</div>
</div>
<button>
<i
class="fas fa-trash text-red-400 hover:bg-red-50 w-10 h-10 rounded-full p-2"
></i>
</button>
</div>
</div>
</div>
<Trends />
</div>
</template>
데이터를 넣어줌
저번에 작성한것과 같이 이거는 작성일을 기준으로 오늘까지 몇일 지났는지 확인할 수 있게 해줌
{{ moment(tweet.created_at).fromNow() }}
아직 댓글은 안가져온 상태임
아래와 같이 잘 가져왔담.
Tweet 페이지에서
onBeforeMount 에 comments 가져오는 코드를 추가한다.
onBeforeMount(async () => {
const unsub = onSnapshot(
doc(db, "tweets", route.params.id),
async (doc) => {
let t = await getTweetInfo(doc.data(), currentUser.value);
tweet.value = t;
}
);
const q = query(
collection(db, "comments"),
where("from_tweet_id", "==", route.params.id),
orderBy("created_at", "desc")
);
const unsubscribe = onSnapshot(q, (snapshot) => {
snapshot.docChanges().forEach(async (change) => {
let comment = await getTweetInfo(
change.doc.data(),
currentUser.value
);
if (change.type === "added") {
comments.value.splice(change.newIndex, 0, comment);
}
if (change.type === "modified") {
comments.value.splice(change.oldIndex, 1, comment);
}
if (change.type === "removed") {
comments.value.splice(change.oldIndex, 1);
}
});
});
});
return에 comments 추가 후
v-for반복문을 comments로 바꿔준다.
<!-- comments -->
<div
v-for="comment in comments"
:key="comment"
class="flex hover:bg-gray-50 cursor-pointer px-3 py-3 border-b border-gray-100"
>
<img
class="w-10 h-10 rounded-full hover:opacity-90"
/>
<div class="ml-2 flex-1">
<div class="flex items-center space-x-2">
<span class="font-bold">{{ comment.email }}</span>
<span class="text-gray text-sm">@{{ comment.usernae }}</span>
<span> {{ moment(comment.created_at).fromNow() }}</span>
</div>
<div>{{ comment.tweet_body }}</div>
</div>
그리고 오른쪽의 삭제 버튼은
handleDeleteComment함수로 삭제해줄건데
이 버튼은 현재 접속중인 유저와 이 답글을 작성한 유저와 동일해야 보인다.
<button
@click="handleDeleteComment(comment)"
v-if="comment.uid == currentUser.uid"
>
<i
class="fas fa-trash text-red-400 hover:bg-red-50 w-10 h-10 rounded-full p-2"
></i>
</button>
답글 삭제 버튼은 아래와 같다.
deleteDoc을 사용하여 comment의 id를 받아서 삭제하고
tweet의 num_comments의 count를 1줄여준다.
const handleDeleteComment = async (comment) => {
if (confirm("답글을 삭제하시겠습니까?")) {
//delete comment
await deleteDoc(doc(db, "comments", comment.id));
//decrease comment counts
const updateTweetRef = doc(db, "tweets", comment.from_tweet_id);
await updateDoc(updateTweetRef, {
num_comments: increment(-1),
});
}
};
다른 유저로 접근했을 시 삭제 버튼 안보