diff --git a/apps/client/src/pages/myBookmark/MyBookmark.tsx b/apps/client/src/pages/myBookmark/MyBookmark.tsx index 8a60c5da..73d07309 100644 --- a/apps/client/src/pages/myBookmark/MyBookmark.tsx +++ b/apps/client/src/pages/myBookmark/MyBookmark.tsx @@ -4,9 +4,26 @@ import { useGetBookmarkArticles, useGetBookmarkUnreadArticles, } from './apis/queries'; +import { REMIND_MOCK_DATA } from '@pages/remind/constants'; +import CardEditModal from '@shared/components/cardEditModal/CardEditModal'; +import OptionsMenuPortal from '@shared/components/sidebar/OptionsMenuPortal'; +import { useAnchoredMenu } from '@shared/hooks/useAnchoredMenu'; +import { belowOf } from '@shared/utils/anchorPosition'; const MyBookmark = () => { const [activeBadge, setActiveBadge] = useState<'all' | 'notRead'>('all'); + const [isEditOpen, setIsEditOpen] = useState(false); + + const { + state: menu, + open: openMenu, + close: closeMenu, + style, + containerRef, + } = useAnchoredMenu((anchor) => belowOf(anchor, 8)); + + const getBookmarkTitle = (id: number | null) => + id == null ? '' : (REMIND_MOCK_DATA.find((d) => d.id === id)?.title ?? ''); const { data: readArticles } = useGetBookmarkArticles(1, 10); const { data: unreadArticles } = useGetBookmarkUnreadArticles(1, 10); @@ -18,6 +35,7 @@ const MyBookmark = () => { return (

나의 북마크

+
{ content={article.memo} // category={article.category.categoryName} date={new Date(article.createdAt).toLocaleDateString('ko-KR')} + onClick={() => {}} + onOptionsClick={(e) => + openMenu(article.articleId, e.currentTarget) + } /> ))} @@ -56,9 +78,43 @@ const MyBookmark = () => { content={article.memo} // category={article.} date={new Date(article.createdAt).toLocaleDateString('ko-KR')} + onClick={() => {}} + onOptionsClick={(e) => + openMenu(article.articleId, e.currentTarget) + } /> ))} + + { + setIsEditOpen(true); + closeMenu(); + }} + onDelete={(id) => { + console.log('delete', id); + closeMenu(); + }} + onClose={closeMenu} + />
+ + {isEditOpen && ( +
+
setIsEditOpen(false)} + /> +
+ {/* 필요하면 menu.categoryId를 모달에 전달 */} + setIsEditOpen(false)} /> +
+
+ )}
); }; diff --git a/apps/client/src/pages/remind/Remind.tsx b/apps/client/src/pages/remind/Remind.tsx index 2f3b11d1..ae4c76f6 100644 --- a/apps/client/src/pages/remind/Remind.tsx +++ b/apps/client/src/pages/remind/Remind.tsx @@ -1,9 +1,26 @@ -import { Badge, Card } from '@pinback/design-system/ui'; import { useState } from 'react'; +import { Badge, Card } from '@pinback/design-system/ui'; +import CardEditModal from '@shared/components/cardEditModal/CardEditModal'; +import OptionsMenuPortal from '@shared/components/sidebar/OptionsMenuPortal'; +import { useAnchoredMenu } from '@shared/hooks/useAnchoredMenu'; +import { belowOf } from '@shared/utils/anchorPosition'; +import { REMIND_MOCK_DATA } from './constants'; import { useGetRemindArticles } from './apis/queries'; import { formatLocalDateTime } from '@shared/utils/formatDateTime'; const Remind = () => { + const [isEditOpen, setIsEditOpen] = useState(false); + + const { + state: menu, + open: openMenu, + close: closeMenu, + style, + containerRef, + } = useAnchoredMenu((anchor) => belowOf(anchor, 8)); + + const getItemTitle = (id: number | null) => + id == null ? '' : (REMIND_MOCK_DATA.find((d) => d.id === id)?.title ?? ''); const [activeBadge, setActiveBadge] = useState('notRead'); const formattedDate = formatLocalDateTime(); @@ -46,9 +63,41 @@ const Remind = () => { content={article.memo} timeRemaining={article.remindAt} category={article.category.categoryName} + onOptionsClick={(e) => + openMenu(article.category.categoryId, e.currentTarget) + } /> ))} + + { + setIsEditOpen(true); + closeMenu(); + }} + onDelete={(id) => { + console.log('delete', id); + closeMenu(); + }} + onClose={closeMenu} + />
+ + {isEditOpen && ( +
+
setIsEditOpen(false)} + /> +
+ setIsEditOpen(false)} /> +
+
+ )}
); }; diff --git a/apps/client/src/shared/utils/anchorPosition.ts b/apps/client/src/shared/utils/anchorPosition.ts index d27b4258..be283760 100644 --- a/apps/client/src/shared/utils/anchorPosition.ts +++ b/apps/client/src/shared/utils/anchorPosition.ts @@ -2,3 +2,8 @@ export function rightOf(anchor: HTMLElement, gap = 8) { const r = anchor.getBoundingClientRect(); return { top: r.top, left: r.right + gap }; } + +export const belowOf = (anchor: HTMLElement, gap = 8) => { + const r = anchor.getBoundingClientRect(); + return { top: r.bottom + gap, left: r.left }; +}; diff --git a/packages/design-system/src/components/card/Card.tsx b/packages/design-system/src/components/card/Card.tsx index d5e4f30b..56a86eac 100644 --- a/packages/design-system/src/components/card/Card.tsx +++ b/packages/design-system/src/components/card/Card.tsx @@ -6,6 +6,8 @@ type BaseProps = { content?: string; category?: string; imageUrl?: string; + onClick?: () => void; + onOptionsClick?: (e: React.MouseEvent) => void; }; type RemindProps = BaseProps & { @@ -22,14 +24,22 @@ type BookmarkProps = BaseProps & { export type CardProps = RemindProps | BookmarkProps; -const Card = (props: CardProps) => { - const { type } = props; +const Card = ( + props: CardProps & { + onOptionsClick?: (e: React.MouseEvent) => void; + } +) => { + const { type, onOptionsClick } = props; return ( <> - {type === 'remind' && } + {type === 'remind' && ( + + )} - {type === 'bookmark' && } + {type === 'bookmark' && ( + + )} ); }; diff --git a/packages/design-system/src/components/card/MyBookmarkCard.tsx b/packages/design-system/src/components/card/MyBookmarkCard.tsx index b64e2b42..a8349525 100644 --- a/packages/design-system/src/components/card/MyBookmarkCard.tsx +++ b/packages/design-system/src/components/card/MyBookmarkCard.tsx @@ -8,6 +8,8 @@ interface MyBookmarkCardProps { category?: string; imageUrl?: string; date: string; + onClick?: () => void; + onOptionsClick?: (e: React.MouseEvent) => void; } const MyBookmarkCard = ({ @@ -16,6 +18,7 @@ const MyBookmarkCard = ({ category, imageUrl, date, + onOptionsClick, }: MyBookmarkCardProps) => { return ( @@ -38,6 +41,7 @@ const MyBookmarkCard = ({ type="button" aria-label="카테고리 상세" className="cursor-pointer self-start" + onClick={(e) => onOptionsClick?.(e)} > diff --git a/packages/design-system/src/components/card/RemindCard.tsx b/packages/design-system/src/components/card/RemindCard.tsx index f1f53528..a53afb43 100644 --- a/packages/design-system/src/components/card/RemindCard.tsx +++ b/packages/design-system/src/components/card/RemindCard.tsx @@ -8,6 +8,8 @@ interface RemindCardProps { category?: string; imageUrl?: string; timeRemaining: string; + onClick?: () => void; + onOptionsClick?: (e: React.MouseEvent) => void; } const RemindCard = ({ @@ -16,6 +18,7 @@ const RemindCard = ({ category, imageUrl, timeRemaining, + onOptionsClick, }: RemindCardProps) => { return ( @@ -46,6 +49,7 @@ const RemindCard = ({ type="button" aria-label="카테고리 상세" className="cursor-pointer self-start" + onClick={(e) => onOptionsClick?.(e)} > @@ -54,7 +58,6 @@ const RemindCard = ({ {content}

- {/* TODO: 카테고리 컴포넌트로 교체 */} {category}