diff --git a/src/app/board/[boardId]/page.tsx b/src/app/board/[boardId]/page.tsx index c0a34796..1e70d8f3 100644 --- a/src/app/board/[boardId]/page.tsx +++ b/src/app/board/[boardId]/page.tsx @@ -35,6 +35,7 @@ import { colorTicket } from "@/types/board"; import deleteBoard from "@/services/board/delete/deleteBoard"; import Swal from "sweetalert2"; import menubars from "@/dummy/menubars.svg" +import deleteReply from "@/services/board/delete/deleteReply"; export default function BoardPage({ params }: { params: { boardId: number } }) { const accessToken = Cookies.get("accessToken"); @@ -49,6 +50,8 @@ export default function BoardPage({ params }: { params: { boardId: number } }) { const [isReplyOpen, setIsReplyOpen] = useState(true); const [isOpenMenu, setIsOpenMenu] = useState(false); const [parentIds, setParentIds] = useState(0); + const [soloReply, setSoloReply] = useState(false); + const [replyStates, setReplyStates] = useState([]); const { data: postData, refetch: postRefetch } = useQuery({ queryKey: ["postData"], @@ -200,11 +203,13 @@ export default function BoardPage({ params }: { params: { boardId: number } }) { mentionMemberNickName: replyNicknames, mentionCommentId: mentionCommentIds }; + try { console.log(commentData); await postComments(commentData); setReplyComment(""); setReplyOpen(Array(postCommentData?.result.length).fill(false)); + setReplyStates(Array(postCommentData?.result.length).fill(false)); commentRefetch(); postRefetch(); } catch (e) { } @@ -259,6 +264,24 @@ export default function BoardPage({ params }: { params: { boardId: number } }) { } }); } + console.log(userInfo) + const deleteReplyHandler = async (replyIdx: number) => { + await deleteReply(replyIdx) + Swal.fire({ + icon: 'success', + title: '정상적으로 삭제되었습니다.', + confirmButtonText: '확인', + confirmButtonColor: '#FB3463', + customClass: { + popup: 'swal-custom-popup', + icon: 'swal-custom-icon' + } + }).then((result) => { + if (result.isConfirmed) { + commentRefetch(); + } + }); + } const editBoardEdit = () => { router.push(`/edits/${params.boardId}`) @@ -271,7 +294,19 @@ export default function BoardPage({ params }: { params: { boardId: number } }) { const images = postData?.result.post.images || []; const bodyWithImages = replaceImagesInBody(postData?.result.post.body, images); - console.log(postData); + + const handleReplyToggle = (index: number, id: number, nickName: string, memberId: string) => { + // 해당 인덱스의 답글 입력란 상태를 토글 + setReplyStates((prev) => { + const newStates = [...prev]; + newStates[index] = !newStates[index]; // 현재 상태를 반전 + return newStates; + }); + setParentIds(id) + setReplyNickname(nickName); + setReplyMemId(memberId); + }; + console.log(replyId); return (
@@ -492,7 +527,7 @@ export default function BoardPage({ params }: { params: { boardId: number } }) { {isReplyOpen && (
{userInfo && ( -
+
{postCommentData?.result && Object.entries(postCommentData.result).map( ([key, coData]: [string, any], index: number) => { const createDateTime = new Date(coData.createDateTime); - const formattedDateTime = `${createDateTime.getFullYear()}.${String(createDateTime.getMonth() + 1).padStart(2, "0")}.${String(createDateTime.getDate()).padStart(2, "0")} ${String(createDateTime.getHours()).padStart(2, "0")}:${String(createDateTime.getMinutes()).padStart(2, "0")}`; + const formattedDateTime = `${createDateTime.getFullYear()}.${String(createDateTime.getMonth() + 1).padStart(2, '0')}.${String(createDateTime.getDate()).padStart(2, '0')} ${String(createDateTime.getHours()).padStart(2, '0')}:${String(createDateTime.getMinutes()).padStart(2, '0')}`; - console.log(coData); return (
-
+
{formattedDateTime}
- {replyOpen[index] ? ( - toggleReply(index)} - > - 답글취소 - - ) : ( - { - toggleReply(index); - setReplyId(coData.id); - setReplyNickname(coData.member.nickName); - setReplyMemId(coData.member.memberId) - }} - > - 답글달기 - + handleReplyToggle(index, coData.id, coData.member.nickName, coData.member.memberId)} + > + {replyStates[index] ? '답글취소' : '답글달기'} + + {userInfo?.memberId === coData.member.memberId && ( + deleteReplyHandler(coData.id)}>삭제 )} +
+ {replyStates[index] && ( +
+
+
+ + + {memberDatas?.result.nickName} + +
+
+ + @{coData.member.nickName} + + setReplyComment(e.target.value)} + /> +
+
+ +
+ )}
{coData?.children.map((childData: any, childIndex: number) => { const createDateTime = new Date(childData.createDateTime); @@ -586,7 +644,7 @@ export default function BoardPage({ params }: { params: { boardId: number } }) {
)} + {userInfo?.memberId === childData.member.memberId && ( + deleteReplyHandler(childData.id)}>삭제 + )} {/* 답글이 열렸을 때 추가적인 요소를 보여줄 수 있습니다 */} {replyOpen[index] && (
diff --git a/src/app/post/page.tsx b/src/app/post/page.tsx index c923130e..13539384 100644 --- a/src/app/post/page.tsx +++ b/src/app/post/page.tsx @@ -1,16 +1,6 @@ "use client" import Header from '@/components/shared/header/Header' import React, { ChangeEvent, useEffect, useState } from 'react' -import air from '@/dummy/air.svg' -import train from '@/dummy/train.svg' -import bus from '@/dummy/bus.svg' -import bicycle from '@/dummy/bicycle.svg' -import car from '@/dummy/car.svg' -import air1 from '@/dummy/air1.svg' -import train1 from '@/dummy/train1.svg' -import bus1 from '@/dummy/bus1.svg' -import bicycle1 from '@/dummy/bicycle1.svg' -import car1 from '@/dummy/car1.svg' import Image from 'next/image' import searchicon from '@/dummy/search.svg' import uploadImages from "@/dummy/uploadfile.svg" @@ -25,6 +15,7 @@ import Swal from 'sweetalert2' import { colorTicket } from '@/types/board' import MyTinyMCEEditor from '@/components/testEditor/textEditor2' import { getCountry, getCountry1 } from '@/services/board/get/getCountry' +import { PostAirSVG, PostBusSVG, PostBycicleSVG, PostCarSVG, PostTrainSVG } from '@/components/transportsvg/post' interface CountryResult { countryIsoAlp2: string; @@ -44,18 +35,6 @@ function PostWrite() { const [bgColor, setBgColor] = useState('#55FBAF'); const [thumbnailPreview, setThumbnailPreview] = useState(null); const [isTransport, setIsTransport] = useState(false); - const [isImageIdx, setIsImageIdx] = useState([ - { imgsrc: air }, - { imgsrc: train }, - { imgsrc: bus }, - { imgsrc: bicycle }, - { imgsrc: car }, - { imgsrc: air1 }, - { imgsrc: train1 }, - { imgsrc: bus1 }, - { imgsrc: bicycle1 }, - { imgsrc: car1 }, - ]); const [passengerCount, setPassengerCount] = useState(0); const [startDate, setStartDate] = useState(null); const [endDate, setEndDate] = useState(null); @@ -74,6 +53,7 @@ function PostWrite() { const [tags, setTags] = useState([]); const [inputValue, setInputValue] = useState(''); const [ticketColor, setTicketColor] = useState('Aquamarine') + const [isImageIdx, setIsImageIdx] = useState([]); const [postRequests, setPostRequests] = useState({ body: '', images: [] as string[], // 이미지 URL을 저장할 배열 @@ -82,6 +62,16 @@ function PostWrite() { const [result1, setResult1] = useState(null); const [transportStr, setTransportStr] = useState('') + useEffect(() => { + setIsImageIdx([ + { imgsrc: }, + { imgsrc: }, + { imgsrc: }, + { imgsrc: }, + { imgsrc: }, + ]); + }, [ticketColor]); + const formatDate = (date: Date | null) => { if (!date) return ''; return date.toLocaleDateString('ko-KR', { @@ -127,10 +117,10 @@ function PostWrite() { console.log() - const selectTransport = (imgSrc: any) => { + const selectTransport = (imgSrc: JSX.Element) => { setIsImageIdx((prevState) => { // 클릭한 항목의 인덱스를 찾기 - const selectedIndex = prevState.findIndex((item) => item.imgsrc === imgSrc); + const selectedIndex = prevState.findIndex((item) => item.imgsrc.type === imgSrc.type && item.imgsrc.props.fillColor === imgSrc.props.fillColor); // 새로운 배열 생성 const updatedState: any = [...prevState]; @@ -140,24 +130,19 @@ function PostWrite() { const selectedItem = updatedState.splice(selectedIndex, 1)[0]; updatedState.unshift(selectedItem); - // 나머지 항목의 인덱스 업데이트 - for (let i = 0; i < updatedState.length; i++) { - updatedState[i].index = i; - } - // 첫 번째 항목의 src에 따라 setTransportStr 설정 if (updatedState.length > 0) { - const transportValue = updatedState[0].imgsrc.src; // updatedState의 첫 번째 값 사용 + const transportValue = updatedState[0].imgsrc.type.name; // SVG 컴포넌트의 이름 사용 - if (transportValue.includes('bicycle')) { + if (transportValue === 'PostBicycleSVG') { setTransportStr('Bicycle'); - } else if (transportValue.includes('air')) { + } else if (transportValue === 'PostAirSVG') { setTransportStr('Airplane'); - } else if (transportValue.includes('train')) { + } else if (transportValue === 'PostTrainSVG') { setTransportStr('Train'); - } else if (transportValue.includes('bus')) { + } else if (transportValue === 'PostBusSVG') { setTransportStr('Bus'); - } else if (transportValue.includes('car')) { + } else if (transportValue === 'PostCarSVG') { setTransportStr('Car'); } } else { @@ -338,16 +323,9 @@ function PostWrite() { isTransport ? (
{isImageIdx.slice(0, 5).map((item: any, index) => ( - {`item { - selectTransport(item.imgsrc); - } - } - /> +
selectTransport(item.imgsrc)}> + {item.imgsrc} +
))}
) : ( @@ -355,7 +333,7 @@ function PostWrite() { className='w-[6rem] h-[6rem] absolute shadowall rounded-full flex items-center justify-center mt-[2rem]' onClick={() => setIsTransport(true)} > - 비행기 + {isImageIdx[0]?.imgsrc}
) } diff --git a/src/components/transportsvg/post.tsx b/src/components/transportsvg/post.tsx new file mode 100644 index 00000000..1e404931 --- /dev/null +++ b/src/components/transportsvg/post.tsx @@ -0,0 +1,62 @@ +import React from 'react'; + +export const PostAirSVG = ({ fillColor }: any) => ( + + + + + + + + + + + + + +) + +export const PostBusSVG = ({ fillColor }: any) => ( + + + + + + + + +) + +export const PostBycicleSVG = ({ fillColor }: any) => ( + + + + + + + +) + +export const PostCarSVG = ({ fillColor }: any) => ( + + + + + + + + + + +) + +export const PostTrainSVG = ({ fillColor }: any) => ( + + + + + + + + +) \ No newline at end of file diff --git a/src/services/board/delete/deleteReply.tsx b/src/services/board/delete/deleteReply.tsx new file mode 100644 index 00000000..a3b99e9a --- /dev/null +++ b/src/services/board/delete/deleteReply.tsx @@ -0,0 +1,12 @@ +import axios from "axios"; + +const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL; + +export default async function deleteReply(id: number) { + try { + const res = await axios.delete(`${backendUrl}/api/comment/${id}`) + return res.data; + } catch (e) { + return null; + } +} \ No newline at end of file diff --git a/src/styles/globals.css b/src/styles/globals.css index 98d55c6d..c0e2cf3c 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -177,7 +177,7 @@ body { } .shadowall { - box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1); + box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.08); } .selectshadow { @@ -503,15 +503,15 @@ body { } .tag-container { - display: flex; - overflow-x: auto; - white-space: nowrap; - padding: 8px 0; + display: flex; + overflow-x: auto; + white-space: nowrap; + padding: 8px 0; } .tag-item { - display: inline-block; - margin-right: 8px; - white-space: nowrap; -} + display: inline-block; + margin-right: 8px; + white-space: nowrap; +} \ No newline at end of file