Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/Nubblee/Nubble-FE into f…
Browse files Browse the repository at this point in the history
…eature/mainPage-39
  • Loading branch information
ssuminii committed Nov 11, 2024
2 parents 7ac1455 + fe8f910 commit 5397e35
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 31 deletions.
28 changes: 16 additions & 12 deletions src/components/FloatingMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
/** @jsxImportSource @emotion/react */
import colors from '@/constants/color'
import { useAuthStore } from '@/stores/authStore'
import { useLikeStore } from '@/stores/likeStore'
import styled from '@emotion/styled'
import { useState } from 'react'
import { HeartIcon, Share2Icon } from 'lucide-react'
import colors from '@/constants/color'
import { useParams } from 'react-router-dom'

const FloatingMenu = () => {
const [liked, setLiked] = useState(false)
const [likeCount, setLikeCount] = useState(0)
const { liked, likeCount, toggleLike } = useLikeStore()

const { sessionId } = useAuthStore()
const { postId } = useParams<{ postId: string }>()

const handleLikeClick = () => {
setLiked(!liked)
setLikeCount(liked ? likeCount - 1 : likeCount + 1)
const handleLikeClick = async () => {
if (!postId) return
toggleLike(postId, sessionId as string)
}

const handleCopyUrl = async () => {
Expand All @@ -19,7 +23,7 @@ const FloatingMenu = () => {
await navigator.clipboard.writeText(currentUrl)
alert('클립보드에 링크가 복사되었어요.')
} catch (err) {
console.log(err)
console.error('링크 복사 실패:', err)
}
}

Expand Down Expand Up @@ -56,19 +60,19 @@ const MenuContainer = styled.div`
border-radius: 30px;
transition:
left 0.3s ease,
top 0.3s ease; /* 위치 변경을 부드럽게 만듦 */
top 0.3s ease;
@media (max-width: 1440px) {
left: 12%; /* 1440px 이하에서 점진적으로 변경 */
left: 12%;
top: 26%;
}
@media (max-width: 1280px) {
left: 9%; /* 1280px 이하에서 위치 변경 */
left: 9%;
}
@media (max-width: 1090px) {
display: none; /* 1080px 이하에서는 메뉴를 숨김 */
display: none;
}
`

Expand Down
2 changes: 1 addition & 1 deletion src/components/comment/CommentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const CommentForm = () => {
console.log('비로그인 댓글 제출', res.data)
} else {
const res = await postMemberComment()
console.log('비로그인 댓글 제출', res.data)
console.log('멤버 댓글 제출', res.data)
}
setSubmitSuccess(true)
setFormData({ nickname: '', password: '', comment: '' })
Expand Down
62 changes: 48 additions & 14 deletions src/components/comment/CommentList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { formatDate } from '@/utils/formatDate'
import { useAuthStore } from '@/stores/authStore'
import useModalStore from '@/stores/modalStore'
import Modal from '@components/Modal'
import { ShowToast } from '@components/Toast'

interface Comment {
commentId: number
Expand Down Expand Up @@ -46,42 +47,75 @@ const CommentList = () => {
const handleDelete = async (commentId: number, type: 'MEMBER' | 'GUEST', password?: string) => {
try {
if (type === 'MEMBER') {
await axios.delete(
`http://nubble-backend-eb-1-env.eba-f5sb82hp.ap-northeast-2.elasticbeanstalk.com/comments/member/${commentId}`,
{
headers: { 'SESSION-ID': sessionId },
// 멤버는 default 타입 모달 띄우기
openModal({
type: 'default',
title: '댓글 삭제 확인',
onAction: async () => {
try {
// 실제 삭제 요청
await axios.delete(
`http://nubble-backend-eb-1-env.eba-f5sb82hp.ap-northeast-2.elasticbeanstalk.com/comments/member/${commentId}`,
{
headers: { 'SESSION-ID': sessionId },
},
)
ShowToast('댓글이 삭제되었습니다.', 'success')
// 삭제 후 상태 업데이트
setCommentsData((prevComments) =>
prevComments.filter((comment) => comment.commentId !== commentId),
)
} catch (error) {
console.error('댓글 삭제 중 에러 발생:', error)
ShowToast('댓글 삭제 중 오류가 발생했습니다.', 'failed')
}
},
)
})
} else {
// 비밀번호가 없는 경우 모달을 열어 비밀번호 요청
// 게스트는 password 타입 모달 띄우기
if (!password) {
openModal({
type: 'password',
title: '댓글 삭제 확인',
onAction: (inputPassword) => handleDelete(commentId, 'GUEST', inputPassword),
onAction: async (inputPassword) => {
try {
await axios.delete(
`http://nubble-backend-eb-1-env.eba-f5sb82hp.ap-northeast-2.elasticbeanstalk.com/comments/guest/${commentId}`,
{
headers: { 'Content-Type': 'application/json' },
data: { guestPassword: inputPassword },
},
)
// 삭제 후 상태 업데이트는 여기에서 실행
setCommentsData((prevComments) =>
prevComments.filter((comment) => comment.commentId !== commentId),
)
ShowToast('댓글이 삭제되었습니다.', 'success')
} catch (error) {
ShowToast('비밀번호가 틀렸습니다.', 'failed')
}
},
})
return
}

// 비밀번호가 있는 경우 삭제 요청 진행
// 비밀번호가 제공된 경우 삭제 진행
await axios.delete(
`http://nubble-backend-eb-1-env.eba-f5sb82hp.ap-northeast-2.elasticbeanstalk.com/comments/guest/${commentId}`,
{
headers: { 'Content-Type': 'application/json' },
data: { guestPassword: password },
},
)
// 삭제 후 상태 업데이트
setCommentsData((prevComments) =>
prevComments.filter((comment) => comment.commentId !== commentId),
)
}

// 댓글 삭제 후 상태 업데이트
setCommentsData((prevComments) =>
prevComments.filter((comment) => comment.commentId !== commentId),
)
} catch (error) {
console.error('댓글 삭제 중 에러 발생:', error)
}
}

if (error) return <p>{error}</p>
if (!commentsData.length) return <p>댓글이 없습니다.</p>

Expand Down
10 changes: 7 additions & 3 deletions src/pages/AddQuestion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,13 @@ const AddQuestion = () => {
useEffect(() => {
const getCodingTestList = async () => {
try {
const res = await axios.get(`${import.meta.env.VITE_NUBBLE_SERVER}/coding-problems`)
const data = res.data.problems.map((problem: any) => ({
id: problem.problemId, // problemId 필드를 id로 저장
const res = await axios.get<{ problems: Question[] }>(
`${import.meta.env.VITE_NUBBLE_SERVER}/coding-problems`,
)

// ProblemResponse 배열을 Question 배열로 변환
const data: Question[] = res.data.problems.map((problem) => ({
id: problem.id,
quizDate: problem.quizDate,
problemTitle: problem.problemTitle,
}))
Expand Down
7 changes: 6 additions & 1 deletion src/pages/PostDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import colors from '@/constants/color'
import { fontSize } from '@/constants/font'
import { useAuthStore } from '@/stores/authStore'
import { useLikeStore } from '@/stores/likeStore'
import { formatDate } from '@/utils/formatDate'
import CommentForm from '@components/comment/CommentForm'
import CommentList from '@components/comment/CommentList'
Expand Down Expand Up @@ -30,6 +31,7 @@ const PostDetail = () => {
const { sessionId } = useAuthStore()
const navigate = useNavigate()
const { userName } = useAuthStore()
const { setLikeData, liked, likeCount } = useLikeStore()

const handlePostEdit = () => {
navigate(`/write?id=${postId}`, { state: { postData } })
Expand All @@ -46,10 +48,13 @@ const PostDetail = () => {
},
})
setPostData(res.data)
if (res.data.postLiked !== liked || res.data.likeCount !== likeCount) {
setLikeData(res.data.postLiked, res.data.likeCount)
}
console.log(res.data)

if (res.data.title !== title) {
navigate('/error') // 에러 페이지 경로에 맞게 수정
navigate('/error')
}
} catch (err: unknown) {
if (axios.isAxiosError(err)) {
Expand Down
56 changes: 56 additions & 0 deletions src/stores/likeStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { create } from 'zustand'
import axios from 'axios'

interface LikeStore {
liked: boolean
likeCount: number
toggleLike: (postId: string, sessionId: string) => Promise<void>
setLikeData: (liked: boolean, likeCount: number) => void // 초기 데이터를 설정하는 함수
}

export const useLikeStore = create<LikeStore>((set) => ({
liked: false,
likeCount: 0,

setLikeData: (liked, likeCount) => set({ liked, likeCount }),

toggleLike: async (postId, sessionId) => {
if (!sessionId) {
alert('로그인이 필요합니다.')
return
}

const currentLiked = useLikeStore.getState().liked
const currentLikeCount = useLikeStore.getState().likeCount

// 낙관적 업데이트
set({
liked: !currentLiked,
likeCount: currentLiked ? currentLikeCount - 1 : currentLikeCount + 1,
})

try {
if (!useLikeStore.getState().liked) {
await axios.delete(`${import.meta.env.VITE_NUBBLE_SERVER}/posts/${postId}/likes`, {
headers: {
'SESSION-ID': sessionId,
},
})
} else {
await axios.put(
`${import.meta.env.VITE_NUBBLE_SERVER}/posts/${postId}/likes`,
{},
{
headers: {
'SESSION-ID': sessionId,
},
},
)
}
} catch (err) {
console.error('좋아요 요청 실패:', err)
// 요청 실패 시 원래 상태로 롤백
set({ liked: currentLiked, likeCount: currentLikeCount })
}
},
}))

0 comments on commit 5397e35

Please sign in to comment.