diff --git a/src/components/CommentInfo.module.scss b/src/components/CommentInfo.module.scss new file mode 100644 index 0000000..7cd7396 --- /dev/null +++ b/src/components/CommentInfo.module.scss @@ -0,0 +1,202 @@ +.commentInfo { + margin: 0; + + .commentHeader { + margin-bottom: 18px; + display: flex; + + .commentUser { + flex: 1; + .userLink { + display: flex; + + .userImage { + display: flex; + align-items: center; + border: solid 1px rgba(0, 0, 0, 0.08); + border-radius: 50%; + flex-shrink: 0; + width: 20px; + height: 20px; + margin: 3px 5px 3px 0; + overflow: hidden; + + img { + width: 100%; + height: 100%; + } + } + + .userDate { + display: flex; + align-items: center; + + .userName { + font-size: 12px; + font-weight: 400; + letter-spacing: -0.2px; + color: #4a4a4a; + line-height: 16px; + } + + .date { + margin-left: 4px; + font-size: 12px; + font-weight: 400; + letter-spacing: -0.2px; + color: #787878; + line-height: 16px; + } + } + } + + .movieName { + color: rgb(0, 0, 0); + font-size: 16px; + letter-spacing: -0.6px; + line-height: 21px; + margin-top: 3px; + } + + .releaseYear { + color: rgb(120, 120, 120); + font-size: 12px; + letter-spacing: -0.2px; + line-height: 16px; + margin-top: 3px; + } + .ratingDiv { + margin-top: 5px; + width: 53px; + + .rating { + display: flex; + justify-content: center; + align-items: center; + color: rgb(74, 74, 74); + font-weight: 400; + letter-spacing: -0.3px; + font-size: 13px; + line-height: 16px; + height: 24px; + padding-right: 8px; + padding-left: 8px; + border: 1px solid rgb(234, 234, 234); + border-radius: 13px; + + .ratingText { + margin-left: 4px; + } + } + } + } + + .poster { + overflow: hidden; + width: 72px; + height: 106px; + border: 0.5px solid rgba(0, 0, 0, 0.16); + border-radius: 3px; + + img { + width: 100%; + height: 100%; + } + } + } + + .commentBody { + color: rgb(74, 74, 74); + margin-bottom: 22px; + font-size: 15px; + font-weight: 400; + letter-spacing: -0.2px; + line-height: 24px; + word-wrap: break-word; + white-space: pre-line; + overflow: hidden; + } + + .commentLikeReply { + height: 40px; + color: rgb(120, 120, 120); + font-size: 12px; + letter-spacing: -0.2px; + line-height: 40px; + margin-top: 32px; + + .likes { + margin-right: 18px; + } + } + + .likeReplyBar { + margin: 0; + + hr { + border: 0; + border-bottom: 1px solid #f0f0f0; + } + + .likeReplyGrid { + margin: 0 20px; + display: grid; + position: relative; + grid-template-columns: 1fr 1fr; + grid-gap: 1px; + height: 43px; + + button { + background: none; + padding: 0; + border: none; + position: relative; + display: flex; + justify-content: center; + align-items: center; + color: #67686a; + font-size: 15px; + letter-spacing: -0.3px; + line-height: 18px; + border-radius: 5px; + margin: 3px; + cursor: pointer; + transition: all 70ms linear 0s; + } + + button:hover { + background-color: rgba(41, 42, 50, 0.08); + color: rgba(41, 42, 50, 1); + svg :not([fill="none"]) { + fill: rgba(41, 42, 50, 1); + } + } + + .likeButton::after { + content: ""; + position: absolute; + right: -4px; + background: #f0f0f0; + width: 1px; + height: 14px; + } + + .likeButtonLiked { + color: rgb(255, 47, 110); + .likeSvg { + color: rgb(255, 47, 110); + } + } + + .fillTarget { + transition: all 70ms linear 0s; + } + + svg { + width: 20px; + height: 20px; + margin-right: 5px; + } + } + } +} diff --git a/src/components/CommentInfo.tsx b/src/components/CommentInfo.tsx new file mode 100644 index 0000000..511c564 --- /dev/null +++ b/src/components/CommentInfo.tsx @@ -0,0 +1,176 @@ +import { Link } from "react-router-dom"; +import userImage from "../assets/user_default.jpg"; +import styles from "./CommentInfo.module.scss"; +import { MovieType } from "./ContentList"; +import ReplyList from "./ReplyList"; +import elapsedTime from "../utils/elapsedTime"; + +export type ReplyType = { + userName: string; + date: Date; + content: string; + likes: number; + liked: boolean; +}; + +type CommentType = { + userName: string; + movie: MovieType; + rating: number; + content: string; + date: Date; + likes: number; + liked: boolean; + replyNumber: number; + replies: ReplyType[]; +}; + +function CommentHeader({ + userName, + movie, + rating, + date, +}: { + userName: string; + movie: MovieType; + rating: number; + date: Date; +}) { + return ( +
+
+ +
+ {userName +
+
+
{userName}
+
{elapsedTime(date)}
+
+ + +
{movie.name}
+
영화 · {movie.releaseYear}
+ +
+
+ star + {rating.toFixed(1)} +
+
+
+ +
+ {movie.name +
+ +
+ ); +} + +function CommentBody({ content }: { content: string }) { + return
{content}
; +} + +function CommentLikeReply({ + likes, + replies, +}: { + likes: number; + replies: number; +}) { + return ( +
+ 좋아요 {likes} + 댓글 {replies} +
+ ); +} + +function LikeReplyBar({ liked }: { liked: boolean }) { + console.log(liked); + return ( +
+
+
+ + +
+
+
+ ); +} + +export default function CommentInfo({ comment }: { comment: CommentType }) { + return ( +
+ + + + + +
+ ); +} diff --git a/src/components/Content.module.scss b/src/components/Content.module.scss index a5fa865..dd4505c 100644 --- a/src/components/Content.module.scss +++ b/src/components/Content.module.scss @@ -57,7 +57,9 @@ width: 280px; height: 400px; margin-bottom: 30px; - transition: width 0.3s, height 0.3s; + transition: + width 0.3s, + height 0.3s; @media (max-width: #{$medium-screen + 100}) { width: 200px; diff --git a/src/components/Content.tsx b/src/components/Content.tsx index bf31038..5467de6 100644 --- a/src/components/Content.tsx +++ b/src/components/Content.tsx @@ -1,4 +1,5 @@ import { useState } from "react"; +import { Link } from "react-router-dom"; import styles from "./Content.module.scss"; import { Carousel } from "./Carousel"; import profileDefault from "../assets/user_default.jpg"; diff --git a/src/components/Footer.module.scss b/src/components/Footer.module.scss index 23e34fc..0f88456 100644 --- a/src/components/Footer.module.scss +++ b/src/components/Footer.module.scss @@ -33,6 +33,7 @@ footer { .companyInfoDiv { margin: 0 20px; display: flex; + max-width: 1320px; @media (min-width: 760px) { margin: 0 3.5%; diff --git a/src/components/ReplyList.module.scss b/src/components/ReplyList.module.scss new file mode 100644 index 0000000..3897f47 --- /dev/null +++ b/src/components/ReplyList.module.scss @@ -0,0 +1,146 @@ +.replyList { + margin-top: 35px; + margin-left: 0px; + margin-right: 0px; + + .replyListHeader { + display: flex; + justify-content: space-between; + align-items: center; + margin: 3px 0px 9px; + + button { + background: none; + color: rgb(255, 47, 110); + font-size: 14px; + font-weight: 500; + letter-spacing: -0.5px; + line-height: 18px; + padding: 0px; + border: none; + } + + button:hover { + text-decoration: underline; + cursor: pointer; + } + + div { + color: rgb(140, 140, 140); + font-size: 13px; + font-weight: 400; + letter-spacing: -0.2px; + line-height: 16px; + } + } + + .replies { + display: flex; + flex-direction: column-reverse; + + .reply { + width: 100%; + padding: 12px 0px; + border-top: 1px solid rgba(0, 0, 0, 0.06); + display: flex; + + .userImage { + width: 32px; + height: 32px; + border-radius: 50%; + overflow: hidden; + box-shadow: rgba(0, 0, 0, 0.08) 0px 0px 0px 1px inset; + + img { + width: 100%; + height: 100%; + } + } + + .replyBody { + width: calc(100% - 40px); + margin-left: auto; + + .replyHeader { + display: flex; + align-items: center; + + .userName { + color: rgba(0, 0, 0, 0.8); + font-size: 14px; + font-weight: 700; + letter-spacing: -0.3px; + line-height: 18px; + } + + .timeAgo { + color: rgb(140, 140, 140); + font-size: 13px; + font-weight: 400; + letter-spacing: -0.2px; + line-height: 16px; + margin-left: auto; + } + } + + .replyContent { + color: rgb(74, 74, 74); + font-size: 15px; + font-weight: 400; + letter-spacing: -0.55px; + line-height: 22px; + white-space: pre-wrap; + width: calc(100% - 40px); + margin-top: 4px; + margin-bottom: 8px; + } + + .liked { + display: flex; + align-items: center; + color: rgb(255, 47, 110); + font-size: 14px; + font-weight: 400; + letter-spacing: -0.3px; + line-height: 18px; + height: 24px; + padding: 0px 9px; + border-radius: 5px; + margin-left: -8px; + width: fit-content; + } + + .liked:hover { + background: rgba(255, 47, 110, 0.08); + cursor: pointer; + } + + .unliked { + display: flex; + align-items: center; + color: rgb(135, 137, 139); + font-size: 14px; + font-weight: 400; + letter-spacing: -0.3px; + line-height: 18px; + height: 24px; + padding: 0px 9px; + border-radius: 5px; + margin-left: -8px; + width: fit-content; + } + + .unliked:hover { + background: rgba(41, 42, 50, 0.08); + cursor: pointer; + } + + svg { + width: 14px; + height: 14px; + margin-right: 6px; + } + } + } + } +} diff --git a/src/components/ReplyList.tsx b/src/components/ReplyList.tsx new file mode 100644 index 0000000..8df137f --- /dev/null +++ b/src/components/ReplyList.tsx @@ -0,0 +1,88 @@ +import { ReplyType } from "./CommentInfo"; +import styles from "./ReplyList.module.scss"; +import userImage from "../assets/user_default.jpg"; +import { Link } from "react-router-dom"; +import elapsedTime from "../utils/elapsedTime"; + +function Reply({ reply }: { reply: ReplyType }) { + return ( +
+ +
+ {reply.userName +
+ +
+
+ +
{reply.userName}
+ +
{elapsedTime(reply.date)}
+
+
{reply.content}
+
+ {reply.liked ? ( + + + + + ) : ( + + + + + )} + {reply.likes} +
+
+
+ ); +} + +export default function ReplyList({ + replyNumber, + replies, +}: { + replyNumber: number; + replies: ReplyType[]; +}) { + return ( +
+
+ +
+ {replyNumber}개 중 {replies.length}개 +
+
+
+ {replies.map((reply: ReplyType, index: number) => ( + + ))} +
+
+ ); +} diff --git a/src/index.css b/src/index.css index 98e14fa..8fb0040 100644 --- a/src/index.css +++ b/src/index.css @@ -23,5 +23,6 @@ input { } a { + color: black; text-decoration: none; } diff --git a/src/pages/CommentPage.module.scss b/src/pages/CommentPage.module.scss new file mode 100644 index 0000000..73d72eb --- /dev/null +++ b/src/pages/CommentPage.module.scss @@ -0,0 +1,23 @@ +.commentPage { + max-width: 1320px; + margin-top: 80px; + margin-left: 15px; + margin-right: 15px; + margin-bottom: 55px; + + @media (min-width: 760px) { + margin-left: 3.5%; + margin-right: 3.5%; + } + + @media (min-width: 760px) { + margin-left: 60px; + margin-right: 60px; + } + + @media (min-width: 1440px) { + margin-left: auto; + margin-right: auto; + width: 1320px; + } +} diff --git a/src/pages/CommentPage.tsx b/src/pages/CommentPage.tsx index 6e7a80f..89851d8 100644 --- a/src/pages/CommentPage.tsx +++ b/src/pages/CommentPage.tsx @@ -1,7 +1,39 @@ +import styles from "./CommentPage.module.scss"; +import CommentInfo from "../components/CommentInfo"; + export default function CommentPage() { + const comment = { + userName: "이동진", + movie: { + name: "오펜하이머", + releaseYear: "2023", + country: "영국", + posterUrl: + "https://an2-img.amz.wtchn.net/image/v2/TnfLooyFVulaY3fZhLMNIw.jpg?jwt=ZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKdmNIUnpJanBiSW1SZk5Ea3dlRGN3TUhFNE1DSmRMQ0p3SWpvaUwzWXlMM04wYjNKbEwybHRZV2RsTHpFMk9UQTFNRFk1TWpBNU9ERTVNamt5TkRNaWZRLmdfM0lvai1JZGVCbjVFRXhYQ3VFODMwdEN4MnNEa2JKbXV4VEk3QlJPYVE", + rating: 4.0, + }, + rating: 4.5, + date: new Date("2024-01-15 12:00"), + content: `줄리어스 로버트 오펜하이머.. + 줄리어스 로버트 오펜하이머.. + 자기 이야기가 영화로 만들어진다니. + 로버트는 얼마나 좋았을까. + `, + likes: 200, + liked: false, + replyNumber: 1000, + replies: new Array(9).fill({ + userName: "J. Robert Oppenheimer", + date: new Date("2024-01-15 10:00"), + content: "I felt good.", + likes: 100, + liked: false, + }), + }; + return ( -
-

단일 코멘트 페이지

-
+
+ +
); } diff --git a/src/pages/Layout.module.scss b/src/pages/Layout.module.scss new file mode 100644 index 0000000..bbdd684 --- /dev/null +++ b/src/pages/Layout.module.scss @@ -0,0 +1,11 @@ +.mainSection { + margin: 0; + padding-top: 0px; + padding-bottom: unset; + .mainDiv { + display: flex; + flex-direction: column; + min-height: 100vh; + justify-content: space-between; + } +} diff --git a/src/pages/Layout.tsx b/src/pages/Layout.tsx index 0defef9..96db726 100644 --- a/src/pages/Layout.tsx +++ b/src/pages/Layout.tsx @@ -1,4 +1,5 @@ import { Outlet } from "react-router-dom"; +import styles from "./Layout.module.scss"; import Header from "../components/Header"; import Footer from "../components/Footer"; import SignupModal from "../components/SignupModal"; @@ -19,8 +20,12 @@ export default function Layout() { )}
- -