Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions apps/client/src/pages/dashboard/apis/query/article.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
putArticle,
} from '@/pages/dashboard/apis/axios/article';
import { PutCategoryRequest } from '@/pages/dashboard/types/api';
import { queryClient } from '@/shared';
import { useMutation, useQuery } from '@tanstack/react-query';
import { getModalCategories } from '../axios';

Expand All @@ -16,6 +17,12 @@ export const usePutArticle = (articleId: number, data: PutCategoryRequest) => {
export const useDeleteArticle = (articleId: number | null) => {
return useMutation({
mutationFn: () => deleteArticle(articleId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['unreadArticles'] });
queryClient.invalidateQueries({ queryKey: ['dashboardCategories'] });
queryClient.invalidateQueries({ queryKey: ['categoryArticles'] });
queryClient.invalidateQueries({ queryKey: ['dailyReminderArticles'] });
},
});
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { memo, type KeyboardEvent } from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@shared/utils/cn';
import type { CategoryProps } from '@pages/dashboard/types/components';
import { cn } from '@shared/utils/cn';
import { cva, type VariantProps } from 'class-variance-authority';
import { memo, type KeyboardEvent } from 'react';

const categoryVariants = cva(
'inline-flex justify-center items-center rounded-[50px] border cursor-pointer transition-colors',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { fetchOGData } from '@/shared/utils/ogImage';
import icDetails from '@assets/icons/ui/details.svg';
import emptyMemo from '@assets/illustrations/empty-states/memo.svg';
import Thumbnail from '@pages/dashboard/components/ui/cards/Thumbnail';
import { cn } from '@shared/utils/cn';
import { CARD_CLASSES } from '@shared/utils/styleUtils';
import { cva, type VariantProps } from 'class-variance-authority';
import { useEffect, useState } from 'react';

const CARD_DIMENSIONS = {
width: 'w-[28.3rem]',
Expand Down Expand Up @@ -53,22 +55,38 @@ interface BookmarkCardProps extends BookmarkCardVariants {

const BookmarkCard = ({
memo,
title,
url,
isRead = false,
handlePopUpOpen,
onDotClick,
}: BookmarkCardProps) => {
const [ogTitle, setOgTitle] = useState<string>('');
const [ogImage, setOgImage] = useState<string>('');

useEffect(() => {
if (!url) {
return;
}

const getOGData = async () => {
const og = await fetchOGData(url);
setOgTitle(og.title || '');
setOgImage(og.image || '');
};

getOGData();
}, [url]);
Comment on lines +63 to +78
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

OG 데이터 페칭에 에러 핸들링과 로딩 상태를 추가하세요.

현재 구현에서는 fetchOGData 실패 시 에러 처리가 없으며, 로딩 상태도 표시하지 않습니다. 사용자 경험을 위해 개선이 필요합니다.

const BookmarkCard = ({
  memo,
  url,
  isRead = false,
  handlePopUpOpen,
  onDotClick,
}: BookmarkCardProps) => {
  const [ogTitle, setOgTitle] = useState<string>('');
  const [ogImage, setOgImage] = useState<string>('');
+  const [isLoading, setIsLoading] = useState(false);
+  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!url) {
      return;
    }

    const getOGData = async () => {
+      setIsLoading(true);
+      setError(null);
      try {
        const og = await fetchOGData(url);
        setOgTitle(og.title || '');
        setOgImage(og.image || '');
+      } catch (err) {
+        setError('OG 데이터를 불러올 수 없습니다');
+        console.error('OG 데이터 페칭 실패:', err);
+      } finally {
+        setIsLoading(false);
      }
    };

    getOGData();
  }, [url]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [ogTitle, setOgTitle] = useState<string>('');
const [ogImage, setOgImage] = useState<string>('');
useEffect(() => {
if (!url) {
return;
}
const getOGData = async () => {
const og = await fetchOGData(url);
setOgTitle(og.title || '');
setOgImage(og.image || '');
};
getOGData();
}, [url]);
const BookmarkCard = ({
memo,
url,
isRead = false,
handlePopUpOpen,
onDotClick,
}: BookmarkCardProps) => {
const [ogTitle, setOgTitle] = useState<string>('');
const [ogImage, setOgImage] = useState<string>('');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (!url) {
return;
}
const getOGData = async () => {
setIsLoading(true);
setError(null);
try {
const og = await fetchOGData(url);
setOgTitle(og.title || '');
setOgImage(og.image || '');
} catch (err) {
setError('OG 데이터를 불러올 수 없습니다');
console.error('OG 데이터 페칭 실패:', err);
} finally {
setIsLoading(false);
}
};
getOGData();
}, [url]);
// ...rest of component rendering (e.g., show loader or error if needed)
};
🤖 Prompt for AI Agents
In apps/client/src/pages/dashboard/components/ui/cards/BookmarkCard.tsx around
lines 63 to 78, the useEffect hook fetching OG data lacks error handling and
loading state management. Add a loading state variable to indicate when data is
being fetched, set it to true before calling fetchOGData and false after
completion. Wrap the fetchOGData call in a try-catch block to catch and handle
any errors, such as logging or setting error state, to prevent unhandled promise
rejections and improve user experience.


return (
<div className={cn(bookmarkCardVariants({ isRead }))}>
<div className="mb-[1.8rem] flex w-full items-center justify-between">
<div className="inline-flex w-64 flex-col items-start justify-start gap-4">
<div className={CARD_CLASSES.thumbnail}>
<Thumbnail alt="북마크 썸네일" url={url} />
<Thumbnail alt="북마크 썸네일" url={url} imageUrl={ogImage} />
</div>

<div>
<div className={CARD_CLASSES.title}>{title}</div>
<div className={CARD_CLASSES.title}>{ogTitle}</div>
<div className={cn(memoVariants({ isRead }))}>
{memo ? (
<div className={CARD_CLASSES.memoInner}>{memo}</div>
Expand Down
120 changes: 66 additions & 54 deletions apps/client/src/pages/dashboard/components/ui/cards/Thumbnail.tsx
Original file line number Diff line number Diff line change
@@ -1,71 +1,83 @@
import { useState, useEffect, useCallback } from 'react';
import emptyThumbnail from '@assets/illustrations/empty-states/thumbnail.svg';
import type { ThumbnailProps } from '@pages/dashboard/types/components';
import { cn } from '@shared/utils/cn';
import { generateThumbnail } from '@pages/dashboard/utils/thumbnail';
import { useState } from 'react';

interface ThumbnailState {
url: string | null;
isLoading: boolean;
hasError: boolean;
imageUrl?: string;
}
Comment on lines 5 to 10
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

ThumbnailState 인터페이스를 정리하세요.

imageUrl 필드가 추가되었지만, 사용되지 않는 필드들이 남아있습니다. 현재 구현에서는 url, isLoading, hasError 필드가 더 이상 의미가 없습니다.

interface ThumbnailState {
-  url: string | null;
-  isLoading: boolean;
  hasError: boolean;
-  imageUrl?: string;
}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/client/src/pages/dashboard/components/ui/cards/Thumbnail.tsx between
lines 5 and 10, the ThumbnailState interface includes unused fields url,
isLoading, and hasError, while imageUrl is added but other fields are obsolete.
Remove the unused fields url, isLoading, and hasError from the interface and
keep only the imageUrl field to reflect the current implementation accurately.


const Thumbnail = ({
alt,
className = '',
url,
imageUrl,
}: Omit<ThumbnailProps, 'src'> & { url?: string }) => {
const [state, setState] = useState<ThumbnailState>({
url: null,
isLoading: false,
hasError: false,
});
Comment on lines 17 to 21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

상태 초기화를 단순화하세요.

현재 구현에서는 isLoading이 항상 false이고 url이 사용되지 않으므로 상태를 단순화할 수 있습니다.

const [state, setState] = useState<ThumbnailState>({
-  url: null,
-  isLoading: false,
  hasError: false,
});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [state, setState] = useState<ThumbnailState>({
url: null,
isLoading: false,
hasError: false,
});
const [state, setState] = useState<ThumbnailState>({
hasError: false,
});
🤖 Prompt for AI Agents
In apps/client/src/pages/dashboard/components/ui/cards/Thumbnail.tsx around
lines 17 to 21, the state initialization includes properties isLoading and url
which are either always false or unused. Simplify the state by removing these
unnecessary properties and keep only the relevant state fields that are actively
used in the component.


const generateThumbnailFromUrl = useCallback(async (url: string) => {
if (!url) {
return;
}
const shouldShowSkeleton = state.isLoading || !imageUrl;

setState((prev) => ({
...prev,
isLoading: true,
hasError: false,
}));
if (shouldShowSkeleton) {
return (
<div
className={cn(
'flex h-full w-full animate-pulse items-center justify-center rounded bg-gray-200',
className
)}
></div>
);
}
Comment on lines +23 to +34
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

스켈레톤 로딩 로직을 수정하세요.

isLoading이 항상 false이므로 스켈레톤은 imageUrl이 없을 때만 표시됩니다. 로딩 상태가 필요없다면 조건을 더 명확하게 만드세요.

-const shouldShowSkeleton = state.isLoading || !imageUrl;
+const shouldShowSkeleton = !imageUrl;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const shouldShowSkeleton = state.isLoading || !imageUrl;
setState((prev) => ({
...prev,
isLoading: true,
hasError: false,
}));
if (shouldShowSkeleton) {
return (
<div
className={cn(
'flex h-full w-full animate-pulse items-center justify-center rounded bg-gray-200',
className
)}
></div>
);
}
const shouldShowSkeleton = !imageUrl;
if (shouldShowSkeleton) {
return (
<div
className={cn(
'flex h-full w-full animate-pulse items-center justify-center rounded bg-gray-200',
className
)}
></div>
);
}
🤖 Prompt for AI Agents
In apps/client/src/pages/dashboard/components/ui/cards/Thumbnail.tsx between
lines 23 and 34, the skeleton loading logic uses state.isLoading which is always
false, causing the skeleton to show only when imageUrl is missing. To fix this,
clarify the condition by either removing the isLoading check if loading state is
unnecessary or ensure isLoading reflects the actual loading state. Update the
shouldShowSkeleton condition accordingly to accurately control when the skeleton
is displayed.


// const generateThumbnailFromUrl = useCallback(async (url: string) => {
// if (!url) {
// return;
// }

// setState((prev) => ({
// ...prev,
// isLoading: true,
// hasError: false,
// }));

try {
const thumbnail = await generateThumbnail(url);
// try {
// const thumbnail = await generateThumbnail(url);

if (thumbnail) {
setState((prev) => ({
...prev,
url: thumbnail,
hasError: false,
isLoading: false,
}));
} else {
setState((prev) => ({
...prev,
url: null,
hasError: false,
isLoading: false,
}));
}
} catch (error) {
console.error('썸네일 생성 실패:', { url, error });
// if (thumbnail) {
// setState((prev) => ({
// ...prev,
// url: thumbnail,
// hasError: false,
// isLoading: false,
// }));
// } else {
// setState((prev) => ({
// ...prev,
// url: null,
// hasError: false,
// isLoading: false,
// }));
// }
// } catch (error) {
// console.error('썸네일 생성 실패:', { url, error });

setState((prev) => ({
...prev,
hasError: false,
isLoading: false,
}));
}
}, []);
// setState((prev) => ({
// ...prev,
// hasError: false,
// isLoading: false,
// }));
// }
// }, []);
Comment on lines +36 to +74
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

주석 처리된 코드를 제거하세요.

더 이상 사용되지 않는 썸네일 생성 로직을 완전히 제거하는 것이 좋습니다. 코드베이스를 깔끔하게 유지하기 위해 주석 처리된 코드를 삭제하세요.

-// const generateThumbnailFromUrl = useCallback(async (url: string) => {
-//   if (!url) {
-//     return;
-//   }
-//   ... (전체 주석 처리된 코드 블록 제거)
-// }, []);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// const generateThumbnailFromUrl = useCallback(async (url: string) => {
// if (!url) {
// return;
// }
// setState((prev) => ({
// ...prev,
// isLoading: true,
// hasError: false,
// }));
try {
const thumbnail = await generateThumbnail(url);
// try {
// const thumbnail = await generateThumbnail(url);
if (thumbnail) {
setState((prev) => ({
...prev,
url: thumbnail,
hasError: false,
isLoading: false,
}));
} else {
setState((prev) => ({
...prev,
url: null,
hasError: false,
isLoading: false,
}));
}
} catch (error) {
console.error('썸네일 생성 실패:', { url, error });
// if (thumbnail) {
// setState((prev) => ({
// ...prev,
// url: thumbnail,
// hasError: false,
// isLoading: false,
// }));
// } else {
// setState((prev) => ({
// ...prev,
// url: null,
// hasError: false,
// isLoading: false,
// }));
// }
// } catch (error) {
// console.error('썸네일 생성 실패:', { url, error });
setState((prev) => ({
...prev,
hasError: false,
isLoading: false,
}));
}
}, []);
// setState((prev) => ({
// ...prev,
// hasError: false,
// isLoading: false,
// }));
// }
// }, []);
🤖 Prompt for AI Agents
In apps/client/src/pages/dashboard/components/ui/cards/Thumbnail.tsx between
lines 36 and 74, remove the entire commented-out generateThumbnailFromUrl
function and its related code since it is no longer used. This will clean up the
codebase by eliminating dead code.


useEffect(() => {
if (url) {
generateThumbnailFromUrl(url);
}
}, [url, generateThumbnailFromUrl]);
// useEffect(() => {
// if (url) {
// generateThumbnailFromUrl(url);
// }
// }, [url, generateThumbnailFromUrl]);
Comment on lines +76 to +80
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

주석 처리된 useEffect를 제거하세요.

사용되지 않는 useEffect 훅을 제거하여 코드를 정리하세요.

-// useEffect(() => {
-//   if (url) {
-//     generateThumbnailFromUrl(url);
-//   }
-// }, [url, generateThumbnailFromUrl]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// useEffect(() => {
// if (url) {
// generateThumbnailFromUrl(url);
// }
// }, [url, generateThumbnailFromUrl]);
🤖 Prompt for AI Agents
In apps/client/src/pages/dashboard/components/ui/cards/Thumbnail.tsx around
lines 76 to 80, there is a useEffect hook that is commented out and not used.
Remove this commented-out useEffect code entirely to clean up and simplify the
codebase.


if (state.isLoading) {
return (
Expand All @@ -80,19 +92,19 @@ const Thumbnail = ({
);
}

if (state.hasError || !state.url) {
return (
<img
src={emptyThumbnail}
alt="썸네일이 없어요"
className={cn('h-full w-full object-contain', className)}
/>
);
}
// if (state.hasError || !state.url) {
// return (
// <img
// src={emptyThumbnail}
// alt="썸네일이 없어요"
// className={cn('h-full w-full object-contain', className)}
// />
// );
// }
Comment on lines +95 to +103
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

에러 폴백 UI를 복원하세요.

주석 처리된 에러 처리 로직을 복원하여 이미지 로드 실패 시 적절한 폴백을 제공하세요.

-// if (state.hasError || !state.url) {
-//   return (
-//     <img
-//       src={emptyThumbnail}
-//       alt="썸네일이 없어요"
-//       className={cn('h-full w-full object-contain', className)}
-//     />
-//   );
-// }
+if (state.hasError) {
+  return (
+    <img
+      src={emptyThumbnail}
+      alt="썸네일이 없어요"
+      className={cn('h-full w-full object-contain', className)}
+    />
+  );
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// if (state.hasError || !state.url) {
// return (
// <img
// src={emptyThumbnail}
// alt="썸네일이 없어요"
// className={cn('h-full w-full object-contain', className)}
// />
// );
// }
if (state.hasError) {
return (
<img
src={emptyThumbnail}
alt="썸네일이 없어요"
className={cn('h-full w-full object-contain', className)}
/>
);
}
🤖 Prompt for AI Agents
In apps/client/src/pages/dashboard/components/ui/cards/Thumbnail.tsx around
lines 95 to 103, the error fallback UI code is commented out, which disables the
fallback image display on error or missing URL. Restore the commented-out block
so that when state.hasError is true or state.url is falsy, the component returns
the fallback img element with the emptyThumbnail source and appropriate alt text
and className.


return (
<img
src={state.url}
src={imageUrl}
alt={alt || '썸네일'}
className={cn('h-full w-full object-cover', className)}
onError={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ const Modal = ({ isOpen, onClose, children, className = '' }: ModalProps) => {
}
};

if (isOpen) {
document.addEventListener('keydown', handleEscapeKey);
document.body.style.overflow = 'hidden';
}
// if (isOpen) {
// document.addEventListener('keydown', handleEscapeKey);
// document.body.style.overflow = 'hidden';
// }
Comment on lines +12 to +15
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

useEffect의 비대칭 동작을 수정하세요.

이벤트 리스너 추가 로직은 주석 처리되어 있지만, cleanup 함수에서는 여전히 이벤트 리스너를 제거하고 있습니다. 이는 추가되지 않은 이벤트 리스너를 제거하려고 시도하므로 비논리적입니다.

다음 중 하나의 방법으로 수정하세요:

방법 1: 조건부 로직을 완전히 제거

  useEffect(() => {
-    const handleEscapeKey = (event: KeyboardEvent) => {
-      if (event.key === 'Escape') {
-        onClose();
-      }
-    };
-
-    // if (isOpen) {
-    //   document.addEventListener('keydown', handleEscapeKey);
-    //   document.body.style.overflow = 'hidden';
-    // }
-
-    return () => {
-      document.removeEventListener('keydown', handleEscapeKey);
-      document.body.style.overflow = 'unset';
-    };
+    // 모달 기능이 필요하지 않은 경우 이 useEffect를 완전히 제거
   }, [isOpen, onClose]);

방법 2: 조건부 로직을 올바르게 구현

  useEffect(() => {
    const handleEscapeKey = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        onClose();
      }
    };

-    // if (isOpen) {
-    //   document.addEventListener('keydown', handleEscapeKey);
-    //   document.body.style.overflow = 'hidden';
-    // }
+    if (isOpen) {
+      document.addEventListener('keydown', handleEscapeKey);
+      document.body.style.overflow = 'hidden';
+    }

    return () => {
-      document.removeEventListener('keydown', handleEscapeKey);
-      document.body.style.overflow = 'unset';
+      if (isOpen) {
+        document.removeEventListener('keydown', handleEscapeKey);
+        document.body.style.overflow = 'unset';
+      }
    };
   }, [isOpen, onClose]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// if (isOpen) {
// document.addEventListener('keydown', handleEscapeKey);
// document.body.style.overflow = 'hidden';
// }
useEffect(() => {
const handleEscapeKey = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
onClose();
}
};
if (isOpen) {
document.addEventListener('keydown', handleEscapeKey);
document.body.style.overflow = 'hidden';
}
return () => {
if (isOpen) {
document.removeEventListener('keydown', handleEscapeKey);
document.body.style.overflow = 'unset';
}
};
}, [isOpen, onClose]);
🤖 Prompt for AI Agents
In apps/client/src/pages/dashboard/components/ui/feedback/Modal.tsx around lines
12 to 15, the useEffect hook has commented out the event listener addition but
still attempts to remove the listener in the cleanup, causing asymmetry. Fix
this by either fully removing both the addition and removal of the event
listener or by properly implementing the conditional logic to add the event
listener when isOpen is true and remove it in the cleanup accordingly.


return () => {
document.removeEventListener('keydown', handleEscapeKey);
Expand Down
10 changes: 3 additions & 7 deletions apps/client/src/pages/dashboard/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,6 @@ const Dashboard = () => {
// 아티클 조회
const currentArticles = getCurrentArticles();

useEffect(() => {
console.log('선택 카테고리:', activeCategory);
}, [activeCategory]);

const getCurrentTotalCount = () => {
if (categoryArticlesData?.data?.totalArticle !== undefined) {
return categoryArticlesData.data.totalArticle;
Expand Down Expand Up @@ -145,11 +141,11 @@ const Dashboard = () => {
<div className="mt-[7.7rem] px-[11.9rem] pb-[3.6rem] pr-[12rem]">
{hasDailyReminders && (
<DailyReminderSection
articles={dailyReminderData?.data?.articles} // 1
articles={dailyReminderData?.data?.articles}
onArticleRead={handleArticleRead}
isLoading={isLoadingDailyReminder}
handlePopUpOpen={onPopUpOpen}
handleArticleDotClick={handleArticleDotClick} //d
handleArticleDotClick={handleArticleDotClick}
/>
)}
<div className={getBookmarkSectionMargin()}>
Expand All @@ -166,7 +162,7 @@ const Dashboard = () => {
totalArticleCount={currentTotalCount}
categoryTotalCounts={categoryTotalCounts}
handlePopUpOpen={onPopUpOpen}
handleArticleDotClick={handleArticleDotClick} // d
handleArticleDotClick={handleArticleDotClick}
/>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions apps/client/src/pages/dashboard/types/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export interface ThumbnailProps {
src?: string;
alt?: string;
className?: string;
imageUrl?: string;
}

export interface ModalProps {
Expand Down
4 changes: 1 addition & 3 deletions apps/client/src/shared/components/ui/modalPop/ModalPop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,7 @@ const ModalPop = ({ onClose, onDelete, selectedArticleId }: ModalPopProps) => {
date: formattedDate,
time: formattedTime,
}));
const og = await fetchOGData(
'https://www.notion.so/Client-214688191681801ab171e8cf9ab3661d'
);
const og = await fetchOGData(articleDetail.url);
setTitle(og.title || '');
setDescription(og.siteName || '');
setImage(og.image || '');
Expand Down