diff --git a/src/pages/mypage/index.tsx b/src/pages/mypage/index.tsx
new file mode 100644
index 00000000..69b8c83e
--- /dev/null
+++ b/src/pages/mypage/index.tsx
@@ -0,0 +1,5 @@
+import MyPageLayout from '@/pageLayout/MypageLayout/MyPageLayout';
+
+export default function mypage() {
+ return
;
+}
diff --git a/src/schema/user.ts b/src/schema/user.ts
index 6cc1cf00..45565a5e 100644
--- a/src/schema/user.ts
+++ b/src/schema/user.ts
@@ -30,9 +30,16 @@ export const PostPresignedUrlResponse = z.object({
url: z.string().url(),
});
+export const GetMyContentCount = z.object({
+ epigramCount: z.number(),
+ commentCount: z.number(),
+});
+
export type GetUserResponseType = z.infer
;
export type GetUserRequestType = z.infer;
export type PatchMeRequestType = z.infer;
export type PostPresignedUrlRequestType = z.infer;
export type PostPresignedUrlResponseType = z.infer;
+
+export type GetMyContentCountType = z.infer;
diff --git a/src/styles/globals.css b/src/styles/globals.css
index 2ff60784..8d264ff4 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -114,6 +114,14 @@
font-display: swap;
}
+@font-face {
+ font-family: 'Montserrat';
+ font-style: normal;
+ font-weight: 100 900;
+ font-display: swap;
+ src: url(https://fonts.gstatic.com/s/montserrat/v26/JTUSjIg1_i6t8kCHKm459Wlhyw.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
:root {
--max-width: 1100px;
diff --git a/src/types/Header.ts b/src/types/Header.ts
new file mode 100644
index 00000000..a75d1fce
--- /dev/null
+++ b/src/types/Header.ts
@@ -0,0 +1,12 @@
+export interface HeaderProps {
+ icon: 'back' | 'search' | '';
+ routerPage: string;
+ isLogo: boolean;
+ insteadOfLogo: string;
+ isProfileIcon: boolean;
+ isShareIcon: boolean;
+ isButton: boolean;
+ textInButton: string;
+ disabled: boolean;
+ onClick: (e: React.MouseEvent) => void;
+}
diff --git a/src/user/ui-content/MyComment.tsx b/src/user/ui-content/MyComment.tsx
new file mode 100644
index 00000000..9f015575
--- /dev/null
+++ b/src/user/ui-content/MyComment.tsx
@@ -0,0 +1,154 @@
+import React, { useState } from 'react';
+import Image from 'next/image';
+import { useRouter } from 'next/router';
+import { textSizeStyles, gapStyles, paddingStyles, contentWidthStyles } from '@/styles/CommentCardStyles';
+import { CommentType } from '@/schema/comment';
+import { Button } from '@/components/ui/button';
+import DeleteAlertModal from '@/components/epigram/DeleteAlertModal';
+import CommentTextarea from '@/components/epigram/Comment/CommentTextarea';
+import NONE_EPI from '../../../public/none-epi.svg';
+
+const sizeStyles = {
+ sm: 'w-[360px]',
+ md: 'md:w-[384px]',
+ lg: 'lg:w-[640px]',
+};
+
+interface MyCommentProps {
+ comments: CommentType[];
+ totalCount: number;
+ onMoreEpigramLoad: () => void;
+ onDeleteComment: (commentId: number) => void;
+ onEditComment: () => void;
+}
+
+function MyComment({ comments, totalCount, onMoreEpigramLoad, onDeleteComment, onEditComment }: MyCommentProps) {
+ const router = useRouter();
+ const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
+ const [selectedCommentId, setSelectedCommentId] = useState(null);
+
+ // NOTE: 현재 수정 중인 댓글의 ID 상태
+ const [editingCommentId, setEditingCommentId] = useState(null);
+
+ const handleMoveToMain = () => {
+ router.push('/epigrams');
+ };
+
+ const handleDeleteComment = () => {
+ if (selectedCommentId !== null) {
+ onDeleteComment(selectedCommentId);
+ setIsDeleteModalOpen(false);
+ }
+ };
+
+ const handleEditComment = (comment: CommentType) => {
+ setEditingCommentId(comment.id);
+ };
+
+ const handleEditComplete = () => {
+ setEditingCommentId(null);
+ onEditComment();
+ };
+
+ // 에피그램 상세 페이지 이동
+ const handleCommentClick = (epigramId: number) => {
+ router.push(`/epigrams/${epigramId}`);
+ };
+
+ const handleKeyDown = (event: React.KeyboardEvent, epigramId: number) => {
+ if (event.key === 'Enter' || event.key === ' ') {
+ handleCommentClick(epigramId);
+ }
+ };
+
+ return totalCount > 0 ? (
+
+ {comments.map((comment) => {
+ const formattedDate = new Date(comment.createdAt).toLocaleString();
+
+ return (
+
+
+
+ {editingCommentId === comment.id ? (
+
+
+
+ ) : (
+
+
+
+
+ {comment.writer.nickname}
+
+
{formattedDate}
+
+
+
+
+
+
+
handleCommentClick(comment.epigramId)}
+ onKeyDown={(event) => handleKeyDown(event, comment.epigramId)}
+ role='button'
+ tabIndex={0}
+ className={`w-full text-zinc-800 font-normal font-pretendard ${textSizeStyles.sm.content} ${textSizeStyles.md.content} ${textSizeStyles.lg.content} ${contentWidthStyles.sm} ${contentWidthStyles.md} ${contentWidthStyles.lg}`}
+ >
+ {comment.content}
+
+
+ )}
+
+
+ );
+ })}
+ {totalCount > comments.length && (
+
+
+
+ )}
+
+
+ ) : (
+
+
+
+
+
아직 작성한 댓글이 없어요!
+
댓글을 달고 다른 사람들과 교류해보세요.
+
+
+
+
+ );
+}
+
+export default MyComment;
diff --git a/src/user/ui-content/MyEpigrams.tsx b/src/user/ui-content/MyEpigrams.tsx
index f5a7d45e..6aad1ea8 100644
--- a/src/user/ui-content/MyEpigrams.tsx
+++ b/src/user/ui-content/MyEpigrams.tsx
@@ -37,7 +37,7 @@ function MyEpigrams({ epigrams, totalCount, onMoreEpigramLoad }: MyEpigramProps)
// 에피그램 상세 페이지 이동
const handleEpigramClick = (epigramId: number) => {
- router.push(`/epigram/${epigramId}`);
+ router.push(`/epigrams/${epigramId}`);
};
const handleKeyDown = (event: React.KeyboardEvent, epigramId: number) => {
diff --git a/tailwind.config.js b/tailwind.config.js
index 25a4545d..e6d59f44 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -6,6 +6,7 @@ module.exports = {
fontFamily: {
pretendard: ['Pretendard'],
iropkeBatang: ['IropkeBatang'],
+ montserrat: ['Montserrat']
},
colors: {
'black-100': '#787878',
@@ -51,14 +52,14 @@ module.exports = {
'sub-gray_3': '#EFF3F8',
},
screens: {
- sm: '640px',
- md: '768px',
- lg: '1024px',
- xl: '1280px',
+ 'sm': '640px',
+ 'md': '768px',
+ 'lg': '1024px',
+ 'xl': '1280px',
'2xl': '1536px',
},
backgroundImage: {
- stripes: 'repeating-linear-gradient(to bottom, #ffffff, #ffffff 23px, #e5e7eb 23px, #e5e7eb 24px)',
+ 'stripes': 'repeating-linear-gradient(to bottom, #ffffff, #ffffff 23px, #e5e7eb 23px, #e5e7eb 24px)',
},
},
},