Profile페이지를 구현하도록 하겠다.
<script>
import Trends from "../components/Trends.vue";
import Tweet from "../components/Tweet.vue";
import store from "../store";
import { computed, ref, onBeforeMount } from "vue";
import {
onSnapshot,
doc,
collection,
where,
orderBy,
query,
} from "firebase/firestore";
import { db } from "../firebase";
import getTweetInfo from "../utils/getTweetInfo";
import moment from "moment";
export default {
components: { Trends, Tweet },
setup() {
const currentUser = computed(() => store.state.user);
const tweets = ref([]);
onBeforeMount(() => {
//get user
const userDocRef = doc(db, "users", currentUser.value.uid);
const getUserInfo = query(userDocRef);
const un = onSnapshot(getUserInfo, (doc) => {
store.commit("SET_USERS", doc.data());
});
//get tweets
const q = query(
collection(db, "tweets"),
where("uid", "==", currentUser.value.uid),
orderBy("created_at", "desc")
);
const unsubscribe = onSnapshot(q, (snapshot) => {
snapshot.docChanges().forEach(async (change) => {
let tweet = await getTweetInfo(change.doc.data(), currentUser.value);
if (change.type === "added") {
tweets.value.splice(change.newIndex, 0, tweet);
}
if (change.type === "modified") {
tweets.value.splice(change.oldIndex, 1, tweet);
}
if (change.type === "removed") {
tweets.value.splice(change.oldIndex, 1);
}
});
});
});
return {
currentUser,
tweets,
moment,
};
},
};
</script>
<div class="flex flex-1">
<!-- 프로필 섹션 -->
<div class="flex-1 flex flex-col border-r border-color">
<!-- title -->
<div class="px-3 py-1 flex border-b border-color">
<button class="mr-4">
<i
class="fas fa-arrow-left text-primary p-3 py-1 rounded-full hover:bg-blue-50"
></i>
</button>
<div>
<div class="font-extrabold text-lg">{{ currentUser.email }}</div>
<div class="text-xs text-gray">{{ currentUser.num_tweets }} 트윗</div>
</div>
</div>
<!-- 프로필 백그라운드 이미지-->
<div class="bg-gray-300 h-40 relative flex-none">
<!-- 프로필이미지 -->
<div
class="w-28 h-28 border-4 border-white bg-gray-100 rounded-full absolute -bottom-14 left-2"
>
<img
:src="`${currentUser.profile_image_url}`"
class="rounded-full opacity-90 hover:opacity-100 cursor-pointer"
/>
</div>
</div>
<!-- 프로필 수정 버튼 -->
<div class="text-right mr-2 mt-2">
<button
class="border border-primary text-primary px-3 py-2 hover:bg-blue-50 font-bold rounded-full text-sm"
>
프로필 수정
</button>
</div>
<!-- 유저 정보 -->
<div class="mx-3 mt-2">
<div class="font-extrabold text-lg">{{ currentUser.email }}</div>
<div class="text-gray">@{{ currentUser.username }}</div>
<div>
<span class="text-gray">가입일:</span>
<span class="text-gray">
{{ moment(currentUser.created_at).format("YYYY년 MM월") }}</span
>
</div>
<div>
<span class="font-bold mr-1">{{
currentUser.followings.length
}}</span>
<span class="text-gray mr-3">팔로우 중</span>
<span class="font-bold mr-1">{{ currentUser.followers.length }}</span>
<span class="text-gray">팔로워</span>
</div>
</div>
그리고 트윗 반복문을 수정한다.
<!-- 트윗들 -->
<div class="overflow-y-auto">
<Tweet
v-for="tweet in tweets"
:tweet="tweet"
:key="tweet"
:currentUser="currentUser"
/>
</div>
</div>
<!-- 트랜드 섹션 -->
<Trends />
</div>
</template>
아래와 같이 현재 접속중인 유저의 정보를 가져와서 표시한다.
이제 각 탭을
트윗/ 리트윗/ 마음에 들어요로 변경할거
<!-- 탭들 -->
<div class="flex border-b border-color mt-3">
<div
class="py-3 w-1/3 text-primary font-bold border-b border-primary text-center hover:bg-blue-50 cursor-pointer hover:text-primary"
>
트윗
</div>
<div
class="py-3 w-1/3 text-gray font-bold text-center hover:bg-blue-50 cursor-pointer hover:text-primary"
>
리트윗
</div>
<div
class="py-3 w-1/3 text-gray font-bold text-center hover:bg-blue-50 cursor-pointer hover:text-primary"
>
좋아요
</div>
</div>
.
그리고
변수를 만들어서 각 탭을 클릭하면 그 탭에 class를 주도록 한다.
const currentTab = ref("tweet");
그리고 클릭 이벤트로 tab의 값을 바꿔준다.
:class로 currentTab의 값에 따라 class를 준다.
<!-- 탭들 -->
<div class="flex border-b border-color mt-3">
<div
@click="currentTab = 'tweet'"
:class="`${
currentTab == 'tweet' ? 'border-b border-primary' : 'text-gray'
} py-3 w-1/3 text-primary font-bold text-center hover:bg-blue-50 cursor-pointer hover:text-primary`"
>
트윗
</div>
<div
@click="currentTab = 'retweet'"
:class="`${
currentTab == 'retweet' ? 'border-b border-primary' : 'text-gray'
} py-3 w-1/3 text-primary font-bold text-center hover:bg-blue-50 cursor-pointer hover:text-primary`"
>
리트윗
</div>
<div
@click="currentTab = 'like'"
:class="`${
currentTab == 'like' ? 'border-b border-primary' : 'text-gray'
} py-3 w-1/3 text-primary font-bold text-center hover:bg-blue-50 cursor-pointer hover:text-primary`"
>
좋아요
</div>
</div>
그리고 각 탭에 맞게 데이터를 가져와야함
현재 tweets를 가져오는 것 처럼
const tweets = ref([]);
const reTweets = ref([]);
const likes = ref([]);
likes와 retweets는 트윗의 내용을 가지고 있지 않음
그래서 데이터를 가져와서 각 변수에 저장할 때 from_tweet_id를 가지고 tweet 컬렉션에서 정보를 가져와서
각 변수에 담아준다.
onBeforeMount(() => {
//get user
const userDocRef = doc(db, "users", currentUser.value.uid);
const getUserInfo = query(userDocRef);
const un = onSnapshot(getUserInfo, (doc) => {
store.commit("SET_USERS", doc.data());
});
//get tweets
const tweetsQuery = query(
collection(db, "tweets"),
where("uid", "==", currentUser.value.uid),
orderBy("created_at", "desc")
);
const tweetsUn = onSnapshot(tweetsQuery, (snapshot) => {
snapshot.docChanges().forEach(async (change) => {
let tweet = await getTweetInfo(change.doc.data(), currentUser.value);
if (change.type === "added") {
tweets.value.splice(change.newIndex, 0, tweet);
}
if (change.type === "modified") {
tweets.value.splice(change.oldIndex, 1, tweet);
}
if (change.type === "removed") {
tweets.value.splice(change.oldIndex, 1);
}
});
});
//get retweets
const retweetsQuery = query(
collection(db, "retweets"),
where("uid", "==", currentUser.value.uid),
orderBy("created_at", "desc")
);
const retweetsUn = onSnapshot(retweetsQuery, (snapshot) => {
snapshot.docChanges().forEach(async (change) => {
const docRef = doc(db, "tweets", change.doc.data().from_tweet_id);
const docSnap = await getDoc(docRef); // Fetch the document snapshot
if (docSnap.exists()) {
// Ensure the document exists
let retweet = await getTweetInfo(docSnap.data(), currentUser.value);
if (change.type === "added") {
reTweets.value.splice(change.newIndex, 0, retweet);
}
if (change.type === "modified") {
reTweets.value.splice(change.oldIndex, 1, retweet);
}
if (change.type === "removed") {
reTweets.value.splice(change.oldIndex, 1);
}
}
});
});
//get likes
const likesQuery = query(
collection(db, "likes"),
where("uid", "==", currentUser.value.uid),
orderBy("created_at", "desc")
);
const likesUn = onSnapshot(likesQuery, (snapshot) => {
snapshot.docChanges().forEach(async (change) => {
const docRef = doc(db, "tweets", change.doc.data().from_tweet_id);
const docSnap = await getDoc(docRef); // Fetch the document snapshot
if (docSnap.exists()) {
// Ensure the document exists
let like = await getTweetInfo(docSnap.data(), currentUser.value);
if (change.type === "added") {
likes.value.splice(change.newIndex, 0, like);
}
if (change.type === "modified") {
likes.value.splice(change.oldIndex, 1, like);
}
if (change.type === "removed") {
likes.value.splice(change.oldIndex, 1);
}
}
});
});
});
그리고 tweet 컴포넌트 반복되는 부분에
currentTab: 현재 탭이 tweet이면 tweets를 반복하고
retweet이며 reTweets를 반복 아니면 likes를 반복하게 코드를 수정한다.
그러면 각 탭을 클릭할때마다 그 탭에 맞는 데이터들이 반복됨
<!-- 트윗들 -->
<div class="overflow-y-auto">
<Tweet
v-for="tweet in currentTab == 'tweet'
? tweets
: currentTab == 'retweet'
? reTweets
: likes"
:tweet="tweet"
:key="tweet"
:currentUser="currentUser"
/>
</div>
'FRONTEND > Vue' 카테고리의 다른 글
[Vue3 + vite + tailwindCSS] 프로필 수정(firebase storage에 이미지 저장) (0) | 2024.04.11 |
---|---|
[Vue3 + vite + tailwindCSS] 다른 유저 프로필 보기 (0) | 2024.04.11 |
[Vue3 + vite + tailwindCSS] 트윗 상세보기 (tweet,comment) (0) | 2024.03.28 |
[Vue3 + vite + tailwindCSS] 좋아요 기능 추가 (0) | 2024.03.28 |
[Vue3 + vite + tailwindCSS] 리트윗 기능 추가 (0) | 2024.03.28 |