From 2f3076e3ac643e41f0e33deb366fd2ea6d10b0ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=ED=86=A0?= <59536977+seongjin2427@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:38:14 +0900 Subject: [PATCH] =?UTF-8?q?[feat]=20=ED=86=A0=EB=A1=A0=20=ED=94=BC?= =?UTF-8?q?=EB=93=9C=20=EC=83=81=EC=84=B8=20=EB=AA=A8=EB=8B=AC=20=EC=9D=BD?= =?UTF-8?q?=EA=B8=B0=20=EC=A0=84=EC=9A=A9=20UI=20=EA=B5=AC=ED=98=84=20(#27?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] added FeedWrapper Component - FeedWrapper depends on whether there is pathname value "p" or not - If pathname "p" value of browser navigation is existed, FeedWrapper render children props * [fix] fixed commit error - The folder name included "@" caused error when committing - The folder name to start "@" means slot router * [feat] added compactTimeFormatter util for feed created time * [feat] added FeedWrapper, ReadOnlyCommonFeed, FeedTextContent Component - FeedWrapper depends on whether or not browser navigation has value of key "f" - ReadOnlyCommonFeed is only rendering from props information about common feed - FeedTextContent is rendering feed information (profile, content, username etc.) * [style] added "flex-wrap: wrap;" style at .hashtag_wrapper in FeedTextContent Component * [feat] added FeedComment, FeedCommentList - not included server request logic * [feat] added FeedLikeBox Component and svg heart icon * [feat] added LikeButton Component * [feat] added FeedCommentWriteInput Component and useAutoResizeTextArea hook * [feat] added Slide Component - added height, maxHeight props at Modal Component * [feat] added FeedReplyWriteInput Component - update useAutoResizeTextArea hook (not use row count, use scrollHeight) * [feat] added ReadOnlyDebateFeed Component * [feat] added DebateContent Component * [feat] completed ReadOnlyDebateFeed Component and Refactoring --- .../DebateContent/DebateContent.module.scss | 56 +++++++++++ .../DebateContent/DebateContent.tsx | 84 ++++++++++++++++ .../components/DebateContent/index.ts | 1 + .../components/FeedComment/FeedComment.tsx | 4 +- .../FeedCommentList/FeedCommentList.tsx | 1 + .../FeedCommentWriteInput.module.scss | 13 ++- .../FeedCommentWriteInput.tsx | 9 +- .../components/FeedLikeBox/FeedLikeBox.tsx | 10 +- .../FeedTextContent.module.scss | 17 +++- .../FeedTextContent/FeedTextContent.tsx | 18 ++-- .../components/LikeButton/LikeButton.tsx | 31 +++--- .../ReadOnlyCommonFeed.module.scss | 8 +- .../ReadOnlyCommonFeed/ReadOnlyCommonFeed.tsx | 87 ++++++++++------- .../ReadOnlyDebateFeed.module.scss | 33 +++++++ .../ReadOnlyDebateFeed/ReadOnlyDebateFeed.tsx | 90 ++++++++++++++++++ .../components/ReadOnlyDebateFeed/index.ts | 1 + src/app/(MainLayout)/page.tsx | 66 ++++++++++++- src/app/(MainLayout)/types/feed.ts | 51 +++++++++- src/assets/icons/blue_flag_fill.svg | 3 + src/assets/icons/red_flag.png | Bin 0 -> 340 bytes src/assets/icons/red_flag_fill.svg | 3 + .../FeedWrapper/FeedWrapper.module.scss | 30 ++++++ .../common/FeedWrapper/FeedWrapper.tsx | 7 +- 23 files changed, 545 insertions(+), 78 deletions(-) create mode 100644 src/app/(MainLayout)/components/DebateContent/DebateContent.module.scss create mode 100644 src/app/(MainLayout)/components/DebateContent/DebateContent.tsx create mode 100644 src/app/(MainLayout)/components/DebateContent/index.ts create mode 100644 src/app/(MainLayout)/components/ReadOnlyDebateFeed/ReadOnlyDebateFeed.module.scss create mode 100644 src/app/(MainLayout)/components/ReadOnlyDebateFeed/ReadOnlyDebateFeed.tsx create mode 100644 src/app/(MainLayout)/components/ReadOnlyDebateFeed/index.ts create mode 100644 src/assets/icons/blue_flag_fill.svg create mode 100644 src/assets/icons/red_flag.png create mode 100644 src/assets/icons/red_flag_fill.svg diff --git a/src/app/(MainLayout)/components/DebateContent/DebateContent.module.scss b/src/app/(MainLayout)/components/DebateContent/DebateContent.module.scss new file mode 100644 index 0000000..5038f4d --- /dev/null +++ b/src/app/(MainLayout)/components/DebateContent/DebateContent.module.scss @@ -0,0 +1,56 @@ +@use '../../../../styles/helpers/index' as *; + +.blue { + background-color: rgba(43, 89, 195, 0.3); +} + +.red { + background-color: rgba(211, 101, 130, 0.3); +} + +.container { + flex: 1; + border-right: 1px solid $COLOR_GRAY_2; + + &:last-of-type { + border-right: none; + } + + .debate_container { + position: relative; + height: 200px; + border-bottom: 1px solid $COLOR_GRAY_2; + + @include flex-center; + + h2 { + font-size: $FONT_SIZE_32; + font-weight: bold; + color: $COLOR_GRAY_2; + } + + .vote_count { + position: absolute; + top: 20px; + left: 20px; + gap: 5px; + + @include flex-center; + } + + .vote { + position: absolute; + width: 100%; + height: 200px; + top: 0; + left: 0; + opacity: 0.5; + border-right: 1px solid $COLOR_GRAY_2; + } + } + + .comment_container { + height: 539px; + overflow: scroll; + } +} diff --git a/src/app/(MainLayout)/components/DebateContent/DebateContent.tsx b/src/app/(MainLayout)/components/DebateContent/DebateContent.tsx new file mode 100644 index 0000000..7a25a11 --- /dev/null +++ b/src/app/(MainLayout)/components/DebateContent/DebateContent.tsx @@ -0,0 +1,84 @@ +import clsx from 'clsx'; + +import { digitNumberFormatter } from '@/utils/formatter'; + +import BlueFlag from '@/assets/icons/blue_flag.svg'; +import BlueFillFlag from '@/assets/icons/blue_flag_fill.svg'; +import RedFlag from '@/assets/icons/red_flag.svg'; +import RedFillFlag from '@/assets/icons/red_flag_fill.svg'; +import FeedCommentList from '../FeedCommentList'; + +import styles from './DebateContent.module.scss'; +import FeedCommentWriteInput from '../FeedCommentWriteInput'; +import { DebateOptionType } from '../../types/feed'; + +interface DebateContentProps { + postId: number; + index: number; + option: DebateOptionType; + isSelected?: boolean; + ratio: number; + disabled?: boolean; +} + +const FLAG_SET = { + BLUE: { + NORMAL: BlueFlag, + FILL: BlueFillFlag, + }, + RED: { + NORMAL: RedFlag, + FILL: RedFillFlag, + }, +}; + +const DebateContent = ({ + postId, + index, + option, + ratio, + isSelected, + disabled, +}: DebateContentProps) => { + const { optionContent, voteCount } = option; + + const currentFlagType = index === 1 ? 'BLUE' : ('RED' as const); + const FLAG = FLAG_SET[currentFlagType]; + + const currentColor = currentFlagType === 'BLUE' ? styles.blue : styles.red; + + return ( +
+
+

{optionContent}

+
+ {isSelected ? : } + {digitNumberFormatter(voteCount)} +
+
+
+
+ +
+
+ +
+
+ ); +}; + +export default DebateContent; diff --git a/src/app/(MainLayout)/components/DebateContent/index.ts b/src/app/(MainLayout)/components/DebateContent/index.ts new file mode 100644 index 0000000..c315731 --- /dev/null +++ b/src/app/(MainLayout)/components/DebateContent/index.ts @@ -0,0 +1 @@ +export { default } from './DebateContent'; diff --git a/src/app/(MainLayout)/components/FeedComment/FeedComment.tsx b/src/app/(MainLayout)/components/FeedComment/FeedComment.tsx index 333bf65..38ab7d2 100644 --- a/src/app/(MainLayout)/components/FeedComment/FeedComment.tsx +++ b/src/app/(MainLayout)/components/FeedComment/FeedComment.tsx @@ -15,6 +15,7 @@ export type FeedCommentType = { createdAt: string; updatedAt: string; likeCount: number; + isLike: boolean; childFeedComments: string[]; }; @@ -31,6 +32,7 @@ const FeedComment = ({ commentData }: FeedCommentProps) => { createdAt, updatedAt, likeCount, + isLike, childFeedComments, } = commentData; @@ -45,7 +47,7 @@ const FeedComment = ({ commentData }: FeedCommentProps) => {

{nickname}

- +

{feedContent}

diff --git a/src/app/(MainLayout)/components/FeedCommentList/FeedCommentList.tsx b/src/app/(MainLayout)/components/FeedCommentList/FeedCommentList.tsx index ea3226e..d3bf7d1 100644 --- a/src/app/(MainLayout)/components/FeedCommentList/FeedCommentList.tsx +++ b/src/app/(MainLayout)/components/FeedCommentList/FeedCommentList.tsx @@ -20,6 +20,7 @@ const makeMockData = (id: number) => ({ createdAt: '2024-10-25 20:08:22', updatedAt: '2024-10-28 21:29:22', likeCount: 1357345 + id, + isLike: false, childFeedComments: +id < 4 ? [4, 5, 6] : [], }); diff --git a/src/app/(MainLayout)/components/FeedCommentWriteInput/FeedCommentWriteInput.module.scss b/src/app/(MainLayout)/components/FeedCommentWriteInput/FeedCommentWriteInput.module.scss index 6ffe10a..84a54c6 100644 --- a/src/app/(MainLayout)/components/FeedCommentWriteInput/FeedCommentWriteInput.module.scss +++ b/src/app/(MainLayout)/components/FeedCommentWriteInput/FeedCommentWriteInput.module.scss @@ -8,10 +8,21 @@ padding: 18px 0 18px 18px; border-top: 1px solid $COLOR_GRAY_2; + &:has(.comment_textarea:disabled) { + & * { + color: $COLOR_GRAY_2; + } + + .submit_button { + cursor: default; + } + } + .comment_textarea { flex: 1; - color: $COLOR_GRAY_2; + height: 20px; line-height: 1.25rem; + color: $COLOR_GRAY_2; white-space: pre-wrap; word-wrap: break-word; } diff --git a/src/app/(MainLayout)/components/FeedCommentWriteInput/FeedCommentWriteInput.tsx b/src/app/(MainLayout)/components/FeedCommentWriteInput/FeedCommentWriteInput.tsx index cfb7e02..ca60096 100644 --- a/src/app/(MainLayout)/components/FeedCommentWriteInput/FeedCommentWriteInput.tsx +++ b/src/app/(MainLayout)/components/FeedCommentWriteInput/FeedCommentWriteInput.tsx @@ -12,12 +12,14 @@ interface FeedCommentWriteInputProps { postId: number; parentId?: number; placeholder?: string; + disabled?: boolean; } const FeedCommentWriteInput = ({ postId, parentId, placeholder = '댓글 달기...', + disabled, }: FeedCommentWriteInputProps) => { const { textareaContent, setTextareaContent, textareaRef } = useAutoResizeTextArea({ maxLine: 3, lineHeight: 20 }); @@ -44,8 +46,13 @@ const FeedCommentWriteInput = ({ onChange={changeHandler} value={textareaContent} ref={textareaRef} + disabled={disabled} + /> + diff --git a/src/app/(MainLayout)/components/FeedLikeBox/FeedLikeBox.tsx b/src/app/(MainLayout)/components/FeedLikeBox/FeedLikeBox.tsx index 08e243b..6fc8874 100644 --- a/src/app/(MainLayout)/components/FeedLikeBox/FeedLikeBox.tsx +++ b/src/app/(MainLayout)/components/FeedLikeBox/FeedLikeBox.tsx @@ -9,14 +9,20 @@ interface FeedLikeBoxProps { postId: number; likeCount: number; commentCount: number; + isLike: boolean; } -const FeedLikeBox = ({ postId, likeCount, commentCount }: FeedLikeBoxProps) => { +const FeedLikeBox = ({ + postId, + likeCount, + commentCount, + isLike, +}: FeedLikeBoxProps) => { return (
- + {digitNumberFormatter(likeCount)}
diff --git a/src/app/(MainLayout)/components/FeedTextContent/FeedTextContent.module.scss b/src/app/(MainLayout)/components/FeedTextContent/FeedTextContent.module.scss index 31cb70d..95877bd 100644 --- a/src/app/(MainLayout)/components/FeedTextContent/FeedTextContent.module.scss +++ b/src/app/(MainLayout)/components/FeedTextContent/FeedTextContent.module.scss @@ -3,8 +3,7 @@ .container { max-height: 300px; padding: 20px; - border-bottom: 1px solid $COLOR_GRAY_2; - + .profile_wrapper { display: flex; justify-content: space-between; @@ -36,12 +35,24 @@ } .feed_content { - padding-bottom: 30px; + max-height: 140px; + margin-bottom: 20px; font-size: $FONT_SIZE_14; color: $COLOR_GRAY_2; line-height: 1.25rem; white-space: pre-line; word-wrap: break-word; + overflow: auto; + + &::-webkit-scrollbar { + scrollbar-width: thin; + background: $COLOR_WHITE; + } + + &::-webkit-scrollbar-thumb { + background: $COLOR_PRIMARY_5; + border-radius: 5px; + } } .hashtag_wrapper { diff --git a/src/app/(MainLayout)/components/FeedTextContent/FeedTextContent.tsx b/src/app/(MainLayout)/components/FeedTextContent/FeedTextContent.tsx index fac1996..9a383d6 100644 --- a/src/app/(MainLayout)/components/FeedTextContent/FeedTextContent.tsx +++ b/src/app/(MainLayout)/components/FeedTextContent/FeedTextContent.tsx @@ -7,13 +7,12 @@ import styles from './FeedTextContent.module.scss'; interface FeedTextContentProps { feedData: { - username: string; + userName: string; profileUrl?: string; createdAt: string; - updatedAt?: string; isFollow: boolean; content: string; - hashtags: string[]; + hashTagNames: string[]; }; } @@ -22,13 +21,12 @@ const DEFAULT_PROFILE = const FeedTextContent = ({ feedData }: FeedTextContentProps) => { const { - username, + userName, profileUrl = DEFAULT_PROFILE, isFollow, createdAt, - updatedAt, content, - hashtags, + hashTagNames, } = feedData; return (
@@ -37,10 +35,8 @@ const FeedTextContent = ({ feedData }: FeedTextContentProps) => {
user_profile
-

{username}

-

- {compactTimeFormatter(updatedAt ?? createdAt)} -

+

{userName}

+

{compactTimeFormatter(createdAt)}

@@ -48,7 +44,7 @@ const FeedTextContent = ({ feedData }: FeedTextContentProps) => {

{content}

- {hashtags.map((hashtag) => ( + {hashTagNames.map((hashtag) => (

#{hashtag}

))}
diff --git a/src/app/(MainLayout)/components/LikeButton/LikeButton.tsx b/src/app/(MainLayout)/components/LikeButton/LikeButton.tsx index d40fc1e..9fe03e9 100644 --- a/src/app/(MainLayout)/components/LikeButton/LikeButton.tsx +++ b/src/app/(MainLayout)/components/LikeButton/LikeButton.tsx @@ -1,32 +1,29 @@ -import ToggleWrapper from '@/components/common/ToggleWrapper'; +'use client'; + +import { useState } from 'react'; import HeartFillIcon from '@/assets/icons/heart-fill.svg'; import HeartIcon from '@/assets/icons/heart.svg'; import styles from './LikeButton.module.scss'; interface LikeButtonProps { - postId: number; + postId?: number; + commentId?: number; + isLike: boolean; } -const LikeButton = ({ postId }: LikeButtonProps) => { +const LikeButton = ({ postId, commentId, isLike }: LikeButtonProps) => { + const [isToggle, setIsToggle] = useState(isLike); + const clickHandler = () => { - console.log(postId); + console.log(postId, commentId); + setIsToggle(!isToggle); }; return ( - - {({ isToggle, toggleHandler }) => ( - - )} - + ); }; diff --git a/src/app/(MainLayout)/components/ReadOnlyCommonFeed/ReadOnlyCommonFeed.module.scss b/src/app/(MainLayout)/components/ReadOnlyCommonFeed/ReadOnlyCommonFeed.module.scss index 6d4bccd..f49d31a 100644 --- a/src/app/(MainLayout)/components/ReadOnlyCommonFeed/ReadOnlyCommonFeed.module.scss +++ b/src/app/(MainLayout)/components/ReadOnlyCommonFeed/ReadOnlyCommonFeed.module.scss @@ -7,6 +7,12 @@ max-height: 800px; overflow: hidden; + .divider { + width: 100%; + height: 1px; + border-top: 1px solid $COLOR_GRAY_2; + } + .left { width: 60%; max-width: 670px; @@ -21,7 +27,7 @@ } .right_up { - max-height: 230px; + flex: 1; } .right_down { diff --git a/src/app/(MainLayout)/components/ReadOnlyCommonFeed/ReadOnlyCommonFeed.tsx b/src/app/(MainLayout)/components/ReadOnlyCommonFeed/ReadOnlyCommonFeed.tsx index e545fd6..6c577d3 100644 --- a/src/app/(MainLayout)/components/ReadOnlyCommonFeed/ReadOnlyCommonFeed.tsx +++ b/src/app/(MainLayout)/components/ReadOnlyCommonFeed/ReadOnlyCommonFeed.tsx @@ -1,56 +1,75 @@ 'use client'; +import Image from 'next/image'; import { useSearchParams } from 'next/navigation'; +import FeedWrapper from '@/components/common/FeedWrapper'; +import { ReadOnlyCommonFeedType } from '../../types/feed'; +import Slide from '../Slide'; +import FeedLikeBox from '../FeedLikeBox'; import FeedTextContent from '../FeedTextContent'; import FeedCommentList from '../FeedCommentList'; +import FeedCommentWriteInput from '../FeedCommentWriteInput'; import styles from './ReadOnlyCommonFeed.module.scss'; -import FeedLikeBox from '../FeedLikeBox'; -import FeedCommentWriteInput from '../FeedCommentWriteInput'; -import Slide from '../Slide'; -const MOCK_FEED_DATA = { - username: 'seongjin', - profileUrl: - 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT4vkwPhD-NHO6sV_3ailgWXjiP_WPM24J3IhkB3xZ-bQ&s', - isFollow: true, - createdAt: '2024-10-25 20:08:22', - updatedAt: '2024-10-28 21:29:22', - content: - '테스트 입니다. 테스트 입니다. 테스트 입니다. 테스트 입니다. 테스트 입니다. \n테스트 입니다. ', - hashtags: ['javascript', 'typescript', 'react'], -}; +interface ReadOnlyCommonFeedProps { + commonFeedData: ReadOnlyCommonFeedType; +} -const ReadOnlyCommonFeed = () => { - const feedId = new URLSearchParams(useSearchParams()).get('f'); +const ReadOnlyCommonFeed = ({ commonFeedData }: ReadOnlyCommonFeedProps) => { + const feedId = new URLSearchParams(useSearchParams()).get('cf'); if (!feedId) { return null; } + const { post, basicUser } = commonFeedData; + return ( -
-
- -
111111111111111111111111111111111111111111111111111111
-
222222222222222222222222222222222222222222222222222222
-
333333333333333333333333333333333333333333333333333333
-
-
-
-
- -
-
- + +
+
+ + {post.contentImageUrls.map((url, index) => ( + {`content_image_${index}`} + ))} +
-
- - +
+
+ +
+
+
+ +
+
+ + +
-
+ ); }; diff --git a/src/app/(MainLayout)/components/ReadOnlyDebateFeed/ReadOnlyDebateFeed.module.scss b/src/app/(MainLayout)/components/ReadOnlyDebateFeed/ReadOnlyDebateFeed.module.scss new file mode 100644 index 0000000..31df86a --- /dev/null +++ b/src/app/(MainLayout)/components/ReadOnlyDebateFeed/ReadOnlyDebateFeed.module.scss @@ -0,0 +1,33 @@ +@use '../../../../styles/helpers/index' as *; + +.container { + display: flex; + width: 100%; + height: 100%; + max-height: 800px; + overflow: hidden; + + .left { + display: flex; + width: 100%; + max-width: 900px; + height: 100%; + border-right: 1px solid $COLOR_GRAY_2; + } + + .right { + width: 100%; + max-width: 400px; + display: flex; + flex-direction: column; + } + + .right_up { + flex: 1; + } + + .right_down { + height: 100%; + overflow: auto; + } +} diff --git a/src/app/(MainLayout)/components/ReadOnlyDebateFeed/ReadOnlyDebateFeed.tsx b/src/app/(MainLayout)/components/ReadOnlyDebateFeed/ReadOnlyDebateFeed.tsx new file mode 100644 index 0000000..de99432 --- /dev/null +++ b/src/app/(MainLayout)/components/ReadOnlyDebateFeed/ReadOnlyDebateFeed.tsx @@ -0,0 +1,90 @@ +'use client'; + +import { useSearchParams } from 'next/navigation'; + +import FeedWrapper from '@/components/common/FeedWrapper'; +import { ReadOnlyDebateFeedType } from '../../types/feed'; +import FeedLikeBox from '../FeedLikeBox'; +import FeedTextContent from '../FeedTextContent'; +import DebateContent from '../DebateContent'; + +import styles from './ReadOnlyDebateFeed.module.scss'; + +interface ReadOnlyDebateFeedProps { + debateFeedData: ReadOnlyDebateFeedType; +} + +const ReadOnlyDebateFeed = ({ debateFeedData }: ReadOnlyDebateFeedProps) => { + console.log(debateFeedData); + + const feedId = new URLSearchParams(useSearchParams()).get('df'); + + if (!feedId) { + return null; + } + + const { post, basicUser } = debateFeedData; + + const [{ voteCount: firstVoteCount }, { voteCount: secondVoteCount }] = + post.options; + + const totalCount = firstVoteCount + secondVoteCount; + const voteCountRatios = [ + Math.floor((firstVoteCount / totalCount) * 100), + Math.floor((secondVoteCount / totalCount) * 100), + ]; + + const notSelectedYet = ![ + post.options[0].optionId, + post.options[1].optionId, + ].includes(post.selectedOptionId); + + return ( + +
+
+ {[0, 1].map((index) => { + const isSelected = + post.selectedOptionId === post.options[index].optionId; + + return ( + + ); + })} +
+
+
+ +
+
+
+ +
+
+
+ + ); +}; + +export default ReadOnlyDebateFeed; diff --git a/src/app/(MainLayout)/components/ReadOnlyDebateFeed/index.ts b/src/app/(MainLayout)/components/ReadOnlyDebateFeed/index.ts new file mode 100644 index 0000000..47246c2 --- /dev/null +++ b/src/app/(MainLayout)/components/ReadOnlyDebateFeed/index.ts @@ -0,0 +1 @@ +export { default } from './ReadOnlyDebateFeed'; diff --git a/src/app/(MainLayout)/page.tsx b/src/app/(MainLayout)/page.tsx index b862d4b..a4dac18 100644 --- a/src/app/(MainLayout)/page.tsx +++ b/src/app/(MainLayout)/page.tsx @@ -1,15 +1,73 @@ -import FeedWrapper from '@/components/common/FeedWrapper'; +import ReadOnlyCommonFeed from './components/ReadOnlyCommonFeed'; +import ReadOnlyDebateFeed from './components/ReadOnlyDebateFeed'; import styles from './page.module.scss'; import ReadOnlyCommonFeed from './components/ReadOnlyCommonFeed'; +const MOCK_DATA_OF_COMMON_FEED = { + post: { + postType: 'BASIC' as const, + postId: 2, + content: + '테스트 내용 입니다. 테스트 내용 입니다. 테스트 내용 입니다. 테스트 내용 입니다. 테스트 내용 입니다. 테스트 내용 입니다. 테스트 내용 입니다. 테스트 내용 입니다. 테스트 내용 입니다. 테스트 내용 입니다. 테스트 내용 입니다. 테스트 내용 입니다. 테스트 내용 입니다.', + hashTagNames: ['javascript', 'typescript'], + likeCount: 0, + commentCount: 0, + createdAt: '2024-10-10T05:47:22.000+00:00', + contentImageUrls: [ + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT4vkwPhD-NHO6sV_3ailgWXjiP_WPM24J3IhkB3xZ-bQ&s', + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT4vkwPhD-NHO6sV_3ailgWXjiP_WPM24J3IhkB3xZ-bQ&s', + ], + isLike: false, + isFollow: false, + }, + basicUser: { + userId: 2, + userName: 'kimchulsu', + profileImgUrl: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT4vkwPhD-NHO6sV_3ailgWXjiP_WPM24J3IhkB3xZ-bQ&s', + }, +}; + +const MOCK_DATA_OF_DEBATE_FEED = { + post: { + postType: 'DEBATE' as const, + postId: 1, + content: '오늘의 점심 메뉴는?', + hashTagNames: ['lunch', 'menu', 'bestmenu'], + likeCount: 1_345_321, + commentCount: 154_421, + createdAt: '2024-11-02', + options: [ + { + optionId: 1, + optionContent: '오늘은 김치찌개다!', + voteCount: 162_452, + }, + { + optionId: 2, + optionContent: '오늘은 된장찌개다!', + voteCount: 31_452, + }, + ], + isFollow: false, + isLike: true, + selectedOptionId: 1, + }, + basicUser: { + userId: 2, + userName: 'hongildong', + profileImgUrl: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT4vkwPhD-NHO6sV_3ailgWXjiP_WPM24J3IhkB3xZ-bQ&s', + }, +}; + const MainPage = () => { return (
메인 - - - + +
); }; diff --git a/src/app/(MainLayout)/types/feed.ts b/src/app/(MainLayout)/types/feed.ts index c6b1ffb..5d860ab 100644 --- a/src/app/(MainLayout)/types/feed.ts +++ b/src/app/(MainLayout)/types/feed.ts @@ -15,4 +15,53 @@ type DiscussionFeedData = { type FeedPopup = 'confirm' | 'publish' | null; -export type { CommonFeedStep, CommonFeedData, DiscussionFeedData, FeedPopup }; +interface BasicUserType { + userId: number; + userName: string; + profileImgUrl: string; +} + +interface DebateOptionType { + optionId: number; + optionContent: string; + voteCount: number; +} + +interface ReadOnlyFeedType { + postId: number; + content: string; + hashTagNames: string[]; + likeCount: number; + commentCount: number; + createdAt: string; + isLike: boolean; + isFollow: boolean; +} + +interface ReadOnlyCommonFeedType { + post: { + postType: 'BASIC'; + contentImageUrls: string[]; + } & ReadOnlyFeedType; + basicUser: BasicUserType; +} + +interface ReadOnlyDebateFeedType { + post: { + postType: 'DEBATE'; + options: DebateOptionType[]; + selectedOptionId: number; + } & ReadOnlyFeedType; + basicUser: BasicUserType; +} + +export type { + CommonFeedStep, + CommonFeedData, + DiscussionFeedData, + FeedPopup, + BasicUserType, + DebateOptionType, + ReadOnlyCommonFeedType, + ReadOnlyDebateFeedType, +}; diff --git a/src/assets/icons/blue_flag_fill.svg b/src/assets/icons/blue_flag_fill.svg new file mode 100644 index 0000000..04ef2ed --- /dev/null +++ b/src/assets/icons/blue_flag_fill.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/red_flag.png b/src/assets/icons/red_flag.png new file mode 100644 index 0000000000000000000000000000000000000000..66d96a2702c6c760c268e5c75ff66ca087a9f1ff GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`j)FbFd;%$g$s6l5$8 za(7}_cTVOdki(Mh=C4pJsFk-_VSFpjO1hRb9-IofH+ZMCp82lJftwRsY}pe0Gs{g5^SUi&tz% zr{skeuW_tW$YWgkHSX9ehbwFgc5Z(B=1q)=qG(hO%;&H;1Vk9`?W^$1EcF%nXd}EA53Q|KK51E z&3<=7faAki)1`tb%zu-9?-Zu<4V!CppU=H0^iv)nTf?%bbGA& jT{xZ7GgTe~DWM4f&YFZ? literal 0 HcmV?d00001 diff --git a/src/assets/icons/red_flag_fill.svg b/src/assets/icons/red_flag_fill.svg new file mode 100644 index 0000000..3143e00 --- /dev/null +++ b/src/assets/icons/red_flag_fill.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/FeedWrapper/FeedWrapper.module.scss b/src/components/common/FeedWrapper/FeedWrapper.module.scss index 7e54913..ffd1d75 100644 --- a/src/components/common/FeedWrapper/FeedWrapper.module.scss +++ b/src/components/common/FeedWrapper/FeedWrapper.module.scss @@ -1 +1,31 @@ @use '../../../styles/helpers/index' as *; + +.container { + display: flex; + width: 100%; + height: 100%; + max-height: 800px; + overflow: hidden; + + .left { + flex: 1; + max-width: 670px; + height: 100%; + border-right: 1px solid $COLOR_GRAY_2; + } + + .right { + width: 40%; + display: flex; + flex-direction: column; + } + + .right_up { + max-height: 230px; + } + + .right_down { + height: 100%; + overflow: auto; + } +} \ No newline at end of file diff --git a/src/components/common/FeedWrapper/FeedWrapper.tsx b/src/components/common/FeedWrapper/FeedWrapper.tsx index 626b04b..1b58db6 100644 --- a/src/components/common/FeedWrapper/FeedWrapper.tsx +++ b/src/components/common/FeedWrapper/FeedWrapper.tsx @@ -11,17 +11,19 @@ interface FeedWrapperProps { modalMaxWidth?: CSSProperties['maxWidth']; modalHeight?: CSSProperties['height']; modalMaxHeight?: CSSProperties['maxHeight']; + feedIdQuery: 'cf' | 'df' | 'sf'; } const FeedWrapper = ({ + children, modalWidth = '90vw', modalMaxWidth = '1070px', modalHeight = '80vw', modalMaxHeight = '800px', - children, + feedIdQuery, }: FeedWrapperProps) => { const router = useRouter(); - const searchParams = new URLSearchParams(useSearchParams()).get('f'); + const searchParams = new URLSearchParams(useSearchParams()).get(feedIdQuery); const closeFeed = (bool: boolean) => { console.log(bool); @@ -29,6 +31,7 @@ const FeedWrapper = ({ }; if (!searchParams) { + router.push('/'); return null; }