diff --git a/apps/jurumarble/next.config.js b/apps/jurumarble/next.config.js index 56433112..bbd85efd 100644 --- a/apps/jurumarble/next.config.js +++ b/apps/jurumarble/next.config.js @@ -9,6 +9,15 @@ const nextConfig = { domains: [ "shopping-phinf.pstatic.net", "elasticbeanstalk-ap-northeast-2-319210348301.s3.ap-northeast-2.amazonaws.com", + "img.danawa.com", + "sulsulsul.com", + "shop-phinf.pstatic.net", + "www.sulseam.com", + "mblogthumb-phinf.pstatic.net", + "sogoodk.com", + "modo-phinf.pstatic.net", + "cdn-pro-web-251-115.cdn-nhncommerce.com", + "lh3.googleusercontent.com", ], }, }; diff --git a/apps/jurumarble/src/app/drink-info/[id]/components/DrinkCommentContainer.tsx b/apps/jurumarble/src/app/drink-info/[id]/components/DrinkCommentContainer.tsx new file mode 100644 index 00000000..d64d52fb --- /dev/null +++ b/apps/jurumarble/src/app/drink-info/[id]/components/DrinkCommentContainer.tsx @@ -0,0 +1,117 @@ +import { useQueryClient } from "@tanstack/react-query"; +import Comment from "app/vote/[id]/components/Comment"; +import CommentForm from "app/vote/[id]/components/CommentForm"; +import CommentToolBar from "app/vote/[id]/components/CommentToolbar"; +import useCommentServices from "app/vote/[id]/services/useCommentServices"; +import { queryKeys } from "lib/queryKeys"; +import Link from "next/link"; +import { useParams } from "next/navigation"; +import { useState } from "react"; +import styled from "styled-components"; + +function DrinkCommentContainer() { + const params = useParams(); + const postId = params.id; + const queryClient = useQueryClient(); + const [sortBy, setSortBy] = useState<"ByTime" | "ByPopularity">("ByTime"); + const onChangeFilter = (sort: "ByTime" | "ByPopularity") => { + setSortBy(sort); + }; + + // const { commentFilter, onChangeCommentFilter } = useCommentFilter(); + const { comments, isError, isLoading, mutateHate, mutateLike, mutateComment } = + useCommentServices(Number(postId), sortBy, "drinks"); + + const [commentForm, setCommentForm] = useState(""); + const onChangeCommentForm = (e: React.ChangeEvent) => { + setCommentForm(e.target.value); + }; + const onSubmitComment = () => { + mutateComment( + { + content: commentForm, + parentId: null, + }, + { + onSuccess: () => { + queryClient.invalidateQueries([queryKeys.DETAIL_COMMENT_LIST]); + setCommentForm(""); + }, + }, + ); + }; + + if (isError) return
에러
; + if (!comments) return
데이터 없음
; + + const commentList = comments.pages.flatMap((page) => page.content); + + return ( + <> + + + + + {!isLoading && + commentList.map( + ( + { + id, + age, + content, + createdDate, + gender, + hateCount, + imageUrlstring, + likeCount, + mbti, + nickName, + userId, + }, + index, + ) => ( + mutateLike(id)} + mutateHate={() => mutateHate(id)} + key={`comment_id_${index}`} + /> + ), + )} +
+
+ + ); +} + +const Container = styled.div` + position: relative; + display: flex; + flex-direction: column; + gap: 16px; + padding: 0 20px; +`; + +export default DrinkCommentContainer; diff --git a/apps/jurumarble/src/app/drink-info/[id]/components/DrinkInfoContainer.tsx b/apps/jurumarble/src/app/drink-info/[id]/components/DrinkInfoContainer.tsx index 3b48ae26..df3fd1a5 100644 --- a/apps/jurumarble/src/app/drink-info/[id]/components/DrinkInfoContainer.tsx +++ b/apps/jurumarble/src/app/drink-info/[id]/components/DrinkInfoContainer.tsx @@ -173,6 +173,7 @@ const DescriptionRow = styled.div` .label { white-space: nowrap; width: 64px; + min-width: 64px; ${({ theme }) => theme.typography.body_long03}; color: ${({ theme }) => theme.colors.black_03}; } diff --git a/apps/jurumarble/src/app/drink-info/[id]/page.tsx b/apps/jurumarble/src/app/drink-info/[id]/page.tsx index 0b6458cf..ee6e4cd8 100644 --- a/apps/jurumarble/src/app/drink-info/[id]/page.tsx +++ b/apps/jurumarble/src/app/drink-info/[id]/page.tsx @@ -2,12 +2,14 @@ import BottomBar from "components/BottomBar"; import React from "react"; +import DrinkCommentContainer from "./components/DrinkCommentContainer"; import DrinkInfoContainer from "./components/DrinkInfoContainer"; function DrinkInfoPage() { return ( <> + ); diff --git a/apps/jurumarble/src/app/map/components/MapContainer.tsx b/apps/jurumarble/src/app/map/components/MapContainer.tsx index aba97bae..6d185204 100644 --- a/apps/jurumarble/src/app/map/components/MapContainer.tsx +++ b/apps/jurumarble/src/app/map/components/MapContainer.tsx @@ -17,6 +17,7 @@ import SvgIcPin from "src/assets/icons/ic_pin.svg"; import Image from "next/image"; const MapContainer = () => { + const [onMap, toggleMap] = useToggle(); const { error, location, toggleOnLocation, onLocation } = useGeoLocation(); const [on, toggle] = useToggle(); const mapRef = useRef(null); @@ -27,7 +28,11 @@ const MapContainer = () => { endY: 132.02500466772065, }); - console.log(location); + useEffect(() => { + setTimeout(() => { + toggleMap(); + }, 600); + }, []); const { drinksList } = useDrinksMapService({ startX: mapXY.startX, @@ -51,12 +56,22 @@ const MapContainer = () => { level: 13, }); - useEffect(() => { - // 윈도우 리사이즈 실행 - setTimeout(() => { - window.dispatchEvent(new Event("resize")); - }, 1000); - }, []); + // useEffect(() => { + // const kakaoMapScript = document.createElement("script"); + // kakaoMapScript.async = false; + // kakaoMapScript.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=700d399006256f95732f06b19c046ba5&autoload=false`; + // document.head.appendChild(kakaoMapScript); + + // const onLoadKakaoAPI = () => { + // window.kakao.maps.load(() => { + // var container = document.getElementById("map"); + + // var map = new window.kakao.maps.Map(container); + // }); + // }; + + // kakaoMapScript.addEventListener("load", onLoadKakaoAPI); + // }, []); const onIdleMap = () => { const map = mapRef.current; @@ -103,8 +118,15 @@ const MapContainer = () => { -
+
{ + window.dispatchEvent(new Event("resize")); + }} + onLoad={() => { + mapRef.current?.getNode(); + }} center={state.center} isPanto={state.isPanto} style={{ @@ -155,8 +177,9 @@ const MapContainer = () => { /> */} - {drinksList.map(({ drinkId, name, latitude, longitude, image, manufacturer }) => ( + {drinksList.map(({ drinkId, name, latitude, longitude, image, manufacturer }, index) => ( { return ( <> -
diff --git a/apps/jurumarble/src/app/page.tsx b/apps/jurumarble/src/app/page.tsx index 0c674708..82f0fcf2 100644 --- a/apps/jurumarble/src/app/page.tsx +++ b/apps/jurumarble/src/app/page.tsx @@ -3,7 +3,9 @@ import BottomBar from "components/BottomBar"; import DivideLine from "components/DivideLine"; import Header from "components/Header"; +import { KAKAO_MAP_API_KEY } from "lib/constants"; import Image from "next/image"; +import Script from "next/script"; import { MainBannerImage } from "public/images"; import styled from "styled-components"; import HotDrinkContainer from "./main/components/HotDrinkContainer"; @@ -13,6 +15,11 @@ import SearchInputWrapper from "./main/components/SearchInputWrapper"; function MainPage() { return ( <> +
diff --git a/apps/jurumarble/src/app/vote/[id]/components/ChipContainer.tsx b/apps/jurumarble/src/app/vote/[id]/components/ChipContainer.tsx index fe54657e..3d50fc79 100644 --- a/apps/jurumarble/src/app/vote/[id]/components/ChipContainer.tsx +++ b/apps/jurumarble/src/app/vote/[id]/components/ChipContainer.tsx @@ -93,7 +93,6 @@ const ChipContainer = ({ onDelete={() => { if (confirm("정말 삭제하시겠습니까?")) { onDelete(); - alert("삭제되었습니다."); } }} onModify={() => { diff --git a/apps/jurumarble/src/app/vote/[id]/components/Comment.tsx b/apps/jurumarble/src/app/vote/[id]/components/Comment.tsx index eedffee3..1c388ac2 100644 --- a/apps/jurumarble/src/app/vote/[id]/components/Comment.tsx +++ b/apps/jurumarble/src/app/vote/[id]/components/Comment.tsx @@ -5,16 +5,21 @@ import { Button } from "components/button"; import { CommentResponse } from "lib/apis/comment"; import Image from "next/image"; import { ExImg1 } from "public/images"; -import React from "react"; +import React, { useEffect, useState } from "react"; import { toast } from "react-toastify"; import useGetUserInfo from "services/useGetUserInfo"; import SvgIcMenu from "src/assets/icons/components/IcMenu"; import styled, { css } from "styled-components"; +import useCommentDeleteService from "../services/useCommentDeleteService"; import useCommentReportService from "../services/useCommentReportService"; import CommentDeleteModal from "./CommentDeleteModal"; +import CommentForm from "./CommentForm"; +import CommentPutForm from "./CommentPutForm"; interface Props { + voteType: "drinks" | "votes"; + postId: number; comment: { id: number; content: string; @@ -28,12 +33,11 @@ interface Props { nickName: string; userId: number; }; - mutateDeleteComment(): void; mutateLike?(): void; mutateHate?(): void; } -function Comment({ comment, mutateDeleteComment, mutateLike, mutateHate }: Props) { +function Comment({ comment, mutateLike, mutateHate, voteType, postId }: Props) { const { userInfo } = useGetUserInfo(); const { mutate } = useCommentReportService(); const { @@ -57,6 +61,22 @@ function Comment({ comment, mutateDeleteComment, mutateLike, mutateHate }: Props toggleNonWriterMenu, onToggleNonWriterMenu, ); + const { onDelete, onPutComment } = useCommentDeleteService(voteType, postId, id); + + const [isModifying, setIsModifying] = useState(false); + const [commentForm, setCommentForm] = useState(""); + const onChangeCommentForm = (e: React.ChangeEvent) => { + setCommentForm(e.target.value); + }; + const onSubmitComment = (content: string) => { + onPutComment(content); + setIsModifying(false); + }; + + useEffect(() => { + setCommentForm(content); + }, [comment]); + return ( {nickName} - {content} - {userId === userInfo?.userId && ( - - - + {isModifying ? ( + <> + + + + + + + + ) : ( + <> + {content} + {userId === userInfo?.userId && ( + + + + )} + +
{createdDate.slice(0, 10)}
・ + ❤️ 좋아요 {likeCount ?? 0}{" "} + ・ + 🖤 싫어요 {hateCount ?? 0}{" "} +
+ )} - -
{createdDate.slice(0, 10)}
・ - ❤️ 좋아요 {likeCount ?? 0} ・ - 🖤 싫어요 {hateCount ?? 0}{" "} -
{userId === userInfo?.userId ? (
@@ -113,7 +159,13 @@ function Comment({ comment, mutateDeleteComment, mutateLike, mutateHate }: Props
)} - {toggleMenu && } + {toggleMenu && ( + setIsModifying((prev) => !prev)} + right="20px" + /> + )} {toggleNonWriterMenu && ( { @@ -224,4 +276,15 @@ const AddRestaurants = styled.div` const BigFont = styled.span` font-size: 17px; `; + +const PutFormWrapper = styled.div` + display: flex; + align-items: center; + justify-content: right; +`; + +const InputWrapper = styled.div` + padding: 12px 0 8px 0; +`; + export default Comment; diff --git a/apps/jurumarble/src/app/vote/[id]/components/CommentContainer.tsx b/apps/jurumarble/src/app/vote/[id]/components/CommentContainer.tsx index ba397750..1e3c8a04 100644 --- a/apps/jurumarble/src/app/vote/[id]/components/CommentContainer.tsx +++ b/apps/jurumarble/src/app/vote/[id]/components/CommentContainer.tsx @@ -83,6 +83,8 @@ function CommentContainer({ postId }: Props) { index, ) => ( void 0} mutateLike={() => mutateLike(id)} mutateHate={() => mutateHate(id)} key={`comment_id_${index}`} diff --git a/apps/jurumarble/src/app/vote/[id]/components/CommentPutForm.tsx b/apps/jurumarble/src/app/vote/[id]/components/CommentPutForm.tsx new file mode 100644 index 00000000..ca17ab2f --- /dev/null +++ b/apps/jurumarble/src/app/vote/[id]/components/CommentPutForm.tsx @@ -0,0 +1,66 @@ +// import { Input } from "@monorepo/ui"; +import Image from "next/image"; +import { ExImg1 } from "public/images"; +import React from "react"; +import styled, { css } from "styled-components"; + +interface Props { + commentForm: string; + onChangeCommentForm(e: React.ChangeEvent): void; + onSubmitComment(content: string): void; +} + +function CommentPutForm({ commentForm, onChangeCommentForm, onSubmitComment }: Props) { + const onSubmit = (e: React.FormEvent) => { + e.preventDefault(); + onSubmitComment(commentForm); + }; + + return ( + +
+ + 수정 +
+
+ ); +} + +const Container = styled.div` + display: flex; + align-items: center; + gap: 6px; +`; + +const Form = styled.form` + display: flex; + flex: 1 1 auto; +`; + +const Input = styled.textarea` + border-right: none; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + width: 100%; + padding: 14px; + resize: none; + ${({ theme }) => css` + border: 1px solid ${theme.colors.black_05}; + color: ${theme.colors.black_02}; + `} +`; + +const SubmitButton = styled.button` + width: 60px; + padding: 16px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + white-space: nowrap; + ${({ theme }) => css` + border: 1px solid ${theme.colors.black_05}; + color: ${theme.colors.main_01}; + background-color: ${theme.colors.white}; + `} +`; + +export default CommentPutForm; diff --git a/apps/jurumarble/src/app/vote/[id]/components/VoteDescription.tsx b/apps/jurumarble/src/app/vote/[id]/components/VoteDescription.tsx index 91fa1305..566f3468 100644 --- a/apps/jurumarble/src/app/vote/[id]/components/VoteDescription.tsx +++ b/apps/jurumarble/src/app/vote/[id]/components/VoteDescription.tsx @@ -1,8 +1,9 @@ import AorBMark from "components/AorBMark"; import { postExecuteVote } from "lib/apis/vote"; +import Path from "lib/Path"; import { media } from "lib/styles"; import Image, { StaticImageData } from "next/image"; -import { useParams } from "next/navigation"; +import { useParams, useRouter } from "next/navigation"; import { ExImg1 } from "public/images"; import React from "react"; import useGetUserInfo from "services/useGetUserInfo"; @@ -37,6 +38,8 @@ interface Props { totalCountB: number; onMutateVoting: (select: AorB) => void; voteType: string; + drinkAId: number; + drinkBId: number; } function VoteDescription({ @@ -51,8 +54,11 @@ function VoteDescription({ totalCountB, onMutateVoting, voteType, + drinkAId, + drinkBId, }: Props) { const { userInfo } = useGetUserInfo(); + const router = useRouter(); const getAB = (direction: Direction) => { return direction === "left" ? "A" : "B"; @@ -88,7 +94,12 @@ function VoteDescription({ {titleA} {percentageA}% {totalCountA}명 - 술정보 보기   {">"} + {voteType === "DRINK" && ( + router.push(`${Path.DRINK_INFO_PAGE}/${drinkAId}`)}> + {" "} + 술정보 보기   {">"} + + )}
A @@ -111,7 +122,11 @@ function VoteDescription({ {titleB} {percentageB}% {totalCountB}명 - 술정보 보기   {">"} + {voteType === "DRINK" && ( + router.push(`${Path.DRINK_INFO_PAGE}/${drinkBId}`)}> + 술정보 보기   {">"} + + )}
B diff --git a/apps/jurumarble/src/app/vote/[id]/page.tsx b/apps/jurumarble/src/app/vote/[id]/page.tsx index b1b324aa..07cc3da2 100644 --- a/apps/jurumarble/src/app/vote/[id]/page.tsx +++ b/apps/jurumarble/src/app/vote/[id]/page.tsx @@ -109,6 +109,8 @@ function Detail() { select={select.choice} onMutateVoting={onMutateVoting} voteType={data.voteType} + drinkAId={data.drinkAId} + drinkBId={data.drinkBId} /> {!!select.choice && ( deleteComment(commentType, typeId, commentId), { + onSuccess: () => { + alert("댓글이 삭제되었습니다."); + queryClient.invalidateQueries([queryKeys.DETAIL_COMMENT_LIST]); + }, + }); + + const { mutate: onPutComment } = useMutation( + (comment: string) => putComment(commentType, typeId, commentId, comment), + { + onSuccess: () => { + alert("댓글이 수정되었습니다."); + queryClient.invalidateQueries([queryKeys.DETAIL_COMMENT_LIST]); + }, + }, + ); + + return { + onDelete: mutate, + onPutComment, + }; +} diff --git a/apps/jurumarble/src/app/vote/page.tsx b/apps/jurumarble/src/app/vote/page.tsx index c4d0ddb1..e8ea5193 100644 --- a/apps/jurumarble/src/app/vote/page.tsx +++ b/apps/jurumarble/src/app/vote/page.tsx @@ -67,8 +67,8 @@ function VoteHomePage() {
- 당신의 투표를 -
기다리고 있어요 + 여행에서 즐길 우리술은 +
우리술 투표로 해결해요