Light Purple Pointer
[Vue3 + vite + tailwindCSS] ํ”„๋กœํ•„ ์ˆ˜์ •(firebase storage์— ์ด๋ฏธ์ง€ ์ €์žฅ)
ยท
FRONTEND/Vue
ํ”„๋กœํ•„ ์ˆ˜์ • ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๋ชจ๋‹ฌ์„ ๋„์›Œ์„œ ํ”„๋กœํ•„์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค์–ด๋ณธ๋‹ค. ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ TweetModal.vue์˜ ๋‚ด์šฉ๋“ค์„ ๋ณต์‚ฌํ•ด์„œ ProfileEdeitModal.vue๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์•ˆ์˜ html ๋ถ€๋ถ„๋“ค์„ ํ•„์š”์— ๋งž๊ฒŒ ๋ณ€๊ฒฝํ•ด์ฃผ๋Š”๋ฐ ํ”„๋กœํ•„ ์ˆ˜์ • ์ €์žฅ ํ˜„์žฌ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋“ค์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค. 1. ๋ฐฑ๊ทธ๋ผ์šด๋“œ์˜ ์นด๋ฉ”๋ผ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํŒŒ์ผ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค๊ณ , ๊ทธ ์‚ฌ์ง„์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์— ์ ์šฉ์‹œํ‚ค๋Š”๊ฒƒ 2. ๋ฐฑ๊ทธ๋ผ์šด๋“œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ”„๋กœํ•„ ํŒŒ์ผ์„ ์„ ํƒ ํ›„ ๋ฐ”๋กœ ํ”„๋กœํ•„์— ์‚ฌ์ง„์ด ๋…ธ์ถœ๋  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์•ผํ•จ html ๊ตฌ์„ฑ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค. button์€ ์นด๋ฉ”๋ผ ์•„์ด์ฝ˜์„ ๋งํ•˜๊ณ  input์€ ์œ„์˜ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ด input์ด ์‹คํ–‰๋˜์–ด์•ผ ํ•จ ๊ทธ๋ž˜์„œ ๋ฒ„ํŠผ์—๋Š” click ์ด๋ฒคํŠธ๋กœ onChangeBackGro..
[Vue3 + vite + tailwindCSS] ๋‹ค๋ฅธ ์œ ์ € ํ”„๋กœํ•„ ๋ณด๊ธฐ
ยท
FRONTEND/Vue
ํ˜„์žฌ๋Š” ํ™ˆ์—์„œ ๋‹ค๋ฅธ ์œ ์ €์˜ ํ”„๋กœํ•„์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ๋‹ค๋ฅธ ์œ ์ €์˜ ํ”„๋กœํ•„์„ ๋ณผ ์ˆ˜ ์—†๋‹ค. ๊ทธ๋ž˜์„œ router์˜ ์ถ”๊ฐ€๋กœ profile/ :uid ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ฃผ์–ด์„œ ๊ฐ ์œ ์ €์— ๋งž๊ฒŒ ํ”„๋กœํ•„์„ ๊ฐ€์ ธ์˜ค๋„๋ก ํ• ๊ฑฐ์ž„ rotuer-> index.js์—์„œ router๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. { path: "/profile", name: "profile", component: Profile, title: "ํ”„๋กœํ•„", icon: "far fa-user fa-fw text-2xl", meta: { isMenu: true, layout: "DefaultLayout", requireAuth: true }, }, { path: "/profile/:uid", component: Profile, icon: "far fa-user fa-fw text-..
[Vue3 + vite + tailwindCSS] ํ”„๋กœํ•„ ํŽ˜์ด์ง€
ยท
FRONTEND/Vue
ProfileํŽ˜์ด์ง€๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค. 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"..
[Vue3 + vite + tailwindCSS] ํŠธ์œ— ์ƒ์„ธ๋ณด๊ธฐ (tweet,comment)
ยท
FRONTEND/Vue
์›ํ•˜๋Š” ํŠธ์œ—์„ ํด๋ฆญํ•˜๋ฉด ํŠธ์œ— ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ด์„œ ํŠธ์œ—์˜ ์ƒ์„ธ ์ •๋ณด์™€ ๋Œ“๊ธ€๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค๊ฑฐ์ž„ 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)ํ•˜๋ฉด ์ด์ „ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ (์‹ ๊ธฐ) ํŠธ์œ— ์ด๋ฉ”์ผ @id Lorem ipsum dolor sit amet, consectetur adipisicing elit. Obcaecati cupiditate..
[Vue3 + vite + tailwindCSS] ์ข‹์•„์š” ๊ธฐ๋Šฅ ์ถ”๊ฐ€
ยท
FRONTEND/Vue
๋ฆฌํŠธ์œ—๊ณผ ๋™์ผํ•˜๊ฒŒ ์ข‹์•„์š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ฉด๋œ๋‹ค. utils์—์„œ handleLikes.js์ถ”๊ฐ€ import { doc, setDoc, collection, updateDoc, increment, deleteDoc, query, where, getDocs, } from "firebase/firestore"; import { db } from "../firebase"; import store from "../store"; export default async (tweet) => { try { //์ด๋ฏธ ์ข‹์•„์š”๋œ ์ƒํƒœ์ธ์ง€ ํ™•์ธํ•˜๊ธฐ if (tweet.isLiked) { const q = query( collection(db, "likes"), where("from_tweet_id", "==", tweet.id), w..
[Vue3 + vite + tailwindCSS] ๋ฆฌํŠธ์œ— ๊ธฐ๋Šฅ ์ถ”๊ฐ€
ยท
FRONTEND/Vue
์ด๋ฒˆ์—๋Š” ๋ฆฌํŠธ์œ— ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๋ฆฌํŠธ์œ— db์ƒ์„ฑ๊ณผ ๋™์‹œ์— ๋ฆฌํŠธ์œ— ์ˆซ์ž๋„ ๋Š˜๋ ค์ค˜์•ผํ•จ utils์— handleRetweet์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌํ•จ import { doc, setDoc, collection, updateDoc, increment, deleteDoc, query, where, getDocs, } from "firebase/firestore"; import { db } from "../firebase"; import store from "../store"; export default async (tweet) => { try { //๋ฆฌํŠธ์œ— ํ•˜์ง€ ์•Š์€ ์ƒํ™ฉ //retweet ์ €์žฅํ•˜๊ธฐ const newRetweetRef = doc(collection(db, "retweets")); awai..
[Vue3 + vite + tailwindCSS] ๊ธ€ ๋ชจ๋‹ฌ๊ณผ ํ•จ์ˆ˜ ์—ฐ๊ฒฐ
ยท
FRONTEND/Vue
์™ผ์ชฝ์— ๋Œ“๊ธ€ ์•„์ด์ฝ˜์„ ํด๋ฆญํ•˜๋ฉด ํŠธ์œ— ๋ชจ๋‹ฌ๊ณผ ๋น„์Šทํ•˜๊ฒŒ ๋‹ต๊ธ€ ๋ชจ๋‹ฌ์ฐฝ์˜ ๋„์›Œ ๋Œ“๊ธ€์„ ๋‹ฌ์•„์ค„ ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค๊ฒƒ์ด๋‹ค. CommentModal.vue๋ฅผ ์ƒ์„ฑํ•˜์—ฌ Tweet.vue์—์„œ ์ปดํฌ๋„ŒํŠธ ๋“ฑ๋ก์„ ํ•œ๋‹ค. import moment from "moment"; import CommentModal from "./CommentModal.vue"; import { ref } from "vue"; export default { components: { CommentModal }, props: ["currentUser", "tweet"], setup() { const showCommentModal = ref(false); return { moment, showCommentModal, }; }, }; ๊ทธ๋ฆฌ๊ณ  showComment..
[Vue3 + vite + tailwindCSS] ํŠธ์œ— ๋ชจ๋‹ฌ๊ณผ ํ•จ์ˆ˜ ์—ฐ๊ฒฐ
ยท
FRONTEND/Vue
ํ˜„์žฌ ํŠธ์œ— ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ถ”๊ฐ€๊ฐ€ ์•ˆ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ํŠธ์œ— ๋ฒ„ํŠผ๊ณผ ํŠธ์œ— ํ•จ์ˆ˜๋ฅผ ์—ฐ๊ฒฐํ• ๊ฑฐ์ž„ ํ™ˆํŽ˜์ด์ง€์—์„œ ์ƒˆ๋กœ์šด ํŠธ์œ—์„ ์ถ”๊ฐ€ํ•˜๋Š”๊ฑฐ๋ž‘ ์ฝ”๋“œ๊ฐ€ ๋™์ผํ•˜๋‹ค ํ•˜์ง€๋งŒ ๋งŒ์•ฝ์— ํŠธ์œ— ์ถ”๊ฐ€ ์ฝ”๋“œ๊ฐ€ ์ˆ˜์ •๋˜๋ฉด ํŠธ์œ— ๋ชจ๋‹ฌ๊ณผ ํ™ˆํŽ˜์ด์ง€ ์ฝ”๋“œ๋ฅผ ๊ฐ๊ฐ ์ˆ˜์ •์„ ํ•ด์ค˜์•ผํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•ด์„œ importํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ฝ”๋“œ ์ˆ˜์ •์„ ์ตœ์†Œํ™” ํ•˜๋„๋ก ํ•œ๋‹ค. src ํด๋” ๋‚ด์— utils ํด๋”๋ฅผ ๋งŒ๋“ค์–ด์„œ addTweet.jsํŒŒ์ผ์„ ๋งŒ๋“ค์—ˆ๋‹ค. addTweet ์—๋Š” Home์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ addTweetํ•จ์ˆ˜๋ฅผ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•˜์—ฌ ๋ถ™์—ฌ๋„ฃ๊ธฐํ•จ ๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ๋ฅผ ์กฐ๊ธˆ ์ˆ˜์ •ํ•œ๋‹ค. 1. export default๋ฅผ ๋ถ™์—ฌ ๋‹ค๋ฅธ ๊ณณ์—์„œ๋„ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ๋งŒ๋“ค์–ด์ฃผ๊ณ  2. ํŠธ์œ— ๋‚ด์šฉ, ํ˜„์žฌ ์‚ฌ์šฉ์ค‘์ธ ์œ ์ € ์ •๋ณด๋ฅผ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค ๊ทธ๋ฆฌ๊ณ  Promi..
[Vue3 + vite + tailwindCSS] ํŠธ์œ— ๋ชจ๋‹ฌ ํŒ์—…
ยท
FRONTEND/Vue
ํŠธ์œ— ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด tailwindcss๋ฅผ ํ™œ์šฉํ•ด์„œ ๋ชจ๋‹ฌ ํŒ์—…์„ ๋งŒ๋“ค์–ด๋ณด๋„๋ก ํ•˜๊ฒ  TweetModal.vue -> ํŠธ์œ— ๋ชจ๋‹ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ ๋‹ค. tailwindcss ํ™ˆํŽ˜์ด์ง€์— ๋“ค์–ด๊ฐ€๋ฉด ๋ฌด๋ฃŒ๋กœ ์ œ๊ณต๋˜๋Š” ๋‹ค์–‘ํ•œ ์ฝ”๋“œ๋“ค์ด ์žˆ๋Š”๋ฐ ๊ทธ ์ค‘ ์•„๋ž˜์˜ ์˜ˆ์‹œ๋ฅผ ์‚ฌ์šฉํ•ด๋ณผ๊ฑฐ์ž„ https://tailwindui.com/components/application-ui/overlays/dialogs Tailwind UI - Official Tailwind CSS Components & Templates Beautiful UI components and templates by the creators of Tailwind CSS. tailwindui.com html์ฝ”๋“œ๋ฅผ ๋ฐ›์•„์„œ template์— ๋ถ™์—ฌ๋„ฃ๊ธฐํ•จ ๊ทธ๋ฆฌ๊ณ  ํŠธ์œ— ๋ชจ๋‹ฌ ์ปดํฌ๋„Œ..
[Vue3 + vite + tailwindCSS] ํŠธ์œ—์— ์œ ์ € ์ •๋ณด ํ‘œ์‹œํ•˜๊ธฐ
ยท
FRONTEND/Vue
ํŠธ์œ— ์ปดํฌ๋„ŒํŠธ์— props๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ค„ ๋•Œ ๊ทธ ํŠธ์œ—์„ ์ž‘์„ฑํ•œ ์œ ์ €์˜ ์ •๋ณด( email, username)๋„ ํ•จ๊ป˜ ๋„˜๊ฒจ์ค˜์•ผ ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ getUserInfo๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠธ์œ—์„ ์ž‘์„ฑํ•  ๋•Œ uid๋กœ ์œ ์ €์ •๋ณด๋ฅผ ๋ฌธ์„œ์—์„œ ๊ฒ€์ƒ‰ํ•ด์„œ ๊ทธ ์œ ์ €์˜ ์ •๋ณด๋„ tweets์— ํ•จ๊ป˜ ๋‹ด์•„์„œ props์— ์ „๋‹ฌํ•˜๋ฉด๋œ๋‹ค. //ํŠธ์œ— ์‹ค์‹œ๊ฐ„ ๊ฐ€์ ธ์˜ค๊ธฐ onBeforeMount(() => { const q = query(collection(db, "tweets"), orderBy("created_at", "desc")); const unsubscribe = onSnapshot(q, (snapshot) => { snapshot.docChanges().forEach(async (change) => { let tweet = awa..
ใ„ด