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}